📄 tda8007.c
字号:
tda_powerdown();
printk("No ATR within timeout\n");
return ERR_POWERUP_ATR_TIMEOUT;
}
}//end 1
if (mode == POWERUP_ISO)
{
// Set up timer for 9600 etu between characters in ATR
tda_writeregister(TOC,0x00);
delay_us(5);
tda_writeregister(TOR3,0x25);
delay_us(5);
tda_writeregister(TOR2,0x80);
delay_us(5);
tda_writeregister(TOR1,0x00);
delay_us(5);
// Start timer
tda_writeregister(TOC,0x61);
}
else // mode is EMV
{
// Set up timer for 9600 etu between characters in ATR, and
// maximum of 19200 etu for whole ATR
tda_writeregister(TOC,0x05);
tda_writeregister(TOR3,0x25);
tda_writeregister(TOR2,0x80);
tda_writeregister(TOR1,0xC0);
// Start timer
tda_writeregister(TOC,0x65);
}//end if
//printk("Getting ATR\n");
index = 0;
while (!done)
{
// Read UART status
USRval = tda_readregister(USR);
{
// If receive buffer full
if (USRval & USR_TBE_RBF_MASK)
{
// Read and store ATR byte
val = tda_readregister(URR);
curByte = val;
rec_buf[index++] = val;
if (index == 1)
{
lastATR[currentSlot].TS = curByte;
if ((curByte != 0x3f) && (curByte != 0x3b))
{
tda_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
check = 0;
}
else
check ^= curByte;
if (index == 2)
{
historicalBytes = curByte & 0x0F;
expectedCharacters = curByte & 0xF0;
lastATR[currentSlot].T0 = curByte;
}
if (index > 2)
{
switch(expectedCharacters)
{
case 0x00:
// Historical characters
historicalBytes--;
lastATR[currentSlot].Historical[lastATR[currentSlot].HistoricalLength++] = curByte;
if (historicalBytes == 0)
{
if (T == 0)
{
done = 1;
}
else
expectedCharacters = 0x01; // Go to checksum state
}
break;
case 0x01:
// TCK case
lastATR[currentSlot].TCK = curByte;
done = 1;
break;
case 0x10:
case 0x30:
case 0x50:
case 0x70:
case 0x90:
case 0xB0:
case 0xD0:
case 0xF0:
// TA case
expectedCharacters &= 0xE0;
lastATR[currentSlot].TA[interfaceIteration] = curByte;
break;
case 0x20:
case 0x60:
case 0xA0:
case 0xE0:
// TB case
expectedCharacters &= 0xD0;
lastATR[currentSlot].TB[interfaceIteration] = curByte;
break;
case 0x40:
case 0xC0:
// TC case
expectedCharacters &= 0xB0;
lastATR[currentSlot].TC[interfaceIteration] = curByte;
break;
case 0x80:
// TD case
expectedCharacters=(curByte&0xF0);
// Handle zero historical characters
if ((expectedCharacters == 0x00) && (historicalBytes == 0))
{
if (T == 0)
{
done = 1;
}
else
expectedCharacters = 0x01;
}
lastATR[currentSlot].TD[interfaceIteration] = curByte;
// If we get TD1, we have the first protocol selection
if ((interfaceIteration==1))
{
T = curByte & 0x0F;
}
else
{
// Changing protocols is only valid under ISO (not allowed in EMV)
if (mode == POWERUP_ISO)
{
if ((curByte & 0x0F) != T)
{
T = curByte & 0x0F;
}
}
else
return ERR_POWERUP_ATR_INVALID; // You cannot change T protocol under EMV
}
interfaceIteration++;
break;
default:
tda_powerdown();
return ERR_POWERUP_ATR_INVALID;
break;
}
}
if (mode == POWERUP_ISO)
{
// Reset timer for 9600 etu between characters in ATR
tda_writeregister(TOC,0x00);
delay_us(5);
tda_writeregister(TOR3,0x25);
delay_us(5);
tda_writeregister(TOR2,0x80);
delay_us(5);
tda_writeregister(TOR1,0x00);
delay_us(5);
// Start timer
tda_writeregister(TOC,0x61);
}
else // mode is EMV
{
// Set up timer for 9600 etu between characters in ATR
// Don't modify TOR1 as it is in auto-reload mode.
tda_writeregister(TOC,0x05);
tda_writeregister(TOR3,0x25);
tda_writeregister(TOR2,0x80);
// Start timer
tda_writeregister(TOC,0x65);
}
}
}
// Read Timer status
if (USRval & USR_TOL3_MASK)
{
printk("Character waiting timeout\n");
tda_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)
{
printk("ATR waiting timeout\n");
tda_powerdown();
return ERR_POWERUP_ATR_TIMEOUT;
}
}
}//end !done
// If we are in T=1 protocol, we get a LRC (xor checksum) at the end
if (T == 1)
{
if (check != 0)
{
printk("LRC failed: 0x%2x\n",check);
tda_powerdown();
return ERR_POWERUP_ATR_CRC_FAILURE;
}
}
// Set ATR length for the ATR received
*rec_len = index;
// Set T protocol mode
TMode[currentSlot] = T;
// Set the 8007 UCR1.PROT mode according to T value
val = tda_readregister(UCR1);
if (T == 0)
tda_writeregister(UCR1,val & ~UCR1_PROT_MASK);
else
tda_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)
tda_writeregister(GTR,lastATR[currentSlot].TC[1]);
else
tda_writeregister(GTR,0xff);
// 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;
printk("WWT: %ld\n",WWT[currentSlot]);
if (mode == POWERUP_EMV)
{
if (lastATR[currentSlot].TB[3] == -1)
{
// FIXME: Should we power down here? It is an EMV violation
tda_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
tda_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
tda_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);
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.
tda_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
break;
}
}
printk("CWT: %ld\n",CWT[currentSlot]);
return 0;
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static int tda_powerdown(void)
{
u8 val;
// Power down the card
val = tda_readregister(PCR);
tda_writeregister(PCR,val & ~PCR_START_MASK);
return 0;
}
/*************************************************************************
功能:check card
参数:
返回值:-1: error
0: OK
**************************************************************************/
static int tda_checkpresence(uchar slot)
{
u8 val;
val = tda_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;
}
/*************************************************************************
功能:select card
参数:
返回值:-1: error
0: OK
**************************************************************************/
static int tda_selectcard(uchar slot)
{
u8 val;
val = tda_readregister(CSR);
switch (slot)
{
case 1:
// Select appropriate smartcard and clear other card selects
tda_writeregister(CSR, (val & ~(CSR_SC3_MASK | CSR_SC2_MASK))|CSR_SC1_MASK);
if(tda_checkpresence(slot) < 0) return NO_CARD_ERR;
break;
case 2:
// Select appropriate smartcard and clear other card selects
tda_writeregister(CSR,(val & ~(CSR_SC3_MASK|CSR_SC1_MASK))|CSR_SC2_MASK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -