?? ic_card.c
字號(hào):
/********************************************************************* * Designed by xiaohuiyang 2005.06.08 E-mail: yxh2001@21cn.com
* *********************************************************************/#include <string.h>#include <stdio.h>#include <stdlib.h>#include "ic_card.h"#include "tl.h" //Include Transport Layerchar m_chErrMsg[20];int ICOpenCom(){ if(TL_Open(2, 9600) != NO_ERR) { return -1; } return 0;}int ICCloseCom(){ TL_Close(); return 0;}int ICPowerOn(){ unsigned char recvbuf[256]; unsigned char cmd[] = "\x12"; unsigned char recvlen = 0; memset(recvbuf, 0x00, sizeof(recvbuf)); SendCmd(cmd, 1, recvbuf, &recvlen); if(recvbuf[1] == 0x3B) return 0; return -1;}int ICPowerDown(){ unsigned char recvbuf[256]; unsigned char cmd[] = "\x11"; unsigned char recvlen = 0; memset(recvbuf, 0x00, sizeof(recvbuf)); SendCmd(cmd, 1, recvbuf, &recvlen); return 0;}int ReadAccount(stMACDATA *pst/*char *account*/){ return PbocSelectPboc(pst/*account*/);}/*=============================================================================//函數(shù)名稱: SendICCommand//輸入?yún)?shù): char *ICSendbuf : 發(fā)送字符串//輸出參數(shù): char *ICRecvbuf : 接收字符串// char *ICSW : 判斷符 //返 回: 0--成功; <0: 失敗//功 能: 發(fā)送ic卡命令//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/short SendICCommand(char *ICSendbuf, char *ICRecvbuf, char *ICSW){ int ret,datalen; char chLen[3]; ret=SendICC(ICSendbuf, 0, ICRecvbuf, ICSW); memset(chLen, 0x00, 3); if(strncmp(ICSW,"61",2)==0) { memcpy(chLen,&ICSW[2],2); sscanf(chLen,"%02X",&datalen); datalen = datalen&0XFF; memset(ICSW, '\0', 5); ret = PbocGetResponse(ICRecvbuf, datalen, ICSW); } return ret;}/*=============================================================================//函數(shù)名稱: PbocGetResponse//輸入?yún)?shù): char *ICSendbuf : 發(fā)送字符串// unsigned int datalen : 發(fā)送字符串長度//輸出參數(shù): char *SW : 判斷符 //返 回: 0--成功; <0: 失敗//功 能: 發(fā)送ic卡響應(yīng)命令//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/short PbocGetResponse(char *ICRecvbuf, unsigned int datalen, char *SW){ int ret; char chSend1[128], chLen[3]; stAPDU apdu; if( datalen<0 || datalen>256 ) return 102; //102代表數(shù)據(jù)長度錯(cuò) memset( &apdu, '\0', sizeof(stAPDU) ); strcpy(apdu.cla,"00"); strcpy(apdu.ins,"C0"); strcpy(apdu.p1,"00"); strcpy(apdu.p2,"00"); sprintf(apdu.p3, "%02X", datalen); memset( chSend1, '\0', 128); sprintf(chSend1,"%s%s%s%s%s%s",apdu.cla,apdu.ins,apdu.p1,apdu.p2,apdu.p3,apdu.data); ret = SendICCommand(chSend1,ICRecvbuf,SW); if( ret ) return ret; ret =CheckSW(SW); if( ret ) return ret; memset(chLen,'\0',3); if(strncmp(SW,"6C",2)==0 || strncmp(SW,"61",2)==0) { memcpy(chLen,&SW[2],2); sscanf(chLen,"%02X",&datalen); datalen = datalen&0XFF; return PbocGetResponse(ICRecvbuf, datalen,SW); } return 0;}/*=============================================================================//函數(shù)名稱: CheckSW//輸入?yún)?shù): char *pSW : 判斷字符串//輸出參數(shù):無//返 回: 0--成功; <0: 失敗//功 能: 檢查ic卡響應(yīng)//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/short CheckSW(char *pSW){ unsigned int nSW; memset(m_chErrMsg,'\0',20); if((strncmp(pSW, "9000", 4)==0 || strncmp(pSW, "61", 2)==0 || strncmp(pSW, "6C", 2)==0 )) { return 0; } sscanf(pSW, "%04X", &nSW); GetICSWErrMsg(nSW); return nSW;}/*=============================================================================//函數(shù)名稱: GetICSWErrMsg//輸入?yún)?shù): unsigned int SW : 錯(cuò)誤標(biāo)志//輸出參數(shù):無//返 回: 0--成功; <0: 失敗//功 能: 獲取錯(cuò)誤信息//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/void GetICSWErrMsg(unsigned int SW){ memset(m_chErrMsg,'\0',20); if( SW==0X6700 ) strcpy(m_chErrMsg,"Lc錯(cuò)誤!"); else if( SW==0X6901 ) strcpy(m_chErrMsg,"命令不接受!"); else if( SW==0X6982 ) strcpy(m_chErrMsg,"不滿足安全狀態(tài)!"); else if( SW==0X6985 ) strcpy(m_chErrMsg,"使用條件不滿足!"); else if( SW==0X6A81 ) strcpy(m_chErrMsg,"不支持此功能!"); else if( SW==0X6A82 ) strcpy(m_chErrMsg,"文件未找到!"); else if( SW==0X6A86 ) strcpy(m_chErrMsg,"參數(shù)P1, P2錯(cuò)誤!"); else if( SW==0X6D00 ) strcpy(m_chErrMsg,"INS錯(cuò)誤!"); else if( SW==0X6E00 ) strcpy(m_chErrMsg,"CLA錯(cuò)誤!"); else if( SW==0X9302 ) strcpy(m_chErrMsg,"MAC無效!"); else if( SW==0X9303 ) strcpy(m_chErrMsg,"應(yīng)用已經(jīng)永久鎖定!"); else if( SW==0X9401 ) strcpy(m_chErrMsg,"金額不足!"); else if( SW==0X9403 ) strcpy(m_chErrMsg,"密鑰索引不支持!"); else if( SW==0X9406 ) strcpy(m_chErrMsg,"所需的MAC不可用!"); else strcpy(m_chErrMsg,"系統(tǒng)出錯(cuò)");}/****************************************************************//* Description : Sends Command to the reader and displays *//* answer or error code . *//* Input : *//* unsigned char *pszCmd -> Command *//* unsigned char ucLgcmd -> Command Length *//* Output : None *//* Returns : Error Code *//* Global Variables : None *//****************************************************************/short int SendCmd( unsigned char *pszCmd, unsigned char ucLgcmd, unsigned char *szRep, unsigned char *ucLgRep){// unsigned char szRep[ 256 ], ucLgRep ; short int siRet;//#ifdef MMI unsigned char ucIndice ; printf( "\n->" ); /*Display Command*/ for ( ucIndice = 0 ; ucIndice < ucLgcmd ; ucIndice++ ) printf( " %02Xh", pszCmd[ ucIndice ] ) ;//#endif /*Send the command and retrieves the answer*/ siRet = TL_SendReceive( ucLgcmd, pszCmd, ucLgRep, szRep ); /*If no error occured then display answer*/ if ( siRet == NO_ERR ) {//#ifdef MMI printf( "\n<-" ); for ( ucIndice = 0 ; ucIndice < *ucLgRep ; ucIndice++ ) printf( " %02Xh", szRep[ ucIndice ] ) ; printf( "\n" );//#endif } else { /*dispay error code value*///#ifdef MMI printf( "\nError occured : %X\n", siRet );//#endif /*Close port*/ TL_Close() ; /*Leave application*/ exit( -1 ) ; } return ( siRet ) ;}/*=============================================================================//函數(shù)名稱: SendICC//輸入?yún)?shù): char *ICSendbuf : 發(fā)送字符串// int sendlen : 發(fā)送長度//輸出參數(shù):char *ICRecvbuf : 接收字符串// char *ICSW : 接收標(biāo)志//返 回: 0--成功; <0: 失敗//功 能: 發(fā)送IC卡指令//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/int SendICC(char *ICSendbuf, int sendlen, char *ICRecvbuf, char *ICSW){ unsigned char ucLgRep; SendCmd((unsigned char *)ICSendbuf, sendlen, (unsigned char *)ICRecvbuf, &ucLgRep) ; return 0;}/*=============================================================================//函數(shù)名稱: PbocICSelect//輸入?yún)?shù): char *file_id : 文件名稱// int filelen :文件長度//輸出參數(shù):unsigned char *recvbuf : 接收字符串//返 回: 0--成功; <0: 失敗//功 能: 文件選擇//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/int PbocICSelect(char *file_id, int filelen, unsigned char *recvbuf){ unsigned char recvlen = 0; unsigned char SendCommand[128]; int sendlen; short ret;// int i; memset((char *)SendCommand, 0x00, sizeof(SendCommand)); sprintf((char *)SendCommand, "%c%c%c%c%c%c", 0x14, 0x00, 0xA4, 0x04, 0x00, filelen); memcpy(SendCommand+6, file_id, filelen); sendlen = filelen + 6; ret = SendCmd(SendCommand, sendlen, recvbuf, &recvlen);/* printf("Pboc IC select:["); for(i = 0; i < recvlen; i++) { printf("%02X ", recvbuf[i]); } printf("]\n");*/ if(recvbuf[1] == 0x61) { sprintf((char *)SendCommand, "%c%c%c%c%c%c", 0x13, 0x00, 0xC0, 0x00, 0x00, recvbuf[2]); SendCmd(SendCommand, 6, recvbuf, &recvlen); } return 0;}/*=============================================================================//函數(shù)名稱: PbocSelectPboc//輸入?yún)?shù): 無//輸出參數(shù):無//返 回: 0--成功; <0: 失敗//功 能: 金融應(yīng)用選擇//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/int PbocSelectPboc(stMACDATA *pst/*char *Account*/){ short ret; short sfi; char *ptr, tmpfilename[256]; char chPSE[50]; unsigned char recvbuf[256];// unsigned char datalen;// char cardno[21]; memset(tmpfilename, 0x00, sizeof(tmpfilename)); memset(recvbuf,'\0',256); memset(chPSE, '\0', 50); memcpy(tmpfilename, "1PAY.SYS.DDF01", 14); strcpy(chPSE, tmpfilename); PbocICSelect("1PAY.SYS.DDF01", strlen(tmpfilename), recvbuf);// if( ret )// return ret; printf("strstr\n"); ptr = strstr((char *)(recvbuf+1), "\x88\x01"); if(ptr == NULL) return -1; ptr += 2; sfi = ptr[0] & 0XFF; memset(recvbuf, 0x00, sizeof(recvbuf));/* for(i = 1; ; i++) { printf("Send Read Record\n"); ret = PbocReadRecord(0x14, ABS_RECORD, sfi, i, 0, (char *)recvbuf); if( ret ) return ret; printf("start strstr find data ...\n"); ptr = strstr((char *)(recvbuf+1),"\x4F"); if(ptr == NULL) return -1; if(strncmp(ptr+2, chPSE, 14) != 0 ) break; } printf("come here\n"); datalen = ptr[1] & 0XFF; memset(tmpfilename, 0x00, sizeof(tmpfilename)); memcpy(tmpfilename, ptr+2, datalen);*/ ret = PbocICSelect("\xD1\x56\x00\x00\x01\x45\x44\x2F\x45\x50\x00\x00\x00\x00\x00\x00", 16, recvbuf); if( ret ) return ret; //Unpackage Receive Data// memset(cardno, 0x00, sizeof(cardno)); GetInfo((char *)recvbuf, pst); // ret = PbocReadBinary(0x14, 21, 0, 30, (char *)recvbuf); return 0;}/*=============================================================================//函數(shù)名稱: PbocReadRecord//輸入?yún)?shù): char head : 發(fā)送頭標(biāo)志// short readmode: 讀取模式// short sfi:// short recno: 記錄數(shù)// short reclen: 接收長度//輸出參數(shù):char *recvbuf: 接收數(shù)據(jù)//返 回: 0--成功; <0: 失敗//功 能: 讀記錄//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/short PbocReadRecord(char head, short readmode, short sfi, short recno, short reclen, char *recvbuf){ unsigned char recvlen = 0; unsigned char datalen; int sendlen; unsigned char SendCommand[128]; short ret, p2; p2 = ( sfi << 3 ) | readmode; memset((char *)SendCommand, 0x00, sizeof(SendCommand)); sprintf((char *)SendCommand, "%c%c%c%c%c%c", head, 0x00, 0xB2, recno, p2, reclen); sendlen = 6; printf("Send Read Record\n"); ret = SendCmd(SendCommand, sendlen, (unsigned char *)recvbuf, &recvlen); if(recvbuf[1] == 0x6C || recvbuf[1] == 0x61) { datalen = recvbuf[2] & 0XFF; return PbocReadRecord(0x13, readmode, sfi, recno, datalen, recvbuf); } return 0;}/*=============================================================================//函數(shù)名稱: PbocReadBinary//輸入?yún)?shù): char head : 發(fā)送頭標(biāo)志// short sfi:// short offset: 偏移量// short readlen: 接收長度//輸出參數(shù):char *recvbuf: 接收數(shù)據(jù)//返 回: 0--成功; <0: 失敗//功 能: 讀二進(jìn)制文件//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/short PbocReadBinary(char head, short sfi, short offset, short readlen, char *recvbuf){ short datalen, ret, p1; int sendlen; unsigned char recvlen = 0; unsigned char SendCommand[128]; if( sfi > 30 || (sfi<21 && sfi!=0 ) ) return FALSE; if( sfi!=0 ) p1 = 0x80 | sfi; else p1 = sfi; memset((char *)SendCommand, 0x00, sizeof(SendCommand)); sprintf((char *)SendCommand, "%c%c%c%c%c%c", head, 0x00, 0xB0, p1, offset, readlen); sendlen = 6; printf("Send ReadBinary\n"); ret = SendCmd(SendCommand, sendlen, (unsigned char *)recvbuf, &recvlen); if(recvbuf[1] == 0x6C || recvbuf[1] == 0x61) { datalen = recvbuf[2] & 0XFF; return PbocReadBinary(0x13, sfi, offset, datalen, recvbuf); } return 0;}/*=============================================================================//函數(shù)名稱: GetInfo//輸入?yún)?shù): char *recvbuf: 接收數(shù)據(jù)//輸出參數(shù):char *cardno : 卡號(hào)//返 回: 0--成功; <0: 失敗//功 能: 獲取返回信息//開發(fā)人員: yangxh//修改記錄: 1. 第一次編寫.===============================================================================*/int GetInfo(char *recvbuf, stMACDATA *pst/*char *cardno*/){ int i; char startday[10], endday[10]; char temp[50]; char *ptr; memset(temp, 0x00, sizeof(temp)); memset(startday, 0x00, sizeof(startday)); memset(endday, 0x00, sizeof(endday)); if(recvbuf[0] != 0x00) return -1; if(recvbuf[1] != 0x6f) // FCI 模板 return -2; printf("FCI:[%02X]\n", recvbuf[2]); if(recvbuf[3] != 0x84) // DF 名 return -3; memcpy(temp, recvbuf+5, recvbuf[4]); printf("DF name:\n"); for(i = 0; i < recvbuf[4]; i++) { printf("%02X ", temp[i]); } printf("\n"); ptr = recvbuf + recvbuf[4] + 5; if(ptr[0] != 0xa5) // FCI 專用數(shù)據(jù) return -4;// printf("FCI Special Data:[%02X]\n", ptr[1]);// ptr = strstr(ptr, "\x9f\x08"); // 應(yīng)用版本號(hào)// printf("Version NO:[%02x%02x]\n", ptr[2], ptr[3]);// ptr += 4; ptr = strstr(ptr, "\x9f\x0c"); // 應(yīng)用版本號(hào) if(ptr != NULL)// 發(fā)送方自定義數(shù)據(jù) FCI { printf("Sender self define fci:[%02x]\n", ptr[2]); } else return -5; ptr += 3; printf("Author card flag:"); // 發(fā)卡方標(biāo)識(shí)符 memcpy(pst->bank_id, ptr, 8); for(i = 0; i < 8; i++) { printf("%02x ", ptr[i]); } printf("\n"); ptr += 8; printf("use type:[%02x]\n", ptr[0]); // 應(yīng)用類型標(biāo)識(shí) printf("version:[%02X]\n", ptr[1]); // 發(fā)卡方應(yīng)用版本號(hào) memset(temp, 0x00, sizeof(temp)); memcpy(temp, ptr+2, 10); // 應(yīng)用序列號(hào) memcpy(pst->card_no, ptr+2, 10);/* for(i = 0; i < 10; i++) { printf("%02X", temp[i]); sprintf(cardno+i*2, "%02X", temp[i]); } for(i = 0; i < 20; i++) { if(cardno[i] == 'F') { cardno[i] = '\0'; break; } } printf("card no:[%s]\n", cardno);*/ memset(temp, 0x00, sizeof(temp)); memcpy(temp, ptr+12, 4); // 應(yīng)用啟用日期 for(i = 0; i < 4; i++) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -