|
@@ -0,0 +1,618 @@
|
|
|
+/*
|
|
|
+ * Module_Payment.c
|
|
|
+ *
|
|
|
+ * Created on: 2021/03/24
|
|
|
+ * Author: Henry Yeh
|
|
|
+ */
|
|
|
+
|
|
|
+#include "Module_Payment.h"
|
|
|
+
|
|
|
+unsigned char CMD_C8[30] = {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)
|
|
|
+ 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
|
|
|
+unsigned char CMD_CARD_DETECT[11] = {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 CMD_USI2[7] = {0x09, 0, 0x03, 'P', 'C', '0', 0x29}; // Configure protocol to USI2
|
|
|
+unsigned char CMD_SET_BAUD[7] = {0x09, 0, 0x03, 'B', 'R', '7', 0x2d}; // Configure module baud rate to 115200
|
|
|
+unsigned char CMD_RESTORE_DEFAULT[7] = {0x09, 0, 0x03, 'D', 'F', 0, 0x08 }; // Restore module configuration to default setting
|
|
|
+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];
|
|
|
+
|
|
|
+ unsigned char status;
|
|
|
+ unsigned char pos_entry;
|
|
|
+ unsigned char u_id[20];
|
|
|
+ unsigned char tkData[4][128];
|
|
|
+} 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/System/[%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;
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Init share memory
|
|
|
+//==========================================
|
|
|
+/**
|
|
|
+ * Share memory initialization
|
|
|
+ * @return function result
|
|
|
+ */
|
|
|
+int InitShareMemory()
|
|
|
+{
|
|
|
+ int result = PASS;
|
|
|
+ int MeterSMId;
|
|
|
+
|
|
|
+ //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
|
|
|
+ {}
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================
|
|
|
+// Init com port
|
|
|
+//==========================================
|
|
|
+/**
|
|
|
+ * TTY port initialization
|
|
|
+ * @return port initial result
|
|
|
+ */
|
|
|
+int InitComPort()
|
|
|
+{
|
|
|
+ int fd;
|
|
|
+ struct termios tios;
|
|
|
+
|
|
|
+ fd = open("/dev/ttyS3", O_RDWR);
|
|
|
+ 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;
|
|
|
+ tios.c_cc[VTIME]=(unsigned char)5; // timeout 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)
|
|
|
+ {
|
|
|
+ /*
|
|
|
+ * TODO: Improve sleep time.
|
|
|
+ */
|
|
|
+ usleep(1000000);
|
|
|
+ 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 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;
|
|
|
+
|
|
|
+ //===============================================
|
|
|
+ // Initialization
|
|
|
+ //===============================================
|
|
|
+ if(InitShareMemory() == FAIL)
|
|
|
+ {
|
|
|
+ DEBUG_ERROR("InitShareMemory NG\n");
|
|
|
+
|
|
|
+ if(ShmStatusCodeData!=NULL)
|
|
|
+ {
|
|
|
+ ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
|
|
|
+ }
|
|
|
+ sleep(5);
|
|
|
+ return FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ UartFd=InitComPort();
|
|
|
+ if(UartFd<0)
|
|
|
+ {
|
|
|
+ DEBUG_ERROR("InitComPort NG\n");
|
|
|
+ if(ShmStatusCodeData!=NULL)
|
|
|
+ {
|
|
|
+ ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
|
|
|
+ }
|
|
|
+ sleep(5);
|
|
|
+ return FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DEBUG_INFO("ttyS3 port open success.\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ //===============================================
|
|
|
+ // Payment module configuration set to default.
|
|
|
+ //===============================================
|
|
|
+ do
|
|
|
+ {
|
|
|
+ rx_len = system_command(UartFd, CMD_RESTORE_DEFAULT, ARRAY_SIZE(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 payment card detect type.
|
|
|
+ //===============================================
|
|
|
+ do
|
|
|
+ {
|
|
|
+ rx_len = system_command(UartFd, CMD_CARD_DETECT, ARRAY_SIZE(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));
|
|
|
+
|
|
|
+ //===============================================
|
|
|
+ // set to protocol_2
|
|
|
+ //===============================================
|
|
|
+ do
|
|
|
+ {
|
|
|
+ rx_len =system_command(UartFd, CMD_USI2, ARRAY_SIZE(CMD_USI2), rx_Array);
|
|
|
+
|
|
|
+ if((rx_Array[0] == ACK) && (rx_len ==1))
|
|
|
+ {
|
|
|
+ DEBUG_INFO("Set protocol to USI2 success.\n");
|
|
|
+ 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));
|
|
|
+
|
|
|
+ //===============================================
|
|
|
+ // Main loop
|
|
|
+ //===============================================
|
|
|
+ for(;;)
|
|
|
+ {
|
|
|
+ if(C8_Polling == true)
|
|
|
+ {
|
|
|
+ Wait_C9 = false;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * TODO:
|
|
|
+ * 1. C8 parameter configure
|
|
|
+ */
|
|
|
+ rx_len =system_command(UartFd, CMD_C8, sizeof(CMD_C8), rx_Array);
|
|
|
+ if((rx_Array[0] == ACK) && (rx_len ==1))
|
|
|
+ {
|
|
|
+ DEBUG_INFO("Polling C8 command get response.\n");
|
|
|
+ Wait_C9 = true;
|
|
|
+ failCount = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+ {
|
|
|
+ sleep(1);
|
|
|
+ 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);
|
|
|
+
|
|
|
+ rx_len = USI2_Parse( rx_Array, rx_Data);
|
|
|
+ if(rx_len > 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:
|
|
|
+ for (int i=5; i<(5 + 16); i++)
|
|
|
+ {
|
|
|
+ C9_Result.u_id[i] = C9_Result.result_data[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ DEBUG_INFO("Payment card\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], ARRAY_SIZE(C9_Result.tkData[idx]));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Mifare:
|
|
|
+ data_len = C9_Result.result_data[6];
|
|
|
+ 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];
|
|
|
+ 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], ARRAY_SIZE(C9_Result.tkData[idx]));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case No_Data:
|
|
|
+
|
|
|
+ DEBUG_INFO("--> No any data.\n");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DEBUG_INFO("--> Unknown pos entry.\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ failCount = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DEBUG_INFO("C9 Parsing result fail.\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DEBUG_WARN("C9 Response timeout: %d \n", failCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ usleep(500000);
|
|
|
+ }
|
|
|
+
|
|
|
+ return FAIL;
|
|
|
+}
|