Module_Payment.c 33 KB

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