#include #include "yc11xx.h" #include "SCI7816.h" #include "yc11xx_uart.h" #include "yc11xx_gpio.h" #define SCI7816_BUF_SIZE 128 unsigned char sci7816_rx_buf[SCI7816_BUF_SIZE]; unsigned char sci7816_tx_buf[SCI7816_BUF_SIZE]; #define SCI7816_CLK_IO 19 //4 //29 #define SCI7816_RESET_IO 24 //2 //28 #define SCI7816_DATA_IO 25 //26 #define SCI7816_VCC_IO 27 //0 //27 #define SCI7816_RESET_IO_HIGH GPIO_SetGpioMultFunction(SCI7816_RESET_IO, GPCFG_OUTPUT_HIGH) #define SCI7816_RESET_IO_LOW GPIO_SetGpioMultFunction(SCI7816_RESET_IO, GPCFG_OUTPUT_LOW) #define SCI7816_DATA_IO_RX GPIO_SetGpioMultFunction(SCI7816_DATA_IO, GPCFG_UART_RXD) #define SCI7816_DATA_IO_TX GPIO_SetGpioMultFunction(SCI7816_DATA_IO, GPCFG_UART_TXD) #define SCI7816_VCC_IO_HIGH GPIO_SetGpioMultFunction(SCI7816_VCC_IO, GPCFG_OUTPUT_HIGH) #define SCI7816_VCC_IO_LOW GPIO_SetGpioMultFunction(SCI7816_VCC_IO, GPCFG_OUTPUT_LOW) void sci7816_clk_enable(void) { GPIO_SetGpioMultFunction(SCI7816_CLK_IO, GPCFG_PWM_OUT0); HWRITE(CORE_CLKOFF+1, 0); HWRITE(CORE_PWM0_PCNT, 2); HWRITE(CORE_PWM0_NCNT, 2); HWRITE(CORE_PWM0_CTRL, 0X30); } void sci7816_clk_disable(void) { GPIO_SetGpioMultFunction(SCI7816_CLK_IO, GPCFG_OUTPUT_LOW); HWRITE(CORE_PWM0_CTRL, 0X00); } void sci7816_io_init(void) { HWRITE(CORE_UART_CTRL, 0x00); //sysclk/186 = 129075 HWRITEW(CORE_UART_BAUD, 0x8000|4463); //3.57 115200 4 129075 372 //186 HWRITEW(CORE_UART_RX_SADDR, sci7816_rx_buf); HWRITEW(CORE_UART_RX_EADDR, sci7816_rx_buf+SCI7816_BUF_SIZE-1); HWRITEW(CORE_UART_RX_RPTR, sci7816_rx_buf); HWRITEW(CORE_UART_TX_SADDR, sci7816_tx_buf); HWRITEW(CORE_UART_TX_EADDR, sci7816_tx_buf+SCI7816_BUF_SIZE-1); HWRITEW(CORE_UART_TX_WPTR, sci7816_tx_buf); HWRITE(CORE_UART_CTRL, 0xc5); } void sci7816_delay_ms(unsigned int time) { unsigned int num,j; for (num = 0; num 0) { sci7816_rec(atr+2, txnum); } recnum = 2 + txnum; if (td1flag == 1) { txnum = 0; if (atr[recnum-1] & 0x80) //TD { txnum++; } if (atr[recnum-1] & 0x40) //TC { txnum++; } if (atr[recnum-1] & 0x20) //TB { txnum++; } if (atr[recnum-1] & 0x10) //TA { txnum++; } if (txnum > 0) { sci7816_rec(atr+recnum, txnum); } recnum += txnum; } sci7816_rec(atr+recnum, logsize); *num = recnum+logsize; return 0; } return 1; } uint8_t SCI7816_Reset (uint8_t *presp ,uint8_t respbufsize, uint16_t *prespsize) { uint8_t data[2] = {0xaa,0x55}; SCI7816_VCC_IO_LOW; SCI7816_RESET_IO_LOW; SCI7816_VCC_IO_HIGH; sci7816_clk_enable(); sci7816_delay_ms(10); sci7816_io_init(); SCI7816_RESET_IO_HIGH; GPIO_SetGpioMultFunction(SCI7816_DATA_IO, GPCFG_UART_RXD); sci7816_delay_ms(5); return esam_rec_atr(presp, prespsize); } uint16_t ISO7816_TPDU_T0(uint8_t *pCommand, uint16_t CommandLength, uint8_t *pResponse, uint16_t *pResponseLength) { uint8_t sw1, Ins; uint16_t p3; uint16_t ret , tmpRecLen=0, tmpSendOffset; tmpRecLen =0; if((NULL == pCommand) || (NULL == pResponse)|| (CommandLength < 4)|| (NULL == pResponseLength)) { return ISO7816_PARA_ERROR; } if(CommandLength == 4) { //case1 pCommand[4] = 0; } Ins = pCommand[1]; sci7816_send(pCommand, 5); pResponse[tmpRecLen] = ISO7816_NULL_T0; do { sci7816_rec(&pResponse[tmpRecLen], 1); }while(pResponse[tmpRecLen] == ISO7816_NULL_T0); sw1 = pResponse[0]; p3 = pCommand[4]; tmpSendOffset = 5; do { if( (0x60 == (sw1 & 0xF0)) || (0x90 == (sw1 & 0xF0)) ) { tmpRecLen++; sci7816_rec(&pResponse[tmpRecLen++], 1); *pResponseLength = tmpRecLen; return OK; } if(Ins == sw1) { if(5 == CommandLength) { sci7816_rec(&pResponse[tmpRecLen], p3 + 2 - tmpRecLen); *pResponseLength = p3 + 2; return OK; } else { //case 3 case4 sci7816_send(pCommand + tmpSendOffset, p3); pResponse[tmpRecLen] = ISO7816_NULL_T0; do { ret = sci7816_rec(&pResponse[tmpRecLen], 1); }while(pResponse[tmpRecLen] == ISO7816_NULL_T0); tmpRecLen++; ret = sci7816_rec(&pResponse[tmpRecLen++], 1); *pResponseLength = tmpRecLen; return OK; } } else if (sw1 == (uint8_t)(~Ins)) { if(5 == CommandLength) { //case 2 ret = sci7816_rec(&pResponse[tmpRecLen++], 1); if(tmpRecLen >= (p3 + 2)) { *pResponseLength = tmpRecLen; return OK; } ret = sci7816_rec(&pResponse[tmpRecLen], 1); sw1 = pResponse[tmpRecLen]; } else { //case 3 case4 if(p3) { sci7816_send(pCommand + tmpSendOffset, 1); tmpSendOffset++; p3--; do { ret = sci7816_rec(&pResponse[tmpRecLen], 1); }while(pResponse[tmpRecLen] == ISO7816_NULL_T0); sw1 = pResponse[tmpRecLen]; continue; } else { do { ret = sci7816_rec(&pResponse[tmpRecLen], 1); }while(pResponse[tmpRecLen] == ISO7816_NULL_T0); sw1 = pResponse[tmpRecLen++]; ret = sci7816_rec(pResponse + 1, 1); *pResponseLength = 2; return OK; } } } else { return ISO7816_PROCEDURE_INS_ERROR; } }while(1); } uint16_t ISO7816_Dispose_CMD(uint8_t *pCmd, uint16_t CmdLen, uint8_t *pResp, uint16_t *pRespLen) { uint16_t ret; uint16_t tmpRespLen,tmpCmdLen; uint16_t tmpOffset; uint8_t tmpCMDBuf[5]; uint8_t tmpRECBuf[286]; uint8_t tmp61Flag; uint8_t lenflag = 0; tmpOffset = 0; tmp61Flag = 0; tmpCmdLen = CmdLen; memcpy(tmpCMDBuf,pCmd,5); ret = ISO7816_TPDU_T0(pCmd, tmpCmdLen, tmpRECBuf + tmpOffset, &tmpRespLen); tmpOffset +=tmpRespLen; while(1) { if(tmpRespLen>=2) { if(tmpRECBuf[tmpOffset-2] == 0x61) { lenflag = 1; tmpCMDBuf[0] = 0; tmpCMDBuf[1] = 0xC0; tmpCMDBuf[2] = 0; tmpCMDBuf[3] = 0; tmpCMDBuf[4] = tmpRECBuf[tmpOffset-1]; tmpOffset -= 2; ret = ISO7816_TPDU_T0(tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen); tmp61Flag = 1; tmpOffset +=tmpRespLen; continue; } else if(tmpRECBuf[tmpOffset-2] == 0x6C) { lenflag = 1; tmpCMDBuf[4] = tmpRECBuf[tmpOffset-1]; tmpOffset -= 2; ret = ISO7816_TPDU_T0(tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen); tmpOffset +=tmpRespLen; continue; } else if((tmpRECBuf[tmpOffset-2] == 0x90) && (tmpRECBuf[tmpOffset-1] == 0x00)) { break; } //date else if((tmpRECBuf[tmpOffset-2] == 0x62) || (tmpRECBuf[tmpOffset-2] == 0x63) || ( (tmpRECBuf[tmpOffset-2] & 0xF0) == 0x90 ) ) { if(tmp61Flag==1) { break; } if((CmdLen > 5) &&(tmpCMDBuf[1] == 0xA4)) //case 3 or 4 { lenflag = 1; tmpCMDBuf[0] = 0; tmpCMDBuf[1] = 0xC0; tmpCMDBuf[2] = 0; tmpCMDBuf[3] = 0; tmpCMDBuf[4] = 0; tmpOffset-=2; ret = ISO7816_TPDU_T0(tmpCMDBuf, 5, tmpRECBuf + tmpOffset, &tmpRespLen); tmpOffset +=tmpRespLen; continue; } else { break; } } else { break; } } else { break; } }//end while // if (lenflag) // { // memcpy(pResp,tmpRECBuf+2,tmpOffset-2); // *pRespLen = tmpOffset - 2; // } // else { memcpy(pResp,tmpRECBuf,tmpOffset); *pRespLen = tmpOffset; } return OK; } uint8_t SCI7816_CosOperation(uint8_t *pcmd, uint16_t cmdsize, uint8_t getrespfalg, uint8_t *presp, uint16_t respbufsize, uint16_t *prespsize) { if (getrespfalg == ESAM_GET_RESP) { return ISO7816_Dispose_CMD(pcmd, cmdsize, presp, prespsize); } else { return ISO7816_TPDU_T0(pcmd, cmdsize, presp, prespsize); } }