📄 ds8007.c.bak
字号:
uint8_t val;
uint8_t USRval;
uint8_t index;
uint8_t etucount = 0;
int16_t i;
uint8_t historicalBytes;
uint8_t expectedCharacters;
uint8_t interfaceIteration = 1;
uint8_t done = 0;
uint8_t check;
// Default to T=0 mode
uint8_t T = 0;
uint8_t curByte;
clearATRStruct(&lastATR[currentSlot]);
NAD[currentSlot] = 0;
// Reset the UART
val = dssc_readregister(CSR);
dssc_writeregister(CSR,val & ~CSR_nRIU_MASK);
// Remove UART reset
val = dssc_readregister(CSR);
dssc_writeregister(CSR,val | CSR_nRIU_MASK);
// Set FIFO to 1 byte
dssc_writeregister(FCR,0x00);
// Set divisor
dssc_writeregister(PDR,12);
// Set prescaler
dssc_writeregister(UCR2,0x00);
// Enable auto convention
val = dssc_readregister(UCR2);
dssc_writeregister(UCR2,val & ~UCR2_nAUTOCONV_MASK);
// Set SS bit
dssc_writeregister(UCR1,UCR1_SS_MASK);
// Wait 40000 to 45000 cycles to release reset
dssc_writeregister(TOC,0x00);
dssc_writeregister(TOR3,0x00);
dssc_writeregister(TOR2,0x6C);
dssc_writeregister(TOR1,0x00);
dssc_writeregister(TOC,0x61);
do
{
val = dssc_readregister(USR);
}
while (!(val & USR_TOL3_MASK));
if (mode == POWERUP_ISO)
{
// Wait up to 40000 cycles for ATR to start
dssc_writeregister(TOC,0x00);
dssc_writeregister(TOR3,0x00);
dssc_writeregister(TOR2,0x78);
dssc_writeregister(TOR1,0x00);
dssc_writeregister(TOC,0x61);
}
else // power up EMV
{
// Wait up to 40000 cycles for ATR to start and 19200 etu counter after first byte
dssc_writeregister(TOC,0x00);
dssc_writeregister(TOR3,0x00);
dssc_writeregister(TOR2,0x78);
dssc_writeregister(TOR1,0xC0);
dssc_writeregister(TOC,0x65);
}
// Release reset
val = dssc_readregister(PCR);
dssc_writeregister(PCR,val | PCR_RSTIN_MASK);
while (1)
{
val = dssc_readregister(MSR);
// If we see the first character come in, break.
if (val & MSR_TBE_RBF_MASK)
break;
val = dssc_readregister(USR);
if (val & (USR_PE_MASK|USR_FER_MASK|USR_OVR_MASK|USR_EA_MASK))
{
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
if (val & USR_TOL3_MASK)
{
dssc_powerdown();
return ERR_POWERUP_ATR_TIMEOUT;
}
}
if (mode == POWERUP_ISO)
{
// Set up timer for 9600 etu between characters in ATR
dssc_writeregister(TOC,0x00);
dssc_writeregister(TOR3,0x25);
dssc_writeregister(TOR2,0x80);
dssc_writeregister(TOR1,0x00);
// Start timer
dssc_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
dssc_writeregister(TOC,0x05);
dssc_writeregister(TOR3,0x25);
dssc_writeregister(TOR2,0x80);
dssc_writeregister(TOR1,0xC0);
// Start timer
dssc_writeregister(TOC,0x65);
}
index = 0;
while (!done)
{
// Read UART status
USRval = dssc_readregister(USR);
{
// If receive buffer full
if (USRval & USR_TBE_RBF_MASK)
{
// Read and store ATR byte
val = dssc_readregister(URR);
curByte = val;
workingBuffer[index++] = val;
if (index == 1)
{
lastATR[currentSlot].TS = curByte;
if ((curByte != 0x3f) && (curByte != 0x3b))
{
dssc_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:
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
break;
}
}
if (mode == POWERUP_ISO)
{
// Reset timer for 9600 etu between characters in ATR
dssc_writeregister(TOC,0x00);
dssc_writeregister(TOR3,0x25);
dssc_writeregister(TOR2,0x80);
dssc_writeregister(TOR1,0x00);
// Start timer
dssc_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.
dssc_writeregister(TOC,0x05);
dssc_writeregister(TOR3,0x25);
dssc_writeregister(TOR2,0x80);
// Start timer
dssc_writeregister(TOC,0x65);
}
}
}
// Read Timer status
if (USRval & USR_TOL3_MASK)
{
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)
{
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)
{
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 DS8007 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)
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)
if (lastATR[currentSlot].TA[3] != -1)
{
val = lastATR[currentSlot].TA[3];
if ((val < 0x10) || (val == 0xFF))
{
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 (mode == POWERUP_EMV)
{
if (lastATR[currentSlot].TB[3] == -1)
{
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
else
{
val = lastATR[currentSlot].TB[i] & 0x0F;
// Fail if CWI is out of range
if (val > 5)
{
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
// Fail if BWI is out of range
if (val > 4)
{
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
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)
{
dssc_powerdown();
return ERR_POWERUP_ATR_INVALID;
}
BWT[currentSlot] = 11 + (1 << val) * 960;
break;
}
}
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;
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;
P1 &= 0xEF; // Happy CS for DS8007 on Eval Refrence Design
switch (rAddress)
{
case URR:
// If reading URR, check the CRED bit in MSR so that
// we don't overrun the DS8007. See MSR.CRED bit description on page
// 18 of DS8007 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;
P1 |= 0x10; // Happy CS for DS8007 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)
{
//ds5250 DMOS &= 0xFE;
P1 |= 0x10; // Happy CS for DS8007 on Eval Refrence Design
RPCTL &= 0xDF;
return 0;
}
}
#endif
break;
default:
break;
}
toReturn = BASE_ADDRESS[rAddress];
//ds5250 DMOS &= 0xFE;
P1 |= 0x10; // Happy CS for DS8007 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;
P1 &= 0xEF; // Happy CS for DS8007 on Eval Refrence Design
switch (rAddress)
{
case TOC:
case UTR:
// If writing TOC or UTR, check the CRED bit in MSR so that
// we don't overrun the DS8007. See MSR.CRED bit description on page
// 18 of DS8007 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;
P1 |= 0x10; // Happy CS for DS8007 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;
P1 |= 0x10; // Happy CS for DS8007 on Eval Refrence Design
RPCTL &= 0xDF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -