📄 tda8007.c
字号:
// Start timer
dssc_writeregister(TOC,0x65);
}
}
}
// Read Timer status
if (USRval & USR_TOL3_MASK)
{
#if DEBUG > 0
printf("Character waiting timeout\n");
#endif
dssc_powerdown();
return ERR_POWERUP_ATR_TIMEOUT;
}
if ((mode == POWERUP_EMV) && (USRval & USR_TOL1_MASK))
{
// If 192 ETU rollover, increment total count
etucount++;
// If we exceed 192 * 100 or 19200 etu, we fail as the whole ATR has not come
if (etucount > 100)
{
#if DEBUG > 0
printf("ATR waiting timeout\n");
#endif
dssc_powerdown();
return ERR_POWERUP_ATR_TIMEOUT;
}
}
}
// If we are in T=1 protocol, we get a LRC (xor checksum) at the end
if (T==1)
{
if (check != 0)
{
#if DEBUG > 0
printf("LRC failed: %02bx\n",check);
#endif
dssc_powerdown();
return ERR_POWERUP_ATR_CRC_FAILURE;
}
}
// Set ATR length for the ATR received
ATRLength[currentSlot] = index;
// Set T protocol mode
TMode[currentSlot] = T;
// Set the 8007 UCR1.PROT mode according to T value
val = dssc_readregister(UCR1);
if (T == 0)
dssc_writeregister(UCR1,val & ~UCR1_PROT_MASK);
else
dssc_writeregister(UCR1,val | UCR1_PROT_MASK);
// Set extra guard time if present in TC1, else use guard time of 0
if (lastATR[currentSlot].TC[1] != -1)
dssc_writeregister(GTR,lastATR[currentSlot].TC[1]);
else
dssc_writeregister(GTR,0x00);
// Set the EDC type (either LRC or CRC)
// FIXME: In EMV mode, if TC3 comes by and is not zero, we should bail out!!!!
EDCtype[currentSlot] = EDC_TYPE_LRC; // Default to LRC if not told otherwise.
for (i = 3;i < 8;i++)
{
if (lastATR[currentSlot].TC[3] != -1)
{
EDCtype[currentSlot] = (lastATR[currentSlot].TC[3] & 0x01)?EDC_TYPE_CRC:EDC_TYPE_LRC;
}
}
// Set IFSC (max segment size of card) if TA3 present (only used for T=1 protocol)
// FIXME: Using TA3 this way may only be correct for EMV, not ISO7816
if (lastATR[currentSlot].TA[3] != -1)
{
val = lastATR[currentSlot].TA[3];
if ((val < 0x10) || (val == 0xFF))
{
// FIXME: Should we power down here? It is an EMV violation
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
IFSC[currentSlot] = val;
}
else
IFSC[currentSlot] = 0x20; // Default for IFSC is 0x20 according to EMV 4.1 8.3.3.9 and ISO7816 9.5.2.1
// Set WWT if present in TC2 (only used for T=0), ISO7816 8.2
if (lastATR[currentSlot].TC[2] != -1)
WWT[currentSlot] = lastATR[currentSlot].TC[2] * 960;
else
WWT[currentSlot] = 960 * 10;
#if DEBUG > 1
printf("WWT: %ld\n",WWT[currentSlot]);
#endif
if (mode == POWERUP_EMV)
{
if (lastATR[currentSlot].TB[3] == -1)
{
// FIXME: Should we power down here? It is an EMV violation
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
else
{
val = lastATR[currentSlot].TB[i] & 0x0F;
// Fail if CWI is out of range
if (val > 5)
{
// FIXME: Should we power down here? It is an EMV violation
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
// Fail if BWI is out of range
if (val > 4)
{
// FIXME: Should we power down here? It is an EMV violation
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
}
}
// Set default values for CWT and BWT, ISO7816 9.5.3.1 and 9.5.3.2
CWT[currentSlot] = 11 + (1 << 13);
BWT[currentSlot] = 11 + (1 << 4) * 960;
for (i = 3;i < 8;i++)
{
// Set CWT and BWT if present in TBi
// FIXME: Check this algorithm again!
if (lastATR[currentSlot].TB[i] != -1)
{
val = lastATR[currentSlot].TB[i] & 0x0F;
CWT[currentSlot] = 11 + (1 << val);
val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
if (val > 9)
{
// FIXME: Should we power down here? It is an ISO7816 violation.
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
BWT[currentSlot] = 11 + (1 << val) * 960;
break;
}
}
#if DEBUG > 1
printf("CWT: %ld\n",CWT[currentSlot]);
printf("BWT: %ld\n",BWT[currentSlot]);
#endif
return 0;
}
int16_t dssc_powerdown()
{
uint8_t val;
// Power down the card
val = dssc_readregister(PCR);
dssc_writeregister(PCR,val & ~PCR_START_MASK);
return 0;
}
int16_t dssc_selectcard(uint8_t slot)
{
uint8_t val;
val = dssc_readregister(CSR);
switch (slot)
{
case 1:
// Select appropriate smartcard and clear other card selects
dssc_writeregister(CSR,val & ~(CSR_SC3_MASK|CSR_SC2_MASK) | CSR_SC1_MASK);
break;
case 2:
// Select appropriate smartcard and clear other card selects
dssc_writeregister(CSR,val & ~(CSR_SC3_MASK|CSR_SC1_MASK) | CSR_SC2_MASK);
break;
case 3:
// Select appropriate smartcard and clear other card selects
dssc_writeregister(CSR,val & ~(CSR_SC2_MASK|CSR_SC1_MASK) | CSR_SC3_MASK);
break;
default:
return ERR_INVALID_SLOT;
}
// Set global slot identifier value
currentSlot = slot-1;
if ( DEBUG > 2)
printf("card selected: %d\n", currentSlot);
return 0;
}
int16_t dssc_checkpresence(uint8_t slot)
{
uint8_t val;
val = dssc_readregister(MSR);
switch(slot)
{
case 1:
if (val & MSR_PR1_MASK) return 1;
break;
case 2:
if (val & MSR_PR2_MASK) return 1;
break;
default:
return ERR_INVALID_SLOT;
break;
}
return 0;
}
/*
Library initialization
*/
int16_t dssc_init()
{
uint8_t val;
// Reset the UART
dssc_writeregister(CSR,0x00);
// Select smart card slot 1
dssc_writeregister(CSR,CSR_SC1_MASK);
// Make sure card is powered down
val = dssc_readregister(PCR);
dssc_writeregister(PCR,val & ~PCR_START_MASK);
// Select smart card slot 2
dssc_writeregister(CSR,CSR_SC2_MASK);
// Make sure card is powered down
val = dssc_readregister(PCR);
dssc_writeregister(PCR,val & ~PCR_START_MASK);
// Select smart card slot 3
dssc_writeregister(CSR,CSR_SC3_MASK);
// Deselect all cards
dssc_writeregister(CSR,0x00);
return 0;
}
int16_t dssc_getATRbuffer(uint8_t *buff, int16_t length)
{
memcpy(buff,workingBuffer,(length<ATRLength[currentSlot])?length:ATRLength[currentSlot]);
return ATRLength[currentSlot];
}
void dssc_getATR(struct ATR *userATR)
{
memcpy(userATR,&lastATR[currentSlot],sizeof(struct ATR));
}
#pragma REGPARMS
uint8_t dssc_readregister(uint8_t address)
{
idata uint8_t rAddress, toReturn;
#ifdef DEBUG_CRED
idata uint8_t count = 0;
#endif
rAddress = address;
//ds5250 DMOS |= 0x01;
RPCTL |= 0x20; //the MOVX route access the expend port(P0,P2);
// P3 &= 0xEF; // Happy CS for 8007 on Ramit Board
P1 &= 0xEF; // Happy CS for 8007 on Eval Refrence Design
switch (rAddress)
{
case URR:
// If reading URR, check the CRED bit in MSR so that
// we don't overrun the 8007. See MSR.CRED bit description on page
// 18 of 8007 spec.
#ifdef DEBUG_CRED
while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
{
// If card de-powers exit with zero return value.
if ((BASE_ADDRESS[PCR] & 0x01) == 0)//if the card is deactivation,then out.
{
//ds5250 DMOS &= 0xFE;
// P3 |= 0x10; // Happy CS for 8007 on Ramit Board
P1 |= 0x10; // Happy CS for 8007 on Eval Refrence Design
RPCTL &= 0xDF;
return 0;
}
count++;
if (count == 30000)
{
printf("CRED read locked up on: %02bx\n",rAddress);
printf("PCR: %02bx\n",BASE_ADDRESS[PCR]);
printf("HSR: %02bx\n",BASE_ADDRESS[HSR]);
count = 0;
}
}
#else
while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
{
// If card de-powers exit with zero return value.
if ((BASE_ADDRESS[PCR] & 0x01) == 0)// there is possible to become permanent cycle run
{
//ds5250 DMOS &= 0xFE;
// P3 |= 0x10; // Happy CS for 8007 on Ramit Board
P1 |= 0x10; // Happy CS for 8007 on Eval Refrence Design
RPCTL &= 0xDF;
return 0;
}
}
#endif
break;
default:
break;
}
toReturn = BASE_ADDRESS[rAddress];
//ds5250 DMOS &= 0xFE;
// P3 |= 0x10; // Happy CS for 8007 on Ramit Board
P1 |= 0x10; // Happy CS for 8007 on Eval Refrence Design
RPCTL &= 0xDF;
return toReturn;
}
void dssc_writeregister(uint8_t address,uint8_t value)
{
idata uint8_t rAddress, rValue;
#ifdef DEBUG_CRED
idata int count = 0;
#endif
rAddress = address;
rValue = value;
//ds5250 DMOS |= 0x01;
RPCTL |= 0x20;
// P3 &= 0xEF; // Happy CS for 8007 on Ramit Board
P1 &= 0xEF; // Happy CS for 8007 on Eval Refrence Design p1.5
switch (rAddress)
{
case TOC:
case UTR:
// If writing TOC or UTR, check the CRED bit in MSR so that
// we don't overrun the 8007. See MSR.CRED bit description on page
// 18 of 8007 spec.
#ifdef DEBUG_CRED
while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
{
// If card de-powers exit with zero return value.
if ((BASE_ADDRESS[PCR] & 0x01) == 0)
{
//ds5250 DMOS &= 0xFE;
// P3 |= 0x10; // Happy CS for 8007 on Ramit Board
P1 |= 0x10; // Happy CS for 8007 on Eval Refrence Design
RPCTL &= 0xDF;
return;
}
count++;
if (count == 30000)
{
printf("CRED write locked up on: %02bx\n",rAddress);
printf("PCR: %02bx\n",BASE_ADDRESS[PCR]);
printf("HSR: %02bx\n",BASE_ADDRESS[HSR]);
count = 0;
}
}
#else
while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK));
#endif
break;
default:
break;
}
BASE_ADDRESS[rAddress] = rValue;
//ds5250 DMOS &= 0xFE;
// P3 |= 0x10; // Happy CS for 8007 on Ramit Board
P1 |= 0x10; // Happy CS for 8007 on Eval Refrence Design
RPCTL &= 0xDF;
}
/*
uint8_t Card_iso_out()
{
uint8_t Ret[2];
// DWORD dRet;
// WORD wRet;
uint8_t ins,count,Chr,Len;
CurTC1=TC1[ChannelNo];
CurCardTS=(CardTS>>ChannelNo)&0x1;
// if(CurCardTS)
// for(i=0;i<5;i++)
// data_buf[2+i]=ChangeTo3F(data_buf[2+i]);
ins=data_buf[3];
*(WORD*)Ret=SendStr(5,&data_buf[2]);
if(Ret[0])
return 2;
Len=data_buf[6]+3;
count=3;
for(;;)
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
if(Ret[0])
return 2;
Chr=Ret[1];
// if(CurCardTS)
// Chr=ChangeTo3F(Chr);
if(Chr==ins)
{
while(count<Len)
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
if(Ret[0])
return 2;
data_buf[count++]=Ret[1];
}
continue;
}
if(Chr==~ins)
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
if(Ret[0])
return 2;
data_buf[count++]=Ret[1];
continue;
}
if(Chr==0x60)
continue;
if(((Chr&0xf0)==0x60)||((Chr&0xf0)==0x90))
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
data_buf[Len]=Chr;
if(Ret[0])
return 2;
// if(CurCardTS)
// data_buf[Len+1]=ChangeTo3F(Ret[1]);
// else
data_buf[Len+1]=Ret[1];
data_buf[2]=Len-1;
break;
}
}
// if(CurCardTS)
// for(i=0;i<count-3;i++)
// data_buf[3+i]=ChangeTo3F(data_buf[3+i]);
return 0;
}
uint8_t Card_iso_in()
{
uint8_t Ret[2];
//WORD wRet;
//DWORD dRet;
uint8_t ins,count,Chr;
CurTC1=TC1[ChannelNo];
CurCardTS=(CardTS>>ChannelNo)&0x1;
// if(CurCardTS)
// for(i=0;i<5+data_buf[6];i++)
// data_buf[2+i]=ChangeTo3F(data_buf[2+i]);
ins=data_buf[3];
*(WORD*)Ret=SendStr(5,&data_buf[2]);
if(Ret[0])
return 2;
count=0;
for(;;)
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
if(Ret[0])
return 2;
Chr=Ret[1];
// if(CurCardTS)
// Chr=ChangeTo3F(Chr);
if(Chr==ins)
{
DelayETU(16);
*(WORD*)Ret=SendStr(data_buf[6]-count,&data_buf[7+count]);
if(Ret[0])
return 2;
continue;
}
if(Chr==~ins)
{
DelayETU(16);
if(ChannelNo)
{
if(SendByteB(data_buf[7+count++]))
return 2;
}
else
{
if(SendByteA(data_buf[7+count++]))
return 2;
}
// if(SendByte(data_buf[7+count++]))
// return 2;
continue;
}
if(Chr==0x60)
continue;
if(((Chr&0xf0)==0x60)||((Chr&0xf0)==0x90))
{
if(ChannelNo)
*(WORD*)Ret=ReceByteB();
else
*(WORD*)Ret=ReceByteA();
// *(WORD*)Ret=ReceByte();
data_buf[3]=Chr;
if(Ret[0])
return 2;
// if(CurCardTS)
// data_buf[4]=ChangeTo3F(Ret[1]);
// else
data_buf[4]=Ret[1];
data_buf[2]=2;
break;
}
}
return 0;
}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -