Module_Payment.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. /*
  2. * Module_Payment.c
  3. *
  4. * Created on: 2021/03/24
  5. * Author: Henry Yeh
  6. */
  7. #include "Module_Payment.h"
  8. unsigned char version[] = {'D', '0', '.', '0', '4'};
  9. unsigned char BLP_CMD_CARD_DETECT[] = {0x09, 0, 0x07, 'M','F','1','4','1','2','1', 0x32}; // Enable payment, MIFARE, 15693 card; Detect Payment Card First; Enable ApplePay VAS
  10. unsigned char BLP_CMD_USI2[] = {0x09, 0, 0x03, 'P', 'C', '0', 0x29}; // Configure protocol to USI2
  11. unsigned char BLP_CMD_SET_BAUD[] = {0x09, 0, 0x03, 'B', 'R', '7', 0x2d}; // Configure module baud rate to 115200
  12. unsigned char BLP_CMD_RESTORE_DEFAULT[] = {0x09, 0, 0x03, 'D', 'F', 0, 0x08 }; // Restore module configuration to default setting
  13. unsigned char BLP_CMD_TLV_ENABLE[] = {0x09, 0, 0x03, 'A', 'A', 'E', 'O'}; // Enable TLV command to support EMV transaction
  14. unsigned char BLP_CMD_SET_AID[] = {0x09, 0, 0x04, 'A', 'D', '0', 0, 0x38}; // Set AID type, 0x00: user defined AID 0x01: Default AID
  15. unsigned char BLP_CMD_LED_IND[] = {0x09, 0, 0x05, 'R', 'I', 'E', 0x01, 0x01, 'R'}; // Reader LED indicator
  16. unsigned char BLP_CMD_CA_PKEY[] = {0x09, 0, 0x03, 'C', 'K', 0x01, 0x03}; // Enable user CA Key
  17. unsigned char BLP_CMD_SOFTCARD_DISABLE[]= {0x09, 0, 0x03, 'I', 'S', 'D', 'T'}; // Disable soft card wallet application
  18. unsigned char BLP_CMD_BEEP_DISABLE[] = {0x09, 0, 0x03, 'B', 'A', 'D', 'M'}; // Beep disable
  19. unsigned char BLP_CMD_ERR_BEEP_STYLE[] = {0x09, 0, 0x03, 'B', 'D', 0, 0x0c}; // Error beep style configure 2 beeps
  20. unsigned char BLP_CMD_ERR_BEEP[] = {0x09, 0, 0x03, 'B', 'T', 'D', 'X'}; // Error beep give sound
  21. unsigned char BLP_CMD_LRC_ENABLE[] = {0x09, 0, 0x03, 'L', 'C', 'E', '@'}; // Enable LRC character of track data
  22. unsigned char BLP_CMD_TX_TRACK[] = {0x09, 0, 0x03, 'T', 'K', '3', '&'}; // Configure output track data 1&2
  23. unsigned char USI_CMD_WARM_RESET[] = {0x01, 0x00, 0x00, 0x01, 0x7f, 0x7f}; // Payment module warm reset
  24. unsigned char USI_CMD_MODULE_STATUS[] = {0x01, 0x00, 0x00, 0x01, 0x24, 0x24}; // Deactivate reader
  25. unsigned char USI_CMD_C8_DEACTIVAVE[] = {0x01, 0x00, 0x00, 0x02, 0xc8, 0x00, 0x00}; // Deactivate reader
  26. unsigned char USI_CMD_C8_POLL[] = {0x01, 0x00, 0x00, 0x2b, // STX, address, command length high byte, command length low byte
  27. 0xc8, 0x01, // Activate the reader
  28. 0x9f, 0x02, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // Amount, Authorized, sample: 100.00 dollar
  29. 0x5f, 0x2a, 0x02, 0x08, 0x40, // Transaction Currency Code follow ISO-4217, sample: 0840(USD)
  30. 0x5f, 0x36, 0x01, 0x02, // Transaction Currency Exponent, Identifies the decimal point position from the right of the transaction amount according to ISO 4217
  31. 0x9c, 0x01, 0x00, // Transaction Type, sample: 00
  32. 0x9a, 0x03, 0x21, 0x03, 0x24, // Transaction Date, sample: 2021/03/24
  33. 0x9f, 0x21, 0x03, 0x13, 0x36, 0x10, // Transaction Time, sample: 13:36:10
  34. 0xff, 0xff, 0x82, 0x05, 0x04, 0x00, 0x00, 0x01, 0x2c, // Command timeout unit is million second, sample: 300ms
  35. 0x00}; // Checksum
  36. unsigned char USI_CMD_HALT_CARD[] = {0x01, 0x00, 0x00, 0x01, 'x', 0x78}; // Halt card
  37. unsigned char USI_CMD_SET_DATE[] = {0x01, 0, 0, 0x07, '5', '4', 0x14, 0x15, 0x05, 0x02, 0x01, 0x18};
  38. unsigned char USI_CMD_SET_TIME[] = {0x01, 0, 0, 0x07, '5', '5', 0x0f, 0x1e, 0x20, 0, 0, 0x37};
  39. unsigned char USI_CMD_ARM_DISABLE[] = {0x01, 0, 0, 0x02, 'H', '0', '{'};
  40. unsigned char USI_CMD_NFC_ACTIVE[] = {0x01, 0, 0, 0x02, 'N', 0x00, 'M'}; // Enable NFC function
  41. unsigned char USI_CMD_NFC_POLL[] = {0x01, 0, 0, 0x05, 'N', ' ', '3', 0x02, 0x01, 'Z'}; // Polling FELICA(NFC Type 3, 414kbps)
  42. unsigned char USI_CMD_BEEP_CONTROL[] = {0x01, 0, 0, 0x05, 'B', '1', 0x7f, 0x09, 0x09, 0x08}; // Beep on 100ms 1 count
  43. int system_command(int uart, unsigned char* cmd, int cmd_len, unsigned char* rx);
  44. int USI2_Parse(unsigned char* rx, unsigned char* rx_data);
  45. struct C9_RESULT
  46. {
  47. unsigned char result_data[512]; // C9 response data without header & checksum
  48. unsigned char status; // C9 response status
  49. unsigned char pos_entry; // C9 response pos entry
  50. unsigned char u_id[20]; // Card SN
  51. unsigned char tkData[4][128]; // Card TK data for credit card
  52. unsigned char isCardPreset:1; // Card is presented on module, 0: removed 1: presented
  53. unsigned char isCommandError:1; // Polling command result, 0: normal 1: error
  54. } C9_Result;
  55. //==========================================
  56. // Common routine
  57. //==========================================
  58. int StoreLogMsg(const char *fmt, ...)
  59. {
  60. char Buf[65536+256];
  61. char buffer[65536];
  62. //char Buf[4096+256];
  63. //char buffer[4096];
  64. time_t CurrentTime;
  65. struct tm *tm;
  66. struct timeval tv;
  67. va_list args;
  68. va_start(args, fmt);
  69. int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
  70. va_end(args);
  71. memset(Buf,0,sizeof(Buf));
  72. CurrentTime = time(NULL);
  73. tm=localtime(&CurrentTime);
  74. gettimeofday(&tv, NULL); // get microseconds, 10^-6
  75. sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s\" >> /Storage/SystemLog/[%04d.%02d]PaymentLog",
  76. tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec,
  77. buffer,
  78. tm->tm_year+1900,tm->tm_mon+1);
  79. system((const char*)Buf);
  80. #ifdef ConsloePrintLog
  81. printf("[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec, buffer);
  82. #endif
  83. return rc;
  84. }
  85. /**
  86. * Execute shell command
  87. * @param cmd: shell command string
  88. * @return shell command execution result
  89. */
  90. int runShellCmd(const char*cmd)
  91. {
  92. int result = FAIL;
  93. char buf[256];
  94. FILE *fp;
  95. fp = popen(cmd, "r");
  96. if(fp != NULL)
  97. {
  98. while(fgets(buf, sizeof(buf), fp) != NULL)
  99. {
  100. DEBUG_INFO("%s\n", buf);
  101. }
  102. result = PASS;
  103. }
  104. pclose(fp);
  105. return result;
  106. }
  107. /**
  108. * Calculate time differential
  109. * @param ST: start time
  110. * @param ET: end time
  111. * @return time differential in million seconds
  112. */
  113. int DiffTimeb(struct timeb ST, struct timeb ET)
  114. {
  115. //return milli-second
  116. unsigned int StartTime,StopTime;
  117. StartTime=(unsigned int)ST.time;
  118. StopTime=(unsigned int)ET.time;
  119. return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
  120. }
  121. /**
  122. * Show communication raw data to debug info
  123. * @param data: raw data
  124. * @param len: data length
  125. * @param isRX: is receive data
  126. */
  127. void show_raw(uint8_t *data, uint16_t len, uint8_t isRX)
  128. {
  129. uint8_t output[8192];
  130. memset(output, 0x00, ARRAY_SIZE(output));
  131. sprintf((char*)output, "%s", (isRX?"RX: ":"TX: "));
  132. for(uint16_t idx = 0;idx<len;idx++)
  133. {
  134. sprintf((char*)output, "%s%02x ", output, data[idx]);
  135. }
  136. DEBUG_INFO("%s\n", output);
  137. }
  138. /**
  139. * Show data to debug info
  140. * @param dat: data content
  141. * @param len: data length
  142. */
  143. void show_data(unsigned char *dat, unsigned int len)
  144. {
  145. uint8_t output[8192];
  146. memset(output, 0x00, ARRAY_SIZE(output));
  147. sprintf((char*)output, "Data: ");
  148. for(uint16_t idx = 0;idx<len;idx++)
  149. {
  150. if(dat[idx] > 31 && dat[idx] < 128 )
  151. sprintf((char*)output, "%s%c", output, dat[idx]);
  152. else
  153. sprintf((char*)output, "%s<%x>", output, dat[idx]);
  154. }
  155. DEBUG_INFO("%s\n", output);
  156. }
  157. /**
  158. * Get sentinel quantity in data array
  159. * @param data: message array address
  160. * @param dataLen: array seek size
  161. * @return how many sentinel flag found
  162. */
  163. int getSentinelQuantity(unsigned char *data, unsigned int dataLen)
  164. {
  165. int result = 0;
  166. for(uint16_t idx=0;idx<dataLen;idx++)
  167. {
  168. if(data[idx] == '?')
  169. result++;
  170. }
  171. return result;
  172. }
  173. /**
  174. * Get sentinel position in array
  175. * @param data: message array address
  176. * @param dataLen: array seek size
  177. * @param idxSentinel: which sentinel idx want to find, since 0 start
  178. * @return sentinel position in array
  179. */
  180. int getSentinelPosition(unsigned char *data, unsigned int dataLen, unsigned char idxSentinel)
  181. {
  182. int result = -1;
  183. int foundCnt = -1;
  184. for(uint16_t idx=0;idx<dataLen;idx++)
  185. {
  186. if(data[idx] == '?')
  187. foundCnt++;
  188. if(foundCnt == idxSentinel)
  189. {
  190. result = idx;
  191. break;
  192. }
  193. }
  194. return result;
  195. }
  196. /**
  197. *
  198. * @param dec: number in dec
  199. * @return number in bcd
  200. */
  201. int decTobcd(int dec)
  202. {
  203. return (dec/10 * 16)+ (dec%10);
  204. }
  205. /**
  206. *
  207. * @param data: message array
  208. * @param dataLen: command & data field length in array
  209. * @return check sum result
  210. */
  211. int calChksum(unsigned char *data, unsigned int dataLen)
  212. {
  213. int result = 0;
  214. for(uint16_t idx=0;idx<dataLen-1;idx++)
  215. {
  216. result ^= data[idx];
  217. }
  218. return (result&0xff);
  219. }
  220. //==========================================
  221. // Init share memory
  222. //==========================================
  223. /**
  224. * Share memory initialization
  225. * @return function result
  226. */
  227. int InitShareMemory()
  228. {
  229. int result = PASS;
  230. int MeterSMId;
  231. #ifndef X86
  232. //init ShmSysConfigAndInfo
  233. if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
  234. {
  235. DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
  236. result = FAIL;
  237. }
  238. else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  239. {
  240. DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
  241. result = FAIL;
  242. }
  243. else
  244. {}
  245. //init ShmStatusCodeData
  246. if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
  247. {
  248. DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
  249. result = FAIL;
  250. }
  251. else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  252. {
  253. DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
  254. result = FAIL;
  255. }
  256. else
  257. {}
  258. #endif
  259. return result;
  260. }
  261. //==========================================
  262. // Init com port
  263. //==========================================
  264. /**
  265. * TTY port initialization
  266. * @return port initial result
  267. */
  268. int InitComPort()
  269. {
  270. int fd;
  271. struct termios tios;
  272. fd = open(TTY_PORT, O_RDWR);
  273. if(fd<=0)
  274. {
  275. return FAIL;
  276. }
  277. ioctl (fd, TCGETS, &tios);
  278. tios.c_cflag = B9600| CS8 | CLOCAL | CREAD;
  279. tios.c_lflag = 0;
  280. tios.c_iflag = 0;
  281. tios.c_oflag = 0;
  282. tios.c_cc[VMIN]=0; // data length threshold, 0 bytes
  283. tios.c_cc[VTIME]=(unsigned char)5; // timeout threshold, 0.5 seconds
  284. tios.c_lflag=0;
  285. tcflush(fd, TCIFLUSH);
  286. ioctl (fd, TCSETS, &tios);
  287. return fd;
  288. }
  289. /**
  290. * Send command to UIC680fg module.
  291. * @param uart: port handle
  292. * @param cmd: command buffer
  293. * @param cmd_len: command length
  294. * @param rx: receive buffer
  295. * @return receive data length
  296. */
  297. int system_command(int uart, unsigned char* cmd, int cmd_len, unsigned char* rx)
  298. {
  299. int rx_len = 0;
  300. tcflush(uart,TCIOFLUSH);
  301. //show_raw(cmd, cmd_len, NO);
  302. if(write(uart, cmd, cmd_len) > 0)
  303. {
  304. usleep(100000);
  305. rx_len = read(uart, rx, 512);
  306. //show_raw(rx, rx_len, YES);
  307. }
  308. else
  309. {
  310. DEBUG_ERROR("system command write fail.\n");
  311. }
  312. return rx_len;
  313. }
  314. /**
  315. * Parsing raw data to USI data
  316. * @param rx: raw data
  317. * @param rx_data: parsing result data
  318. * @return parsing result data length
  319. */
  320. int USI2_Parse(unsigned char* rx, unsigned char* rx_data)
  321. {
  322. int result = -1;
  323. unsigned int data_len =0;
  324. unsigned int chksum = 0;
  325. if(rx[0] == SOH) // SOH = 0x01
  326. {
  327. data_len = (unsigned int)rx[2] <<8;
  328. data_len |= rx[3];
  329. for(int idx=0;idx<(data_len+4);idx++)
  330. {
  331. chksum ^= rx[idx];
  332. }
  333. if((chksum&0xff) == rx[(data_len+4)])
  334. {
  335. memcpy(rx_data, &rx[4], data_len);
  336. result = data_len;
  337. }
  338. else
  339. DEBUG_WARN("USI2 message checksum error.\n");
  340. }
  341. else
  342. {
  343. DEBUG_WARN("USI2 message header is not <01>.\n");
  344. }
  345. return result;
  346. }
  347. /**
  348. *
  349. * @param onCnt: Buzzer on quantity
  350. */
  351. void buzzer_on(int UartFd, uint8_t onCnt)
  352. {
  353. unsigned char rx_Array[512]={0};
  354. USI_CMD_BEEP_CONTROL[5] = 0x30 + onCnt;
  355. USI_CMD_BEEP_CONTROL[ARRAY_SIZE(USI_CMD_BEEP_CONTROL)-1] = calChksum(USI_CMD_BEEP_CONTROL, ARRAY_SIZE(USI_CMD_BEEP_CONTROL));
  356. system_command(UartFd, USI_CMD_BEEP_CONTROL, ARRAY_SIZE(USI_CMD_BEEP_CONTROL), rx_Array);
  357. }
  358. //==========================================
  359. // Main loop
  360. //==========================================
  361. int main(void)
  362. {
  363. int UartFd;
  364. uint16_t failCount = 0;
  365. unsigned char rx_Array[512]={0}, rx_Data[512]={0};
  366. char C8_Polling = true;
  367. char Wait_C9 = false;
  368. int rx_len = 0;
  369. int data_len = 0;
  370. time_t CurrentTime;
  371. struct tm *tm;
  372. DEBUG_INFO("Task version: %s\n", version);
  373. //===============================================
  374. // Initialization
  375. //===============================================
  376. #ifndef X86
  377. if(InitShareMemory() == FAIL)
  378. {
  379. DEBUG_ERROR("InitShareMemory NG\n");
  380. if(ShmStatusCodeData!=NULL)
  381. {
  382. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
  383. }
  384. sleep(5);
  385. return FAIL;
  386. }
  387. #endif
  388. UartFd=InitComPort();
  389. if(UartFd<0)
  390. {
  391. DEBUG_ERROR("InitComPort NG\n");
  392. if(ShmStatusCodeData!=NULL)
  393. {
  394. #ifndef X86
  395. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
  396. #endif
  397. }
  398. sleep(5);
  399. return FAIL;
  400. }
  401. else
  402. {
  403. DEBUG_INFO("%s port open success.\n", TTY_PORT);
  404. }
  405. //===============================================
  406. // Payment module configuration set to default (BLP Protocol)
  407. //===============================================
  408. do
  409. {
  410. rx_len = system_command(UartFd, BLP_CMD_RESTORE_DEFAULT, ARRAY_SIZE(BLP_CMD_RESTORE_DEFAULT), rx_Array);
  411. if((rx_Array[0] == ACK) && (rx_len ==1))
  412. {
  413. DEBUG_INFO("Set to the default success.\n");
  414. failCount = 0;
  415. }
  416. else
  417. {
  418. DEBUG_WARN("Set to the default fail (<%02x>).\n", rx_Array[0]);
  419. failCount++;
  420. }
  421. if(failCount > RETRY_LIMIT)
  422. {
  423. DEBUG_ERROR("Set to the default fail over retry limit.\n");
  424. return FAIL;
  425. }
  426. }while((rx_Array[0] != ACK) || (rx_len != 1));
  427. //===============================================
  428. // set to protocol_2 (BLP Protocol)
  429. //===============================================
  430. do
  431. {
  432. rx_len =system_command(UartFd, BLP_CMD_USI2, ARRAY_SIZE(BLP_CMD_USI2), rx_Array);
  433. if((rx_Array[0] == ACK) && (rx_len ==1))
  434. {
  435. DEBUG_INFO("Set protocol to USI2 success.\n");
  436. DEBUG_INFO("Wait for payment module warm-reset.\n");
  437. sleep(10);
  438. failCount = 0;
  439. }
  440. else
  441. {
  442. DEBUG_WARN("Set protocol to USI2 fail (<%02x>).\n", rx_Array[0]);
  443. failCount++;
  444. }
  445. if(failCount > RETRY_LIMIT)
  446. {
  447. DEBUG_ERROR("Set protocol to USI2 fail over retry limit.\n");
  448. return FAIL;
  449. }
  450. }while((rx_Array[0] != ACK) || (rx_len !=1));
  451. //===============================================
  452. // Disable self-arm mode (USI2 Protocol)
  453. //===============================================
  454. do
  455. {
  456. USI_CMD_ARM_DISABLE[ARRAY_SIZE(USI_CMD_ARM_DISABLE)-1] = calChksum(USI_CMD_ARM_DISABLE, ARRAY_SIZE(USI_CMD_ARM_DISABLE));
  457. system_command(UartFd, USI_CMD_ARM_DISABLE, ARRAY_SIZE(USI_CMD_ARM_DISABLE), rx_Array);
  458. rx_len = USI2_Parse(rx_Array, rx_Data);
  459. if((rx_Data[0] == ACK) && (rx_len >= 0))
  460. {
  461. DEBUG_INFO("Set disable self-arm mode success.\n");
  462. failCount = 0;
  463. }
  464. else
  465. {
  466. DEBUG_WARN("Set disable self-arm mode fail (<%02x>).\n", rx_Data[0]);
  467. failCount++;
  468. }
  469. if(failCount > RETRY_LIMIT)
  470. {
  471. DEBUG_ERROR("Set disable self-arm mode fail over retry limit.\n");
  472. return FAIL;
  473. }
  474. }while((rx_Data[0] != ACK) || (rx_len < 0));
  475. //===============================================
  476. // Enable TLV command (BLP Protocol)
  477. //===============================================
  478. do
  479. {
  480. rx_len = system_command(UartFd, BLP_CMD_TLV_ENABLE, ARRAY_SIZE(BLP_CMD_TLV_ENABLE), rx_Array);
  481. if((rx_Array[0] == ACK) && (rx_len ==1))
  482. {
  483. DEBUG_INFO("Set enable TLV command success.\n");
  484. failCount = 0;
  485. }
  486. else
  487. {
  488. DEBUG_WARN("Set enable TLV command fail (<%02x>).\n", rx_Array[0]);
  489. failCount++;
  490. }
  491. if(failCount > RETRY_LIMIT)
  492. {
  493. DEBUG_ERROR("Set enable TLV command fail over retry limit.\n");
  494. return FAIL;
  495. }
  496. }while((rx_Array[0] != ACK) || (rx_len != 1));
  497. //===============================================
  498. // Set AID type (BLP Protocol)
  499. //===============================================
  500. do
  501. {
  502. rx_len = system_command(UartFd, BLP_CMD_SET_AID, ARRAY_SIZE(BLP_CMD_SET_AID), rx_Array);
  503. if((rx_Array[0] == ACK) && (rx_len ==1))
  504. {
  505. DEBUG_INFO("Set AID type success.\n");
  506. failCount = 0;
  507. }
  508. else
  509. {
  510. DEBUG_WARN("Set AID type fail (<%02x>).\n", rx_Array[0]);
  511. failCount++;
  512. }
  513. if(failCount > RETRY_LIMIT)
  514. {
  515. DEBUG_ERROR("Set AID type fail over retry limit.\n");
  516. return FAIL;
  517. }
  518. }while((rx_Array[0] != ACK) || (rx_len != 1));
  519. //===============================================
  520. // Set LED indicator (BLP Protocol)
  521. //===============================================
  522. do
  523. {
  524. rx_len = system_command(UartFd, BLP_CMD_LED_IND, ARRAY_SIZE(BLP_CMD_LED_IND), rx_Array);
  525. if((rx_Array[0] == ACK) && (rx_len ==1))
  526. {
  527. DEBUG_INFO("Set LED indicator success.\n");
  528. failCount = 0;
  529. }
  530. else
  531. {
  532. DEBUG_WARN("Set LED indicator fail (<%02x>).\n", rx_Array[0]);
  533. failCount++;
  534. }
  535. if(failCount > RETRY_LIMIT)
  536. {
  537. DEBUG_ERROR("Set LED indicator over retry limit.\n");
  538. return FAIL;
  539. }
  540. }while((rx_Array[0] != ACK) || (rx_len != 1));
  541. //===============================================
  542. // Set CA public key type (BLP Protocol)
  543. //===============================================
  544. do
  545. {
  546. rx_len = system_command(UartFd, BLP_CMD_CA_PKEY, ARRAY_SIZE(BLP_CMD_CA_PKEY), rx_Array);
  547. if((rx_Array[0] == ACK) && (rx_len ==1))
  548. {
  549. DEBUG_INFO("Set CA public key type success.\n");
  550. failCount = 0;
  551. }
  552. else
  553. {
  554. DEBUG_WARN("Set CA public key type fail (<%02x>).\n", rx_Array[0]);
  555. failCount++;
  556. }
  557. if(failCount > RETRY_LIMIT)
  558. {
  559. DEBUG_ERROR("Set CA public key type over retry limit.\n");
  560. return FAIL;
  561. }
  562. }while((rx_Array[0] != ACK) || (rx_len != 1));
  563. //===============================================
  564. // Set payment card detect type (BLP Protocol)
  565. //===============================================
  566. do
  567. {
  568. rx_len = system_command(UartFd, BLP_CMD_CARD_DETECT, ARRAY_SIZE(BLP_CMD_CARD_DETECT), rx_Array);
  569. if((rx_Array[0] == ACK) && (rx_len ==1))
  570. {
  571. DEBUG_INFO("Set payment card type success.\n");
  572. failCount = 0;
  573. }
  574. else
  575. {
  576. DEBUG_WARN("Set payment card type fail (<%02x>).\n", rx_Array[0]);
  577. failCount++;
  578. }
  579. if(failCount > RETRY_LIMIT)
  580. {
  581. DEBUG_ERROR("Set payment card type fail over retry limit.\n");
  582. return FAIL;
  583. }
  584. }while((rx_Array[0] != ACK) || (rx_len !=1));
  585. //===============================================
  586. // Disable soft card wallet application (BLP Protocol)
  587. //===============================================
  588. do
  589. {
  590. rx_len = system_command(UartFd, BLP_CMD_SOFTCARD_DISABLE, ARRAY_SIZE(BLP_CMD_SOFTCARD_DISABLE), rx_Array);
  591. if((rx_Array[0] == ACK) && (rx_len ==1))
  592. {
  593. DEBUG_INFO("Set disable soft card success.\n");
  594. failCount = 0;
  595. }
  596. else
  597. {
  598. DEBUG_WARN("Set disable soft card fail (<%02x>).\n", rx_Array[0]);
  599. failCount++;
  600. }
  601. if(failCount > RETRY_LIMIT)
  602. {
  603. DEBUG_ERROR("Set disable soft card fail over retry limit.\n");
  604. return FAIL;
  605. }
  606. }while((rx_Array[0] != ACK) || (rx_len !=1));
  607. //===============================================
  608. // Disable beep (BLP Protocol)
  609. //===============================================
  610. do
  611. {
  612. rx_len = system_command(UartFd, BLP_CMD_BEEP_DISABLE, ARRAY_SIZE(BLP_CMD_BEEP_DISABLE), rx_Array);
  613. if((rx_Array[0] == ACK) && (rx_len ==1))
  614. {
  615. DEBUG_INFO("Set beep disable success.\n");
  616. failCount = 0;
  617. }
  618. else
  619. {
  620. DEBUG_WARN("Set beep disable fail (<%02x>).\n", rx_Array[0]);
  621. failCount++;
  622. }
  623. if(failCount > RETRY_LIMIT)
  624. {
  625. DEBUG_ERROR("Set beep disable fail over retry limit.\n");
  626. return FAIL;
  627. }
  628. }while((rx_Array[0] != ACK) || (rx_len !=1));
  629. //===============================================
  630. // Set error beep style (BLP Protocol)
  631. //===============================================
  632. do
  633. {
  634. rx_len = system_command(UartFd, BLP_CMD_ERR_BEEP_STYLE, ARRAY_SIZE(BLP_CMD_ERR_BEEP_STYLE), rx_Array);
  635. if((rx_Array[0] == ACK) && (rx_len ==1))
  636. {
  637. DEBUG_INFO("Set error beep style success.\n");
  638. failCount = 0;
  639. }
  640. else
  641. {
  642. DEBUG_WARN("Set error beep style fail (<%02x>).\n", rx_Array[0]);
  643. failCount++;
  644. }
  645. if(failCount > RETRY_LIMIT)
  646. {
  647. DEBUG_ERROR("Set error beep style fail over retry limit.\n");
  648. return FAIL;
  649. }
  650. }while((rx_Array[0] != ACK) || (rx_len !=1));
  651. //===============================================
  652. // Set error beep (BLP Protocol)
  653. //===============================================
  654. do
  655. {
  656. rx_len = system_command(UartFd, BLP_CMD_ERR_BEEP, ARRAY_SIZE(BLP_CMD_ERR_BEEP), rx_Array);
  657. if((rx_Array[0] == ACK) && (rx_len ==1))
  658. {
  659. DEBUG_INFO("Set error beep success.\n");
  660. failCount = 0;
  661. }
  662. else
  663. {
  664. DEBUG_WARN("Set error beep fail (<%02x>).\n", rx_Array[0]);
  665. failCount++;
  666. }
  667. if(failCount > RETRY_LIMIT)
  668. {
  669. DEBUG_ERROR("Set error beep fail over retry limit.\n");
  670. return FAIL;
  671. }
  672. }while((rx_Array[0] != ACK) || (rx_len !=1));
  673. //===============================================
  674. // Set enable LRC (BLP Protocol)
  675. //===============================================
  676. do
  677. {
  678. rx_len = system_command(UartFd, BLP_CMD_LRC_ENABLE, ARRAY_SIZE(BLP_CMD_LRC_ENABLE), rx_Array);
  679. if((rx_Array[0] == ACK) && (rx_len ==1))
  680. {
  681. DEBUG_INFO("Set enable LRC success.\n");
  682. failCount = 0;
  683. }
  684. else
  685. {
  686. DEBUG_WARN("Set enable LRC fail (<%02x>).\n", rx_Array[0]);
  687. failCount++;
  688. }
  689. if(failCount > RETRY_LIMIT)
  690. {
  691. DEBUG_ERROR("Set enable LRC fail over retry limit.\n");
  692. return FAIL;
  693. }
  694. }while((rx_Array[0] != ACK) || (rx_len !=1));
  695. //===============================================
  696. // Set TX data tracks (BLP Protocol)
  697. //===============================================
  698. do
  699. {
  700. rx_len = system_command(UartFd, BLP_CMD_TX_TRACK, ARRAY_SIZE(BLP_CMD_TX_TRACK), rx_Array);
  701. if((rx_Array[0] == ACK) && (rx_len ==1))
  702. {
  703. DEBUG_INFO("Set TX data tracks success.\n");
  704. failCount = 0;
  705. }
  706. else
  707. {
  708. DEBUG_WARN("Set TX data tracks fail (<%02x>).\n", rx_Array[0]);
  709. failCount++;
  710. }
  711. if(failCount > RETRY_LIMIT)
  712. {
  713. DEBUG_ERROR("Set TX data tracks over retry limit.\n");
  714. return FAIL;
  715. }
  716. }while((rx_Array[0] != ACK) || (rx_len !=1));
  717. //===============================================
  718. // Set module RTC date (USI2 Protocol)
  719. //===============================================
  720. do
  721. {
  722. CurrentTime = time(NULL);
  723. tm=localtime(&CurrentTime);
  724. USI_CMD_SET_DATE[6] = ((tm->tm_year+1900)/100);
  725. USI_CMD_SET_DATE[7] = ((tm->tm_year+1900)%100);
  726. USI_CMD_SET_DATE[8] = (tm->tm_mon+1);
  727. USI_CMD_SET_DATE[9] = tm->tm_mday;
  728. USI_CMD_SET_DATE[10] = tm->tm_wday==0?0x07:tm->tm_wday;
  729. USI_CMD_SET_DATE[ARRAY_SIZE(USI_CMD_SET_DATE)-1] = calChksum(USI_CMD_SET_DATE, ARRAY_SIZE(USI_CMD_SET_DATE));
  730. system_command(UartFd, USI_CMD_SET_DATE, ARRAY_SIZE(USI_CMD_SET_DATE), rx_Array);
  731. rx_len = USI2_Parse(rx_Array, rx_Data);
  732. if((rx_Data[0] == ACK) && (rx_len >= 0))
  733. {
  734. DEBUG_INFO("Set module RTC date success.\n");
  735. failCount = 0;
  736. }
  737. else
  738. {
  739. DEBUG_WARN("Set module RTC date fail (<%02x>).\n", rx_Data[0]);
  740. failCount++;
  741. }
  742. if(failCount > RETRY_LIMIT)
  743. {
  744. DEBUG_ERROR("Set module RTC date fail over retry limit.\n");
  745. return FAIL;
  746. }
  747. }while((rx_Data[0] != ACK) || (rx_len < 0));
  748. //===============================================
  749. // Set module RTC time (USI2 Protocol)
  750. //===============================================
  751. do
  752. {
  753. CurrentTime = time(NULL);
  754. tm=localtime(&CurrentTime);
  755. USI_CMD_SET_TIME[6] = tm->tm_hour;
  756. USI_CMD_SET_TIME[7] = tm->tm_min;
  757. USI_CMD_SET_TIME[8] = tm->tm_sec;
  758. USI_CMD_SET_TIME[ARRAY_SIZE(USI_CMD_SET_TIME)-1] = calChksum(USI_CMD_SET_TIME, ARRAY_SIZE(USI_CMD_SET_TIME));
  759. system_command(UartFd, USI_CMD_SET_TIME, ARRAY_SIZE(USI_CMD_SET_TIME), rx_Array);
  760. rx_len = USI2_Parse(rx_Array, rx_Data);
  761. if((rx_Data[0] == ACK) && (rx_len >= 0))
  762. {
  763. DEBUG_INFO("Set module RTC time success.\n");
  764. failCount = 0;
  765. }
  766. else
  767. {
  768. DEBUG_WARN("Set module RTC time fail (<%02x>).\n", rx_Data[0]);
  769. failCount++;
  770. }
  771. if(failCount > RETRY_LIMIT)
  772. {
  773. DEBUG_ERROR("Set module RTC time fail over retry limit.\n");
  774. return FAIL;
  775. }
  776. }while((rx_Data[0] != ACK) || (rx_len < 0));
  777. DEBUG_INFO("Payment module initialize completed.\n");
  778. //===============================================
  779. // Main loop
  780. //===============================================
  781. for(;;)
  782. {
  783. USI_CMD_NFC_ACTIVE[ARRAY_SIZE(USI_CMD_NFC_ACTIVE)-1] = calChksum(USI_CMD_NFC_ACTIVE, ARRAY_SIZE(USI_CMD_NFC_ACTIVE));
  784. if(system_command(UartFd, USI_CMD_NFC_ACTIVE, ARRAY_SIZE(USI_CMD_NFC_ACTIVE), rx_Array) > 0)
  785. {
  786. rx_len = USI2_Parse(rx_Array, rx_Data);
  787. if((rx_Data[2] == 0x00) && (rx_len >= 0))
  788. {
  789. USI_CMD_NFC_POLL[ARRAY_SIZE(USI_CMD_NFC_POLL)-1] = calChksum(USI_CMD_NFC_POLL, ARRAY_SIZE(USI_CMD_NFC_POLL));
  790. if(system_command(UartFd, USI_CMD_NFC_POLL, ARRAY_SIZE(USI_CMD_NFC_POLL), rx_Array) > 0)
  791. {
  792. rx_len = USI2_Parse(rx_Array, rx_Data);
  793. if((rx_Data[2] == 0x00) && (rx_len >= 0))
  794. {
  795. // FELICA
  796. memcpy(&C9_Result.result_data, rx_Data, rx_len);
  797. C9_Result.status = C9_Result.result_data[2];
  798. C9_Result.pos_entry = Felica;
  799. memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
  800. memcpy(C9_Result.u_id, &C9_Result.result_data[6], 6);
  801. DEBUG_INFO("FELICA, UID: %02X-%02X-%02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3], C9_Result.u_id[4], C9_Result.u_id[5]);
  802. buzzer_on(UartFd, 1);
  803. // Wait card removed
  804. do
  805. {
  806. USI_CMD_NFC_POLL[ARRAY_SIZE(USI_CMD_NFC_POLL)-1] = calChksum(USI_CMD_NFC_POLL, ARRAY_SIZE(USI_CMD_NFC_POLL));
  807. system_command(UartFd, USI_CMD_NFC_POLL, ARRAY_SIZE(USI_CMD_NFC_POLL), rx_Array);
  808. rx_len = USI2_Parse(rx_Array, rx_Data);
  809. if((rx_Data[2] != 0x00) && (rx_len >= 0))
  810. {
  811. DEBUG_INFO("Card removed.\n");
  812. C9_Result.isCardPreset = OFF;
  813. failCount = 0;
  814. }
  815. else if((rx_Data[0] == 0x00) && (rx_len >= 0))
  816. {
  817. //DEBUG_INFO("Card seated.\n");
  818. C9_Result.isCardPreset = ON;
  819. failCount = 0;
  820. }
  821. else
  822. {
  823. DEBUG_WARN("Module status read fail (<%02x>).\n", rx_Data[0]);
  824. failCount++;
  825. }
  826. if(failCount > RETRY_LIMIT)
  827. {
  828. C9_Result.isCardPreset = OFF;
  829. DEBUG_ERROR("Module status read fail over retry limit.\n");
  830. }
  831. }while(((rx_Data[2] == 0x00) || (rx_len < 0)) && (failCount < RETRY_LIMIT));
  832. }
  833. else
  834. {
  835. // MIFARE, IDO-15693, Credit Card, Apple Pay in query
  836. if(C8_Polling == true)
  837. {
  838. Wait_C9 = false;
  839. CurrentTime = time(NULL);
  840. tm=localtime(&CurrentTime);
  841. USI_CMD_C8_DEACTIVAVE[ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE)-1] = calChksum(USI_CMD_C8_DEACTIVAVE, ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE));
  842. if(system_command(UartFd, USI_CMD_C8_DEACTIVAVE, ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE), rx_Array) > 0)
  843. {
  844. rx_len = USI2_Parse(rx_Array, rx_Data);
  845. if((rx_Data[0] == ACK) && (rx_len >= 0))
  846. {
  847. //DEBUG_INFO("C8 deactivate command success.\n");
  848. failCount = 0;
  849. USI_CMD_C8_POLL[9] = decTobcd((1000/10000000000)%100);
  850. USI_CMD_C8_POLL[10] = decTobcd((1000/100000000)%100);
  851. USI_CMD_C8_POLL[11] = decTobcd((1000/1000000)%100);
  852. USI_CMD_C8_POLL[12] = decTobcd((1000/10000)%100);
  853. USI_CMD_C8_POLL[13] = decTobcd((1000/100)%100);
  854. USI_CMD_C8_POLL[14] = decTobcd((1000/1)%100);
  855. USI_CMD_C8_POLL[18] = (CURRENCY_USD>>0x08)&0xff;
  856. USI_CMD_C8_POLL[19] = (CURRENCY_USD>>0x00)&0xff;
  857. USI_CMD_C8_POLL[29] = decTobcd((tm->tm_year+1900)-2000);
  858. USI_CMD_C8_POLL[30] = decTobcd(tm->tm_mon+1);
  859. USI_CMD_C8_POLL[31] = decTobcd(tm->tm_mday);
  860. USI_CMD_C8_POLL[35] = decTobcd(tm->tm_hour);
  861. USI_CMD_C8_POLL[36] = decTobcd(tm->tm_min);
  862. USI_CMD_C8_POLL[37] = decTobcd(tm->tm_sec);
  863. USI_CMD_C8_POLL[ARRAY_SIZE(USI_CMD_C8_POLL)-1] = calChksum(USI_CMD_C8_POLL, ARRAY_SIZE(USI_CMD_C8_POLL));
  864. if(system_command(UartFd, USI_CMD_C8_POLL, ARRAY_SIZE(USI_CMD_C8_POLL), rx_Array) > 0)
  865. {
  866. rx_len = USI2_Parse(rx_Array, rx_Data);
  867. if((rx_Data[0] == ACK) && (rx_len >= 0))
  868. {
  869. //DEBUG_INFO("C8 polling command success.\n");
  870. Wait_C9 = true;
  871. failCount = 0;
  872. C9_Result.isCommandError = OFF;
  873. }
  874. else
  875. {
  876. DEBUG_INFO("C8 polling command fail (<%02x>).\n", rx_Data[0]);
  877. C9_Result.isCommandError = ON;
  878. }
  879. }
  880. }
  881. else
  882. {
  883. DEBUG_INFO("C8 deactivate command fail.\n");
  884. C9_Result.isCommandError = ON;
  885. }
  886. }
  887. if(Wait_C9 == true)
  888. {
  889. //=============================================
  890. // wait card to attach the reader and wait C9
  891. //=============================================
  892. tcflush(UartFd,TCIOFLUSH);
  893. memset(rx_Array, 0x00, ARRAY_SIZE(rx_Array));
  894. rx_len = 0;
  895. do
  896. {
  897. //DEBUG_INFO("C9 response reading...\n");
  898. usleep(1000000);
  899. rx_len = read(UartFd, rx_Array, ARRAY_SIZE(rx_Array)); // read response if data count match 512 or timeout.
  900. failCount++;
  901. } while ((rx_len == 0) && (failCount < RETRY_LIMIT));
  902. //=============================================
  903. // Parse rx_Array to rx_Data
  904. //=============================================
  905. if((rx_len > 3) && (failCount < RETRY_LIMIT))
  906. {
  907. // print this raw data before parse it.
  908. //show_data(rx_Array, rx_len);
  909. if((rx_len = USI2_Parse( rx_Array, rx_Data)) > 0)
  910. {
  911. // debug the input data message
  912. //show_data(rx_Data, rx_len);
  913. // Copy RAW data to structure
  914. memcpy(&C9_Result.result_data, rx_Data, rx_len);
  915. C9_Result.status = C9_Result.result_data[1];
  916. C9_Result.pos_entry = C9_Result.result_data[2];
  917. switch(C9_Result.pos_entry)
  918. {
  919. case VISA_qVSDC:
  920. case VISA_MSD:
  921. case MASTER_MChip:
  922. case Master_MagStripe:
  923. case AMEX_EMV:
  924. case AMEX_MSD:
  925. memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
  926. memcpy(C9_Result.u_id, &C9_Result.result_data[5], 16);
  927. DEBUG_INFO("Credit card SN:\n");
  928. show_data(C9_Result.u_id, 16);
  929. for(uint8_t idx=0;idx<getSentinelQuantity(C9_Result.result_data, rx_len);idx++)
  930. {
  931. memset(C9_Result.tkData[idx], 0x00, ARRAY_SIZE(C9_Result.tkData[idx]));
  932. memcpy(C9_Result.tkData[idx],
  933. &C9_Result.result_data[((idx==0)?3:getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2)],
  934. (idx==0?getSentinelPosition(C9_Result.result_data, rx_len, idx)+1-3+1:getSentinelPosition(C9_Result.result_data, rx_len, idx)+1-getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2+1));
  935. DEBUG_INFO("TK[%d]: \n", idx);
  936. show_data(C9_Result.tkData[idx], getSentinelPosition(C9_Result.tkData[idx], ARRAY_SIZE(C9_Result.tkData[idx]), 0)+2);
  937. }
  938. buzzer_on(UartFd, 1);
  939. break;
  940. case Mifare:
  941. data_len = C9_Result.result_data[6];
  942. memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
  943. memcpy(C9_Result.u_id, &C9_Result.result_data[7], data_len);
  944. switch(C9_Result.result_data[3])
  945. {
  946. case MIFARE_ULTRALIGHT:
  947. DEBUG_INFO("MIFARE Ultralight, UID: %02X-%02X-%02X-%02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3], C9_Result.u_id[4], C9_Result.u_id[5], C9_Result.u_id[6]);
  948. break;
  949. case MIFARE_CLASSIC_1K:
  950. DEBUG_INFO("MIFARE Classic 1K, UID: %02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3]);
  951. break;
  952. case MIFARE_CLASSIC_4K:
  953. DEBUG_INFO("MIFARE Classic 4K, UID: %02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3]);
  954. break;
  955. case MIFARE_DESFIRE:
  956. DEBUG_INFO("MIFARE DESFire, UID: %02X-%02X-%02X-%02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3], C9_Result.u_id[4], C9_Result.u_id[5], C9_Result.u_id[6]);
  957. break;
  958. case MIFARE_PLUS_2K:
  959. DEBUG_INFO("MIFARE Plus 2k, UID: %02X-%02X-%02X-%02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3], C9_Result.u_id[4], C9_Result.u_id[5], C9_Result.u_id[6]);
  960. break;
  961. case MIFARE_MINI:
  962. DEBUG_INFO("MIFARE Mini, UID: %02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3]);
  963. break;
  964. case MIFARE_RESERVE:
  965. DEBUG_INFO("MIFARE Reserve, UID: \n");
  966. break;
  967. case MIFARE_JEWEL:
  968. DEBUG_INFO("MIFARE Jewel, UID: \n");
  969. break;
  970. case MIFARE_JCOP31:
  971. DEBUG_INFO("MIFARE JCOP31, UID: \n");
  972. break;
  973. }
  974. buzzer_on(UartFd, 1);
  975. break;
  976. case ISO_15693:
  977. data_len =(C9_Result.result_data[5]<<8) | C9_Result.result_data[6];
  978. memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
  979. memcpy(C9_Result.u_id, &C9_Result.result_data[4+data_len-8], 8);
  980. DEBUG_INFO("ISO_15693, UID: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", C9_Result.u_id[0], C9_Result.u_id[1], C9_Result.u_id[2], C9_Result.u_id[3], C9_Result.u_id[4], C9_Result.u_id[5], C9_Result.u_id[6], C9_Result.u_id[7]);
  981. buzzer_on(UartFd, 1);
  982. break;
  983. case Apple_Pay:
  984. DEBUG_INFO("Apple_Pay VAS only.\n");
  985. for(uint8_t idx=0;idx<getSentinelQuantity(C9_Result.result_data, rx_len);idx++)
  986. {
  987. memcpy(C9_Result.tkData[idx],
  988. &C9_Result.result_data[((idx==0)?3:getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2)],
  989. (idx==0?getSentinelPosition(C9_Result.result_data, rx_len, idx)+1-3+1:getSentinelPosition(C9_Result.result_data, rx_len, idx)+1-getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2+1));
  990. DEBUG_INFO("TK[%d]: \n", idx);
  991. show_data(C9_Result.tkData[idx], getSentinelPosition(C9_Result.tkData[idx], ARRAY_SIZE(C9_Result.tkData[idx]), 0)+2);
  992. }
  993. buzzer_on(UartFd, 1);
  994. break;
  995. case No_Data:
  996. //DEBUG_INFO("No any data.\n");
  997. break;
  998. default:
  999. DEBUG_WARN("Unknown pos entry.\n");
  1000. if(C9_Result.status == C9_RES_C8_CMD_TIMEOUT)
  1001. DEBUG_WARN("C8 command timeout.\n");
  1002. else if(C9_Result.status == C9_RES_CMD_EXECUTING)
  1003. DEBUG_WARN("Command executing or Wait Card to be Removed.\n");
  1004. break;
  1005. }
  1006. failCount = 0;
  1007. // Wait card removed
  1008. if(C9_Result.pos_entry != No_Data)
  1009. {
  1010. do
  1011. {
  1012. system_command(UartFd, USI_CMD_MODULE_STATUS, ARRAY_SIZE(USI_CMD_MODULE_STATUS), rx_Array);
  1013. rx_len = USI2_Parse(rx_Array, rx_Data);
  1014. if(!(rx_Data[0]&0x02) && (rx_len >= 0))
  1015. {
  1016. DEBUG_INFO("Card removed.\n");
  1017. C9_Result.isCardPreset = OFF;
  1018. failCount = 0;
  1019. }
  1020. else if((rx_Data[0]&0x02) && (rx_len >= 0))
  1021. {
  1022. //DEBUG_INFO("Card seated.\n");
  1023. C9_Result.isCardPreset = ON;
  1024. failCount = 0;
  1025. }
  1026. else
  1027. {
  1028. DEBUG_WARN("Module status read fail (<%02x>).\n", rx_Data[0]);
  1029. failCount++;
  1030. }
  1031. if(failCount > RETRY_LIMIT)
  1032. {
  1033. C9_Result.isCardPreset = OFF;
  1034. DEBUG_ERROR("Module status read fail over retry limit.\n");
  1035. }
  1036. }while(((rx_Data[0]&0x02) || (rx_len < 0)) && (failCount < RETRY_LIMIT));
  1037. }
  1038. }
  1039. else
  1040. {
  1041. DEBUG_INFO("C9 Parsing result fail.\n");
  1042. C9_Result.isCommandError = ON;
  1043. buzzer_on(UartFd, 3);
  1044. // Wait card removed
  1045. do
  1046. {
  1047. usleep(500000);
  1048. system_command(UartFd, USI_CMD_MODULE_STATUS, ARRAY_SIZE(USI_CMD_MODULE_STATUS), rx_Array);
  1049. rx_len = USI2_Parse(rx_Array, rx_Data);
  1050. if(!(rx_Data[0]&0x02) && (rx_len >= 0))
  1051. {
  1052. DEBUG_INFO("Card removed.\n");
  1053. C9_Result.isCardPreset = OFF;
  1054. C9_Result.isCommandError = OFF;
  1055. failCount = 0;
  1056. }
  1057. else if((rx_Data[0]&0x02) && (rx_len >= 0))
  1058. {
  1059. //DEBUG_INFO("Card seated.\n");
  1060. C9_Result.isCardPreset = ON;
  1061. failCount = 0;
  1062. }
  1063. else
  1064. {
  1065. DEBUG_WARN("Module status read fail (<%02x>).\n", rx_Data[0]);
  1066. failCount++;
  1067. }
  1068. if(failCount > RETRY_LIMIT)
  1069. {
  1070. C9_Result.isCardPreset = OFF;
  1071. DEBUG_ERROR("Module status read fail over retry limit.\n");
  1072. }
  1073. }while(((rx_Data[0]&0x02) || (rx_len < 0)) && (failCount < RETRY_LIMIT));
  1074. }
  1075. }
  1076. else
  1077. {
  1078. DEBUG_WARN("C9 Response timeout: %d \n", failCount);
  1079. buzzer_on(UartFd, 3);
  1080. }
  1081. }
  1082. }
  1083. }
  1084. }
  1085. }
  1086. }
  1087. usleep(500000);
  1088. }
  1089. return FAIL;
  1090. }