contactlessimpl.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. #include "contactlessimpl.h"
  2. #include "cmb.h"
  3. #define DEVICE_NAME "CREATOR CRT-603 (CZ1) CCR RF 0"
  4. ContactlessCardImpl::ContactlessCardImpl()
  5. {
  6. m_pConnect = new CPcscLibrary();
  7. m_bCardConn = false;
  8. }
  9. ContactlessCardImpl::~ContactlessCardImpl()
  10. {
  11. delete m_pConnect;
  12. }
  13. ErrorCodeEnum ContactlessCardImpl::DevOpen(DWORD dwPort,DWORD dwBaudRate)
  14. {
  15. LOG4VTM_FUNCTION();
  16. char cFilePath[300] = {0};
  17. GetCurLibsPath(m_sLibPath, cFilePath);
  18. sprintf(cFilePath, "DevOpen GetCurProcPath = %s", m_sLibPath);
  19. LOG4VTM(INFO, cFilePath);
  20. sprintf(cFilePath, "%s/cw/libCRT603.cw.so", m_sLibPath); //usr symbolic link to point the real so
  21. bool bOK = m_pConnect->Load(cFilePath, cFilePath);
  22. if (!bOK) return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen");
  23. int iCount = 0;
  24. int iRt = m_pConnect->OpenConnect(&iCount);
  25. if (iRt != 0)
  26. return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen OpenConnect %d", iRt);
  27. iRt = m_pConnect->SetReaderName(0);
  28. if (iRt != 0)
  29. return GetErrorInfo(PCSC_HARDWARE_ERROR, "DevOpen SetReaderName %d", iRt);
  30. return GetErrorInfo(0, "DevOpen %d", iRt);
  31. }
  32. int getFileVer(char* sFile, short& ch1, short& ch2)
  33. {
  34. ch1 = 0;
  35. ch2 = 0;
  36. char* pFind = strstr(sFile, ".so");
  37. char* pTemp = pFind;
  38. while (pTemp)
  39. {
  40. pFind = pTemp;
  41. pTemp = strstr(pFind + 3, ".so");
  42. }
  43. if (pFind == NULL) return 0;
  44. pTemp = pFind - 1;
  45. while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
  46. if (*pTemp == '.')
  47. ch2 = atoi(pTemp+1);
  48. pTemp--;
  49. while(isdigit(*pTemp) && pTemp > sFile) pTemp--;
  50. if (*pTemp == '.')
  51. ch1 = atoi(pTemp+1);
  52. return 1;
  53. }
  54. ErrorCodeEnum ContactlessCardImpl::GetDevCategory(DevCategoryInfo &devCategory)
  55. {
  56. LOG4VTM_FUNCTION();
  57. if (!m_pConnect->IsLoadSucceed())
  58. return GetErrorInfo(PCSC_NOT_OPEN, "GetDevCategory");
  59. ErrorCodeEnum err = Error_Succeed;
  60. char sSer[256];
  61. memset(sSer, 0, sizeof(sSer));
  62. if (m_pConnect->GetVersionInfo(2, sSer) == 0)
  63. {
  64. sSer[32] = 0;
  65. strcpy(devCategory.szType, sSer);
  66. }
  67. else
  68. strcpy(devCategory.szType, DEVICE_NAME);
  69. strcpy(devCategory.szModel, "WID=Cashway001");
  70. strcpy(devCategory.szVendor, "cw");
  71. char cFilePath[300] = {0};
  72. GetCurLibsPath(m_sLibPath, cFilePath);
  73. short v1,v2;
  74. getFileVer(cFilePath, v1, v2);
  75. devCategory.version.wMajor = v1;
  76. devCategory.version.wMinor = v2;
  77. devCategory.version.wRevision = 0xffff;
  78. devCategory.version.wBuild = FILE_VERSION;
  79. char szRet[512] = {0};
  80. sprintf(szRet, "szType:%s,szModel:%s,szVendor:%s,version.wMajor:%d,version.wMinor:%d,version.wBuild:%d,version.wRevision:%d,eState:%d(0:故障1:正常)",
  81. devCategory.szType,devCategory.szModel,devCategory.szVendor,devCategory.version.wMajor,devCategory.version.wMinor,devCategory.version.wBuild,devCategory.version.wRevision,devCategory.eState);
  82. LOG4VTM(INFO, szRet);
  83. return Error_Succeed;
  84. }
  85. ErrorCodeEnum ContactlessCardImpl::Reset()
  86. {
  87. LOG4VTM_FUNCTION();
  88. if (!m_pConnect->IsLoadSucceed())
  89. return GetErrorInfo(PCSC_NOT_OPEN, "Reset");
  90. m_pConnect->CloseConnect();
  91. int iCount = 0;
  92. int iRt = m_pConnect->OpenConnect(&iCount);
  93. if (iRt != 0)
  94. return GetErrorInfo(PCSC_HARDWARE_ERROR, "Reset OpenConnect %d", iRt);
  95. iRt = m_pConnect->SetReaderName(0);
  96. if (iRt != 0)
  97. return GetErrorInfo(PCSC_HARDWARE_ERROR, "Reset SetReaderName %d", iRt);
  98. return GetErrorInfo(0, "Reset %d", iRt);
  99. }
  100. ErrorCodeEnum ContactlessCardImpl::DevClose()
  101. {
  102. LOG4VTM_FUNCTION();
  103. if (!m_pConnect->IsLoadSucceed())
  104. return GetErrorInfo(PCSC_NOT_OPEN, "DevClose");
  105. m_pConnect->CloseConnect();
  106. ErrorCodeEnum err = Error_Succeed;
  107. return err;
  108. }
  109. // DEC_SUCCESS DEC_HARDWARE DEC_TIMEOUT DEC_INVALID_PARAMETER DEC_INVALID_MASTER_KEY
  110. const static CmbErrorDef RFICErrorDat[] = {
  111. {0, "成功", Error_Succeed, DEC_SUCCESS},
  112. {PCSC_NOT_OPEN, "设备没有打开", Error_Hardware, DEC_DEV_NOT_OPENED},
  113. {PCSC_HARDWARE_ERROR,"设备硬件故障", Error_Hardware, DEC_HARDWARE},
  114. {PCSC_TIMEOUT, "设备响应超时", Error_DevCommFailed, DEC_TIMEOUT},
  115. {PCSC_PARA_ERR, "传入参数错误", Error_Param, DEC_INVALID_PARAMETER},
  116. {PCSC_NOT_CONN, "未建立连接", Error_DevMedia, DEC_INVALID_PARAMETER},
  117. {PCSC_NO_CARD, "未检测到卡", Error_DevMedia, DEC_INVALID_PARAMETER},
  118. {-105, "卡已经移除", Error_DevMedia, DEC_INVALID_PARAMETER},
  119. };
  120. ErrorCodeEnum ContactlessCardImpl::GetErrorInfo(int iCode, char* sErr, ...)
  121. {
  122. size_t iLenOne = sizeof(CmbErrorDef);
  123. size_t iLenAll = sizeof(RFICErrorDat);
  124. int iCount = iLenAll / iLenOne;
  125. char sErrInfo[256]="";
  126. DWORD dSta = 0;
  127. int iErr = -1;
  128. for (int ia = 0; ia < iCount; ia++)
  129. {
  130. if (RFICErrorDat[ia].iCode == iCode)
  131. {
  132. dSta = RFICErrorDat[ia].iInf;
  133. strcpy(sErrInfo, RFICErrorDat[ia].sInf);
  134. iErr = RFICErrorDat[ia].iRet;
  135. break;
  136. }
  137. }
  138. char sErrAll[300];
  139. va_list arglist;
  140. va_start(arglist, sErr);
  141. _vsnprintf(sErrAll, 128, sErr, arglist);
  142. va_end(arglist);
  143. if (sErrInfo[0])
  144. {
  145. strcat(sErrAll, " ");
  146. strcat(sErrAll, sErrInfo);
  147. }
  148. sErrAll[200] = 0;
  149. iLenOne = strlen(sErrAll);
  150. sprintf(m_DevErrInfo.szErrMsg, "{\"ErrCode\":\"%04x\",\"Description\":\"%s\"}", iErr, sErrAll);
  151. // strcpy(m_DevErrInfo.szErrMsg, sErrAll);
  152. m_DevErrInfo.dwErrMsgLen = ((dSta << 16) & 0xffff0000) + iLenOne;
  153. if (iErr != Error_Succeed)
  154. LOG4VTM(WARN, m_DevErrInfo.szErrMsg);
  155. else
  156. LOG4VTM(INFO, m_DevErrInfo.szErrMsg);
  157. return (ErrorCodeEnum)iErr;
  158. }
  159. ErrorCodeEnum ContactlessCardImpl::GetLastErr(DevErrorInfo &devErrInfo)
  160. {
  161. memcpy(&devErrInfo, &m_DevErrInfo, sizeof(DevErrorInfo));
  162. return Error_Succeed;
  163. }
  164. //
  165. ErrorCodeEnum ContactlessCardImpl::GetDevStatus(RFICReaderStatus& devStatus)
  166. {
  167. LOG4VTM_FUNCTION();
  168. if (!m_pConnect->IsLoadSucceed())
  169. return GetErrorInfo(PCSC_NOT_OPEN, "GetDevStatus");
  170. int ia = m_pConnect->GetCardStatus();
  171. switch(ia){
  172. case 1:
  173. devStatus.eMediaPos = CI_MEDIA_RF;
  174. break;
  175. case 2:
  176. devStatus.eMediaPos = CI_MEDIA_NOTPRESENT;
  177. m_bCardConn = false;
  178. break;
  179. default:
  180. devStatus.eMediaPos = CI_MEDIA_NOTPRESENT;
  181. m_bCardConn = false;
  182. }
  183. return Error_Succeed;
  184. }
  185. //
  186. // Abort current operation.
  187. //
  188. ErrorCodeEnum ContactlessCardImpl::AbortRead()
  189. {
  190. return Error_Succeed;
  191. }
  192. //
  193. // Active contactless card(Type A,B,Mifare)
  194. // The first,second,third activation order decided by fstType,scdType,thdType respectively
  195. // fstType,scdType,thdType can be one of 'A','B','M','0'(30H,no type)
  196. // outType indicates the type of activation result
  197. //
  198. ErrorCodeEnum ContactlessCardImpl::ActiveContactlessICCard(char fstType, char scdType, char thdType, char& outType)
  199. {
  200. LOG4VTM_FUNCTION();
  201. if (!m_pConnect->IsLoadSucceed())
  202. return GetErrorInfo(PCSC_NOT_OPEN, "ActiveContactlessICCard");
  203. BYTE byAtrData[256] = {0};
  204. int iAtrLen = 0;
  205. m_bCardConn = false;
  206. int iRet = m_pConnect->ReaderConnect(byAtrData, &iAtrLen);
  207. if (iRet != 0 || iAtrLen < 1)
  208. {
  209. outType = '0';
  210. return GetErrorInfo(PCSC_NO_CARD, "ActiveContactlessICCard ReaderConnect %d %s", iRet, m_pConnect->GetLastError());
  211. }
  212. char sHexData[512];
  213. ::ANSIToHexStr(byAtrData, iAtrLen, sHexData);
  214. printf("ATR %d %s\n", iAtrLen, sHexData);
  215. outType = 'A';
  216. if (strcmp(sHexData, "3B8F8001804F0CA000000306030001E00000018B") == 0)
  217. outType = '0';
  218. if (strcmp(sHexData, "3B8F8001804F0CA000000306030001000000006A") == 0) // 公交卡、房卡
  219. outType = 'M';
  220. if (strcmp(sHexData, "3B8F8001804F0CA0000003060300020000000069") == 0)
  221. outType = 'M';
  222. if (strcmp(sHexData, "3B8F8001804F0CA000000306030001E00000018B") == 0)
  223. outType = '0';
  224. // if (strcmp(sHexData, "3B8E800180318066B1C5240100ED83009000F7") == 0) //
  225. // outType = '2';
  226. if (iAtrLen == 13 && strstr(sHexData, "3B888001D103")) //身份证
  227. outType = 'B';
  228. m_bCardConn = true;
  229. return GetErrorInfo(iRet, "ActiveContactlessICCard");
  230. }
  231. //
  232. // Deactivate contactless IC card
  233. //
  234. ErrorCodeEnum ContactlessCardImpl::DeactContactlessICCard()
  235. {
  236. LOG4VTM_FUNCTION();
  237. if (!m_pConnect->IsLoadSucceed())
  238. return GetErrorInfo(PCSC_NOT_OPEN, "DeactContactlessICCard");
  239. m_bCardConn = false;
  240. int iRet = m_pConnect->EjectCard();
  241. if (iRet == 0)
  242. return GetErrorInfo(0, "DeactContactlessICCard");
  243. return GetErrorInfo(PCSC_HARDWARE_ERROR, "ActiveCDeactContactlessICCard %d", iRet);;
  244. }
  245. //
  246. // Warm reset card(IC)
  247. //
  248. ErrorCodeEnum ContactlessCardImpl::WarmReset()
  249. {
  250. LOG4VTM_FUNCTION();
  251. if (!m_pConnect->IsLoadSucceed())
  252. return GetErrorInfo(PCSC_NOT_OPEN, "WarmReset");
  253. m_bCardConn = false;
  254. if (m_pConnect->GetCardStatus() != 1)
  255. return GetErrorInfo(PCSC_NO_CARD, "WarmReset");
  256. int iRet = m_pConnect->EjectCard();
  257. if (iRet != 0)
  258. return GetErrorInfo(iRet, "WarmReset");
  259. BYTE byAtrData[256] = {0};
  260. int iAtrLen = 0;
  261. iRet = m_pConnect->ReaderConnect(byAtrData, &iAtrLen);
  262. if (iRet == 0)
  263. {
  264. m_bCardConn = true;
  265. return GetErrorInfo(0, "WarmReset");
  266. }
  267. return GetErrorInfo(PCSC_HARDWARE_ERROR, "WarmReset %d", iRet);;
  268. }
  269. //
  270. // Mifare operation
  271. // Arguments:
  272. // - eFunType:function type as load key,authentication and so on
  273. // - return/data(hex) byte order like BIG EDIAN. ex:0x12345678 --> data[i] = 0x12,data[i+1] = 0x34,data[i+2] = 0x56,data[i+3] = 0x78
  274. // - sendBuf:[parameter(hex)][data(hex)]
  275. // - recvBuf:[status(1byte)][return data(hex)]
  276. // -- [eFunType],[parameter,data],[status(1byte),return data]
  277. // -- [CI_MIFARE_LOAD_KEY],[key select(1byte),sector num(1byte),uncoded keys(6bytes)],[status(1byte)]
  278. // -- [CI_MIFARE_AUTH],[key select(1byte),sector num(1byte)],[status(1byte)]
  279. // -- [CI_MIFARE_READ],[block num(1byte)],[status(1byte),data(16bytes)]
  280. // -- [CI_MIFARE_WRITE],[block num(1byte),data(16bytes)],[status(1byte)]
  281. // -- [CI_MIFARE_INC],[source block num(1byte),destination block num(1byte),inc value(4bytes)],[status(1byte)]
  282. // -- [CI_MIFARE_DEC],[source block num(1byte),destination block num(1byte),dec value(4bytes)],[status(1byte)]
  283. // -- key select(1byte):AKey(00h),BKey(01h)
  284. // -- status(1byte):OK(00h),other error code(!00h)
  285. ErrorCodeEnum ContactlessCardImpl::MifareCommand(MifareFuctionEnum eFunType, CmdInfo sendBuf, CmdInfo& recvBuf)
  286. {
  287. LOG4VTM_FUNCTION();
  288. return Error_NotImpl;
  289. }
  290. //
  291. // RF Type A,B command.
  292. // APDU:Application Protocol Data Unit
  293. // Arguments:
  294. // - CmdSend.lpCmd:Command-APDU
  295. // - CmdRecv.lpData:Response-APDU
  296. //
  297. ErrorCodeEnum ContactlessCardImpl::RFTypeABCommand(CmdInfo sendBuf, CmdInfo& recvBuf)
  298. {
  299. LOG4VTM_FUNCTION();
  300. if (m_bCardConn == false)
  301. return GetErrorInfo(PCSC_NOT_CONN, "RFTypeABCommand");
  302. unsigned char sAnsi[1024];
  303. int iRetCount = 0;
  304. ::HexStrToANSI((char*)sendBuf.data, sAnsi, sendBuf.dwSize);
  305. int iRet = m_pConnect->SendApdu(sAnsi, sendBuf.dwSize << 1, sAnsi, &iRetCount);
  306. if (iRet != 0)
  307. return GetErrorInfo(iRet, "RFTypeABCommand SendApdu %d %s", iRet, m_pConnect->GetLastError());
  308. ::ANSIToHexStr(sAnsi, iRetCount, (char*)recvBuf.data);
  309. recvBuf.dwSize = iRetCount << 1;
  310. return Error_Succeed;
  311. }
  312. //halt card
  313. //card have been halted must move from induction zone then can be found again
  314. ErrorCodeEnum ContactlessCardImpl::HaltCard()
  315. {
  316. LOG4VTM_FUNCTION();
  317. if (!m_pConnect->IsLoadSucceed())
  318. return GetErrorInfo(PCSC_NOT_OPEN, "HaltCard");
  319. int iRet = m_pConnect->EjectCard();
  320. if (iRet == 0)
  321. {
  322. m_bCardConn = false;
  323. return GetErrorInfo(0, "HaltCard");
  324. }
  325. return GetErrorInfo(PCSC_HARDWARE_ERROR, "HaltCard %d", iRet);;
  326. }