12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094 |
- /*
- * Module_Payment.c
- *
- * Created on: 2021/03/24
- * Author: Henry Yeh
- */
- #include "Module_Payment.h"
- unsigned char version[] = {'D', '0', '.', '0', '3'};
- 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
- unsigned char BLP_CMD_USI2[] = {0x09, 0, 0x03, 'P', 'C', '0', 0x29}; // Configure protocol to USI2
- unsigned char BLP_CMD_SET_BAUD[] = {0x09, 0, 0x03, 'B', 'R', '7', 0x2d}; // Configure module baud rate to 115200
- unsigned char BLP_CMD_RESTORE_DEFAULT[] = {0x09, 0, 0x03, 'D', 'F', 0, 0x08 }; // Restore module configuration to default setting
- unsigned char BLP_CMD_TLV_ENABLE[] = {0x09, 0, 0x03, 'A', 'A', 'E', 'O'}; // Enable TLV command to support EMV transaction
- unsigned char BLP_CMD_SET_AID[] = {0x09, 0, 0x04, 'A', 'D', '0', 0, 0x38}; // Set AID type, 0x00: user defined AID 0x01: Default AID
- unsigned char BLP_CMD_LED_IND[] = {0x09, 0, 0x05, 'R', 'I', 'E', 0x01, 0x01, 'R'}; // Reader LED indicator
- unsigned char BLP_CMD_CA_PKEY[] = {0x09, 0, 0x03, 'C', 'K', 0x01, 0x03}; // Enable user CA Key
- unsigned char BLP_CMD_SOFTCARD_DISABLE[]= {0x09, 0, 0x03, 'I', 'S', 'D', 'T'}; // Disable soft card wallet application
- unsigned char BLP_CMD_ERR_BEEP_STYLE[] = {0x09, 0, 0x03, 'B', 'D', 0, 0x0c}; // Error beep style configure 2 beeps
- unsigned char BLP_CMD_ERR_BEEP[] = {0x09, 0, 0x03, 'B', 'T', 'D', 'X'}; // Error beep give sound
- unsigned char BLP_CMD_LRC_ENABLE[] = {0x09, 0, 0x03, 'L', 'C', 'E', '@'}; // Enable LRC character of track data
- unsigned char BLP_CMD_TX_TRACK[] = {0x09, 0, 0x03, 'T', 'K', '3', '&'}; // Configure output track data 1&2
- unsigned char USI_CMD_WARM_RESET[] = {0x01, 0x00, 0x00, 0x01, 0x7f, 0x7f}; // Payment module warm reset
- unsigned char USI_CMD_MODULE_STATUS[] = {0x01, 0x00, 0x00, 0x01, 0x24, 0x24}; // Deactivate reader
- unsigned char USI_CMD_C8_DEACTIVAVE[] = {0x01, 0x00, 0x00, 0x02, 0xc8, 0x00, 0x00}; // Deactivate reader
- unsigned char USI_CMD_C8_POLL[] = {0x01, 0x00, 0x00, 0x2b, // STX, address, command length high byte, command length low byte
- 0xc8, 0x01, // Activate the reader
- 0x9f, 0x02, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // Amount, Authorized, sample: 100.00 dollar
- 0x5f, 0x2a, 0x02, 0x08, 0x40, // Transaction Currency Code follow ISO-4217, sample: 0840(USD)
- 0x5f, 0x36, 0x01, 0x02, // Transaction Currency Exponent, Identifies the decimal point position from the right of the transaction amount according to ISO 4217
- 0x9c, 0x01, 0x00, // Transaction Type, sample: 00
- 0x9a, 0x03, 0x21, 0x03, 0x24, // Transaction Date, sample: 2021/03/24
- 0x9f, 0x21, 0x03, 0x13, 0x36, 0x10, // Transaction Time, sample: 13:36:10
- 0xff, 0xff, 0x82, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // Command timeout unit is million second, sample: umlimit
- 0x00}; // Checksum
- unsigned char USI_CMD_HALT_CARD[] = {0x01, 0x00, 0x00, 0x01, 'x', 0x78}; // Halt card
- unsigned char USI_CMD_SET_DATE[] = {0x01, 0, 0, 0x07, '5', '4', 0x14, 0x15, 0x05, 0x02, 0x01, 0x18};
- unsigned char USI_CMD_SET_TIME[] = {0x01, 0, 0, 0x07, '5', '5', 0x0f, 0x1e, 0x20, 0, 0, 0x37};
- unsigned char USI_CMD_ARM_DISABLE[] = {0x01, 0, 0, 0x02, 'H', '0', '{'};
- unsigned char USI_CMD_NFC_POLL[] = {0x01, 0, 0, 0x05, 'N', ' ', '3', 0x02, 0x01, 'Z'}; // Polling FELICA(NFC Type 3, 414kbps)
- int system_command(int uart, unsigned char* cmd, int cmd_len, unsigned char* rx);
- int USI2_Parse(unsigned char* rx, unsigned char* rx_data);
- struct C9_RESULT
- {
- unsigned char result_data[512]; // C9 response data without header & checksum
-
- unsigned char status; // C9 response status
- unsigned char pos_entry; // C9 response pos entry
- unsigned char u_id[20]; // Card SN
- unsigned char tkData[4][128]; // Card TK data for credit card
- unsigned char isCardPreset:1; // Card is presented on module, 0: removed 1: presented
- unsigned char isCommandError:1; // Polling command result, 0: normal 1: error
- } C9_Result;
- //==========================================
- // Common routine
- //==========================================
- int StoreLogMsg(const char *fmt, ...)
- {
- char Buf[65536+256];
- char buffer[65536];
- //char Buf[4096+256];
- //char buffer[4096];
- time_t CurrentTime;
- struct tm *tm;
- struct timeval tv;
- va_list args;
- va_start(args, fmt);
- int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
- va_end(args);
- memset(Buf,0,sizeof(Buf));
- CurrentTime = time(NULL);
- tm=localtime(&CurrentTime);
- gettimeofday(&tv, NULL); // get microseconds, 10^-6
- sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s\" >> /Storage/SystemLog/[%04d.%02d]PaymentLog",
- tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec,
- buffer,
- tm->tm_year+1900,tm->tm_mon+1);
- system((const char*)Buf);
- #ifdef ConsloePrintLog
- 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);
- #endif
- return rc;
- }
- /**
- * Execute shell command
- * @param cmd: shell command string
- * @return shell command execution result
- */
- int runShellCmd(const char*cmd)
- {
- int result = FAIL;
- char buf[256];
- FILE *fp;
- fp = popen(cmd, "r");
- if(fp != NULL)
- {
- while(fgets(buf, sizeof(buf), fp) != NULL)
- {
- DEBUG_INFO("%s\n", buf);
- }
- result = PASS;
- }
- pclose(fp);
- return result;
- }
- /**
- * Calculate time differential
- * @param ST: start time
- * @param ET: end time
- * @return time differential in million seconds
- */
- int DiffTimeb(struct timeb ST, struct timeb ET)
- {
- //return milli-second
- unsigned int StartTime,StopTime;
- StartTime=(unsigned int)ST.time;
- StopTime=(unsigned int)ET.time;
- return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
- }
- /**
- * Show communication raw data to debug info
- * @param data: raw data
- * @param len: data length
- * @param isRX: is receive data
- */
- void show_raw(uint8_t *data, uint16_t len, uint8_t isRX)
- {
- uint8_t output[8192];
- memset(output, 0x00, ARRAY_SIZE(output));
- sprintf((char*)output, "%s", (isRX?"RX: ":"TX: "));
- for(uint16_t idx = 0;idx<len;idx++)
- {
- sprintf((char*)output, "%s%02x ", output, data[idx]);
- }
- DEBUG_INFO("%s\n", output);
- }
- /**
- * Show data to debug info
- * @param dat: data content
- * @param len: data length
- */
- void show_data(unsigned char *dat, unsigned int len)
- {
- uint8_t output[8192];
- memset(output, 0x00, ARRAY_SIZE(output));
- sprintf((char*)output, "Data: ");
- for(uint16_t idx = 0;idx<len;idx++)
- {
- if(dat[idx] > 31 && dat[idx] < 128 )
- sprintf((char*)output, "%s%c", output, dat[idx]);
- else
- sprintf((char*)output, "%s<%x>", output, dat[idx]);
- }
- DEBUG_INFO("%s\n", output);
- }
- /**
- * Get sentinel quantity in data array
- * @param data: message array address
- * @param dataLen: array seek size
- * @return how many sentinel flag found
- */
- int getSentinelQuantity(unsigned char *data, unsigned int dataLen)
- {
- int result = 0;
- for(uint16_t idx=0;idx<dataLen;idx++)
- {
- if(data[idx] == '?')
- result++;
- }
- return result;
- }
- /**
- * Get sentinel position in array
- * @param data: message array address
- * @param dataLen: array seek size
- * @param idxSentinel: which sentinel idx want to find, since 0 start
- * @return sentinel position in array
- */
- int getSentinelPosition(unsigned char *data, unsigned int dataLen, unsigned char idxSentinel)
- {
- int result = -1;
- int foundCnt = -1;
- for(uint16_t idx=0;idx<dataLen;idx++)
- {
- if(data[idx] == '?')
- foundCnt++;
- if(foundCnt == idxSentinel)
- {
- result = idx;
- break;
- }
- }
- return result;
- }
- /**
- *
- * @param dec: number in dec
- * @return number in bcd
- */
- int decTobcd(int dec)
- {
- return (dec/10 * 16)+ (dec%10);
- }
- /**
- *
- * @param data: message array
- * @param dataLen: command & data field length in array
- * @return check sum result
- */
- int calChksum(unsigned char *data, unsigned int dataLen)
- {
- int result = 0;
- for(uint16_t idx=0;idx<dataLen-1;idx++)
- {
- result ^= data[idx];
- }
- return (result&0xff);
- }
- //==========================================
- // Init share memory
- //==========================================
- /**
- * Share memory initialization
- * @return function result
- */
- int InitShareMemory()
- {
- int result = PASS;
- int MeterSMId;
- #ifndef X86
- //init ShmSysConfigAndInfo
- if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
- {
- DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
- result = FAIL;
- }
- else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
- {
- DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
- result = FAIL;
- }
- else
- {}
- //init ShmStatusCodeData
- if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
- {
- DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
- result = FAIL;
- }
- else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
- {
- DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
- result = FAIL;
- }
- else
- {}
- #endif
- return result;
- }
- //==========================================
- // Init com port
- //==========================================
- /**
- * TTY port initialization
- * @return port initial result
- */
- int InitComPort()
- {
- int fd;
- struct termios tios;
- #ifndef X86
- fd = open("/dev/ttyS3", O_RDWR);
- #else
- fd = open("/dev/ttyUSB3", O_RDWR);
- #endif
- if(fd<=0)
- {
- return FAIL;
- }
- ioctl (fd, TCGETS, &tios);
- tios.c_cflag = B9600| CS8 | CLOCAL | CREAD;
- tios.c_lflag = 0;
- tios.c_iflag = 0;
- tios.c_oflag = 0;
- tios.c_cc[VMIN]=0; // data length threshold, 0 bytes
- tios.c_cc[VTIME]=(unsigned char)5; // timeout threshold, 0.5 seconds
- tios.c_lflag=0;
- tcflush(fd, TCIFLUSH);
- ioctl (fd, TCSETS, &tios);
- return fd;
- }
- /**
- * Send command to UIC680fg module.
- * @param uart: port handle
- * @param cmd: command buffer
- * @param cmd_len: command length
- * @param rx: receive buffer
- * @return receive data length
- */
- int system_command(int uart, unsigned char* cmd, int cmd_len, unsigned char* rx)
- {
- int rx_len = 0;
- tcflush(uart,TCIOFLUSH);
- //show_raw(cmd, cmd_len, NO);
- if(write(uart, cmd, cmd_len) > 0)
- {
- usleep(100000);
- rx_len = read(uart, rx, 512);
- //show_raw(rx, rx_len, YES);
- }
- else
- {
- DEBUG_ERROR("system command write fail.\n");
- }
- return rx_len;
- }
- /**
- * Parsing raw data to USI data
- * @param rx: raw data
- * @param rx_data: parsing result data
- * @return parsing result data length
- */
- int USI2_Parse(unsigned char* rx, unsigned char* rx_data)
- {
- int result = -1;
- unsigned int data_len =0;
- unsigned int chksum = 0;
-
- if(rx[0] == SOH) // SOH = 0x01
- {
- data_len = (unsigned int)rx[2] <<8;
- data_len |= rx[3];
-
- for(int idx=0;idx<(data_len+4);idx++)
- {
- chksum ^= rx[idx];
- }
-
- if((chksum&0xff) == rx[(data_len+4)])
- {
- memcpy(rx_data, &rx[4], data_len);
- result = data_len;
- }
- else
- DEBUG_WARN("USI2 message checksum error.\n");
- }
- else
- {
- DEBUG_WARN("USI2 message header is not <01>.\n");
- }
- return result;
- }
- //==========================================
- // Main loop
- //==========================================
- int main(void)
- {
- int UartFd;
- uint16_t failCount = 0;
- unsigned char rx_Array[512]={0}, rx_Data[512]={0};
- char C8_Polling = true;
- char Wait_C9 = false;
- int rx_len = 0;
- int data_len = 0;
- time_t CurrentTime;
- struct tm *tm;
- DEBUG_INFO("Task version: %s\n", version);
- //===============================================
- // Initialization
- //===============================================
- #ifndef X86
- if(InitShareMemory() == FAIL)
- {
- DEBUG_ERROR("InitShareMemory NG\n");
- if(ShmStatusCodeData!=NULL)
- {
- ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
- }
- sleep(5);
- return FAIL;
- }
- #endif
- UartFd=InitComPort();
- if(UartFd<0)
- {
- DEBUG_ERROR("InitComPort NG\n");
- if(ShmStatusCodeData!=NULL)
- {
- #ifndef X86
- ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
- #endif
- }
- sleep(5);
- return FAIL;
- }
- else
- {
- DEBUG_INFO("ttyS3 port open success.\n");
- }
- //===============================================
- // Payment module configuration set to default (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_RESTORE_DEFAULT, ARRAY_SIZE(BLP_CMD_RESTORE_DEFAULT), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set to the default success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set to the default fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set to the default fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len != 1));
- //===============================================
- // set to protocol_2 (BLP Protocol)
- //===============================================
- do
- {
- rx_len =system_command(UartFd, BLP_CMD_USI2, ARRAY_SIZE(BLP_CMD_USI2), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set protocol to USI2 success.\n");
- DEBUG_INFO("Wait for payment module warm-reset.\n");
- sleep(10);
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set protocol to USI2 fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set protocol to USI2 fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Disable self-arm mode (USI2 Protocol)
- //===============================================
- do
- {
- USI_CMD_ARM_DISABLE[ARRAY_SIZE(USI_CMD_ARM_DISABLE)-1] = calChksum(USI_CMD_ARM_DISABLE, ARRAY_SIZE(USI_CMD_ARM_DISABLE));
- system_command(UartFd, USI_CMD_ARM_DISABLE, ARRAY_SIZE(USI_CMD_ARM_DISABLE), rx_Array);
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if((rx_Data[0] == ACK) && (rx_len >= 0))
- {
- DEBUG_INFO("Set disable self-arm mode success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set disable self-arm mode fail (<%02x>).\n", rx_Data[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set disable self-arm mode fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Data[0] != ACK) || (rx_len < 0));
- //===============================================
- // Enable TLV command (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_TLV_ENABLE, ARRAY_SIZE(BLP_CMD_TLV_ENABLE), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set enable TLV command success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set enable TLV command fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set enable TLV command fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len != 1));
- //===============================================
- // Set AID type (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_SET_AID, ARRAY_SIZE(BLP_CMD_SET_AID), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set AID type success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set AID type fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set AID type fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len != 1));
- //===============================================
- // Set LED indicator (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_LED_IND, ARRAY_SIZE(BLP_CMD_LED_IND), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set LED indicator success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set LED indicator fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set LED indicator over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len != 1));
- //===============================================
- // Set CA public key type (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_CA_PKEY, ARRAY_SIZE(BLP_CMD_CA_PKEY), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set CA public key type success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set CA public key type fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set CA public key type over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len != 1));
- //===============================================
- // Set payment card detect type (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_CARD_DETECT, ARRAY_SIZE(BLP_CMD_CARD_DETECT), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set payment card type success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set payment card type fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set payment card type fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Disable soft card wallet application (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_SOFTCARD_DISABLE, ARRAY_SIZE(BLP_CMD_SOFTCARD_DISABLE), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set disable soft card success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set disable soft card fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set disable soft card fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Set error beep style (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_ERR_BEEP_STYLE, ARRAY_SIZE(BLP_CMD_ERR_BEEP_STYLE), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set error beep style success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set error beep style fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set error beep style fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Set error beep (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_ERR_BEEP, ARRAY_SIZE(BLP_CMD_ERR_BEEP), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set error beep success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set error beep fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set error beep fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Set enable LRC (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_LRC_ENABLE, ARRAY_SIZE(BLP_CMD_LRC_ENABLE), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set enable LRC success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set enable LRC fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set enable LRC fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
- //===============================================
- // Set TX data tracks (BLP Protocol)
- //===============================================
- do
- {
- rx_len = system_command(UartFd, BLP_CMD_TX_TRACK, ARRAY_SIZE(BLP_CMD_TX_TRACK), rx_Array);
- if((rx_Array[0] == ACK) && (rx_len ==1))
- {
- DEBUG_INFO("Set TX data tracks success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set TX data tracks fail (<%02x>).\n", rx_Array[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set TX data tracks over retry limit.\n");
- return FAIL;
- }
- }while((rx_Array[0] != ACK) || (rx_len !=1));
-
- //===============================================
- // Set module RTC date (USI2 Protocol)
- //===============================================
- do
- {
- CurrentTime = time(NULL);
- tm=localtime(&CurrentTime);
- USI_CMD_SET_DATE[6] = ((tm->tm_year+1900)/100);
- USI_CMD_SET_DATE[7] = ((tm->tm_year+1900)%100);
- USI_CMD_SET_DATE[8] = (tm->tm_mon+1);
- USI_CMD_SET_DATE[9] = tm->tm_mday;
- USI_CMD_SET_DATE[10] = tm->tm_wday==0?0x07:tm->tm_wday;
- USI_CMD_SET_DATE[ARRAY_SIZE(USI_CMD_SET_DATE)-1] = calChksum(USI_CMD_SET_DATE, ARRAY_SIZE(USI_CMD_SET_DATE));
- system_command(UartFd, USI_CMD_SET_DATE, ARRAY_SIZE(USI_CMD_SET_DATE), rx_Array);
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if((rx_Data[0] == ACK) && (rx_len >= 0))
- {
- DEBUG_INFO("Set module RTC date success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set module RTC date fail (<%02x>).\n", rx_Data[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set module RTC date fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Data[0] != ACK) || (rx_len < 0));
- //===============================================
- // Set module RTC time (USI2 Protocol)
- //===============================================
- do
- {
- CurrentTime = time(NULL);
- tm=localtime(&CurrentTime);
- USI_CMD_SET_TIME[6] = tm->tm_hour;
- USI_CMD_SET_TIME[7] = tm->tm_min;
- USI_CMD_SET_TIME[8] = tm->tm_sec;
- USI_CMD_SET_TIME[ARRAY_SIZE(USI_CMD_SET_TIME)-1] = calChksum(USI_CMD_SET_TIME, ARRAY_SIZE(USI_CMD_SET_TIME));
- system_command(UartFd, USI_CMD_SET_TIME, ARRAY_SIZE(USI_CMD_SET_TIME), rx_Array);
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if((rx_Data[0] == ACK) && (rx_len >= 0))
- {
- DEBUG_INFO("Set module RTC time success.\n");
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Set module RTC time fail (<%02x>).\n", rx_Data[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- DEBUG_ERROR("Set module RTC time fail over retry limit.\n");
- return FAIL;
- }
- }while((rx_Data[0] != ACK) || (rx_len < 0));
- //===============================================
- // Main loop
- //===============================================
- for(;;)
- {
- if(C8_Polling == true)
- {
- Wait_C9 = false;
- CurrentTime = time(NULL);
- tm=localtime(&CurrentTime);
- USI_CMD_C8_DEACTIVAVE[ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE)-1] = calChksum(USI_CMD_C8_DEACTIVAVE, ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE));
- if(system_command(UartFd, USI_CMD_C8_DEACTIVAVE, ARRAY_SIZE(USI_CMD_C8_DEACTIVAVE), rx_Array) > 0)
- {
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if((rx_Data[0] == ACK) && (rx_len >= 0))
- {
- DEBUG_INFO("C8 deactivate command success.\n");
- failCount = 0;
- USI_CMD_C8_POLL[9] = decTobcd((1000/10000000000)%100);
- USI_CMD_C8_POLL[10] = decTobcd((1000/100000000)%100);
- USI_CMD_C8_POLL[11] = decTobcd((1000/1000000)%100);
- USI_CMD_C8_POLL[12] = decTobcd((1000/10000)%100);
- USI_CMD_C8_POLL[13] = decTobcd((1000/100)%100);
- USI_CMD_C8_POLL[14] = decTobcd((1000/1)%100);
- USI_CMD_C8_POLL[18] = (CURRENCY_USD>>0x08)&0xff;
- USI_CMD_C8_POLL[19] = (CURRENCY_USD>>0x00)&0xff;
- USI_CMD_C8_POLL[29] = decTobcd((tm->tm_year+1900)-2000);
- USI_CMD_C8_POLL[30] = decTobcd(tm->tm_mon+1);
- USI_CMD_C8_POLL[31] = decTobcd(tm->tm_mday);
- USI_CMD_C8_POLL[35] = decTobcd(tm->tm_hour);
- USI_CMD_C8_POLL[36] = decTobcd(tm->tm_min);
- USI_CMD_C8_POLL[37] = decTobcd(tm->tm_sec);
- USI_CMD_C8_POLL[ARRAY_SIZE(USI_CMD_C8_POLL)-1] = calChksum(USI_CMD_C8_POLL, ARRAY_SIZE(USI_CMD_C8_POLL));
- if(system_command(UartFd, USI_CMD_C8_POLL, ARRAY_SIZE(USI_CMD_C8_POLL), rx_Array) > 0)
- {
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if((rx_Data[0] == ACK) && (rx_len >= 0))
- {
- DEBUG_INFO("C8 polling command success.\n");
- Wait_C9 = true;
- failCount = 0;
- C9_Result.isCommandError = OFF;
- }
- else
- {
- DEBUG_INFO("C8 polling command fail (<%02x>).\n", rx_Data[0]);
- C9_Result.isCommandError = ON;
- }
- }
- }
- else
- {
- DEBUG_INFO("C8 deactivate command fail.\n");
- C9_Result.isCommandError = ON;
- }
- }
- if(Wait_C9 == true)
- {
- //=============================================
- // wait card to attach the reader and wait C9
- //=============================================
- tcflush(UartFd,TCIOFLUSH);
- memset(rx_Array, 0x00, ARRAY_SIZE(rx_Array));
- rx_len = 0;
- do
- {
- DEBUG_INFO("C9 response reading...\n");
- usleep(2000000);
- rx_len = read(UartFd, rx_Array, ARRAY_SIZE(rx_Array)); // read response if data count match 512 or timeout.
- failCount++;
- } while ((rx_len == 0) && (failCount < RETRY_LIMIT));
- //=============================================
- // Parse rx_Array to rx_Data
- //=============================================
- if((rx_len > 3) && (failCount < RETRY_LIMIT))
- {
- // print this raw data before parse it.
- //show_data(rx_Array, rx_len);
- if((rx_len = USI2_Parse( rx_Array, rx_Data)) > 0)
- {
- // debug the input data message
- //show_data(rx_Data, rx_len);
- // Copy RAW data to structure
- memcpy(&C9_Result.result_data, rx_Data, rx_len);
- C9_Result.status = C9_Result.result_data[1];
- C9_Result.pos_entry = C9_Result.result_data[2];
- switch(C9_Result.pos_entry)
- {
- case VISA_qVSDC:
- case VISA_MSD:
- case MASTER_MChip:
- case Master_MagStripe:
- case AMEX_EMV:
- case AMEX_MSD:
- memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
- memcpy(C9_Result.u_id, &C9_Result.result_data[5], 16);
- DEBUG_INFO("Credit card SN:\n");
- show_data(C9_Result.u_id, 16);
- for(uint8_t idx=0;idx<getSentinelQuantity(C9_Result.result_data, rx_len);idx++)
- {
- memset(C9_Result.tkData[idx], 0x00, ARRAY_SIZE(C9_Result.tkData[idx]));
- memcpy(C9_Result.tkData[idx],
- &C9_Result.result_data[((idx==0)?3:getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2)],
- (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));
- DEBUG_INFO("TK[%d]: \n", idx);
- show_data(C9_Result.tkData[idx], getSentinelPosition(C9_Result.tkData[idx], ARRAY_SIZE(C9_Result.tkData[idx]), 0)+2);
- }
- break;
- case Mifare:
- data_len = C9_Result.result_data[6];
- memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
- memcpy(C9_Result.u_id, &C9_Result.result_data[7], data_len);
- switch(C9_Result.result_data[3])
- {
- case MIFARE_ULTRALIGHT:
- 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]);
- break;
- case MIFARE_CLASSIC_1K:
- 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]);
- break;
- case MIFARE_CLASSIC_4K:
- 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]);
- break;
- case MIFARE_DESFIRE:
- 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]);
- break;
- case MIFARE_PLUS_2K:
- 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]);
- break;
- case MIFARE_MINI:
- 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]);
- break;
- case MIFARE_RESERVE:
- DEBUG_INFO("MIFARE Reserve, UID: \n");
- break;
- case MIFARE_JEWEL:
- DEBUG_INFO("MIFARE Jewel, UID: \n");
- break;
- case MIFARE_JCOP31:
- DEBUG_INFO("MIFARE JCOP31, UID: \n");
- break;
- }
- break;
- case ISO_15693:
- data_len =(C9_Result.result_data[5]<<8) | C9_Result.result_data[6];
- memset(C9_Result.u_id, 0x00, ARRAY_SIZE(C9_Result.u_id));
- memcpy(C9_Result.u_id, &C9_Result.result_data[4+data_len-8], 8);
- 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]);
- break;
- case Apple_Pay:
- DEBUG_INFO("Apple_Pay VAS only.\n");
- for(uint8_t idx=0;idx<getSentinelQuantity(C9_Result.result_data, rx_len);idx++)
- {
- memcpy(C9_Result.tkData[idx],
- &C9_Result.result_data[((idx==0)?3:getSentinelPosition(C9_Result.result_data, rx_len, idx-1)+2)],
- (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));
- DEBUG_INFO("TK[%d]: \n", idx);
- show_data(C9_Result.tkData[idx], getSentinelPosition(C9_Result.tkData[idx], ARRAY_SIZE(C9_Result.tkData[idx]), 0)+2);
- }
- break;
- case No_Data:
- DEBUG_INFO("No any data.\n");
- break;
- default:
- DEBUG_WARN("Unknown pos entry.\n");
- if(C9_Result.status == C9_RES_C8_CMD_TIMEOUT)
- DEBUG_WARN("C8 command timeout.\n");
- else if(C9_Result.status == C9_RES_CMD_EXECUTING)
- DEBUG_WARN("Command executing or Wait Card to be Removed.\n");
- break;
- }
- failCount = 0;
- // Wait card removed
- do
- {
- system_command(UartFd, USI_CMD_MODULE_STATUS, ARRAY_SIZE(USI_CMD_MODULE_STATUS), rx_Array);
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if(!(rx_Data[0]&0x02) && (rx_len >= 0))
- {
- DEBUG_INFO("Card removed.\n");
- C9_Result.isCardPreset = OFF;
- failCount = 0;
- }
- else if((rx_Data[0]&0x02) && (rx_len >= 0))
- {
- //DEBUG_INFO("Card seated.\n");
- C9_Result.isCardPreset = ON;
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Module status read fail (<%02x>).\n", rx_Data[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- C9_Result.isCardPreset = OFF;
- DEBUG_ERROR("Module status read fail over retry limit.\n");
- }
- }while(((rx_Data[0]&0x02) || (rx_len < 0)) && (failCount < RETRY_LIMIT));
- }
- else
- {
- DEBUG_INFO("C9 Parsing result fail.\n");
- C9_Result.isCommandError = ON;
- // Wait card removed
- do
- {
- usleep(500000);
- system_command(UartFd, USI_CMD_MODULE_STATUS, ARRAY_SIZE(USI_CMD_MODULE_STATUS), rx_Array);
- rx_len = USI2_Parse(rx_Array, rx_Data);
- if(!(rx_Data[0]&0x02) && (rx_len >= 0))
- {
- DEBUG_INFO("Card removed.\n");
- C9_Result.isCardPreset = OFF;
- C9_Result.isCommandError = OFF;
- failCount = 0;
- }
- else if((rx_Data[0]&0x02) && (rx_len >= 0))
- {
- //DEBUG_INFO("Card seated.\n");
- C9_Result.isCardPreset = ON;
- failCount = 0;
- }
- else
- {
- DEBUG_WARN("Module status read fail (<%02x>).\n", rx_Data[0]);
- failCount++;
- }
- if(failCount > RETRY_LIMIT)
- {
- C9_Result.isCardPreset = OFF;
- DEBUG_ERROR("Module status read fail over retry limit.\n");
- }
- }while(((rx_Data[0]&0x02) || (rx_len < 0)) && (failCount < RETRY_LIMIT));
- }
- }
- else
- {
- DEBUG_WARN("C9 Response timeout: %d \n", failCount);
- }
- }
- }
- usleep(1000000);
- }
- return FAIL;
- }
|