Browse Source

[Improve][Modularization][Module_Payment]

2021.05.03 / Folus Wen

Actions:
1. Restart polling process after card removed from payment module.

Files:
1. As follow commit history

Image version: D0.03
Image checksum: XXXXXXXX

Hardware PWB P/N : XXXXXXX
Hardware Version : XXXXXXX
FolusWen 3 years ago
parent
commit
cb520bde05
2 changed files with 542 additions and 66 deletions
  1. 539 66
      EVSE/Modularization/Module_Payment.c
  2. 3 0
      EVSE/Modularization/Module_Payment.h

+ 539 - 66
EVSE/Modularization/Module_Payment.c

@@ -6,28 +6,54 @@
  */
 
 #include	"Module_Payment.h"
-unsigned char version[]					= {'D', '0', '.', '0', '1'};
-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
+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];
+	unsigned char result_data[512];			// C9 response data without header & checksum
 	
-	unsigned char status;
-	unsigned char pos_entry;
-	unsigned char u_id[20];
-	unsigned char tkData[4][128];
+	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;
 
 //==========================================
@@ -195,6 +221,34 @@ int getSentinelPosition(unsigned char *data, unsigned int dataLen, unsigned char
 	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
 //==========================================
@@ -207,6 +261,7 @@ int InitShareMemory()
 	int result = PASS;
 	int MeterSMId;
 
+#ifndef X86
 	//init ShmSysConfigAndInfo
 	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
     {
@@ -234,6 +289,7 @@ int InitShareMemory()
 	}
 	else
 	{}
+#endif
 
    	return result;
 }
@@ -249,8 +305,11 @@ 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;
@@ -260,8 +319,8 @@ int InitComPort()
 	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_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);
@@ -282,16 +341,13 @@ 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);
+	//show_raw(cmd, cmd_len, NO);
 	if(write(uart, cmd, cmd_len) > 0)
 	{
-		/*
-		 *	TODO: Improve sleep time.
-		 */
-		usleep(1000000);
+		usleep(100000);
 		rx_len = read(uart, rx, 512);
 
-		show_raw(rx, rx_len, YES);
+		//show_raw(rx, rx_len, YES);
 	}
 	else
 	{
@@ -328,6 +384,8 @@ int USI2_Parse(unsigned char* rx, unsigned char* rx_data)
 			memcpy(rx_data, &rx[4], data_len);
 			result = data_len;
 		}
+        else
+        	DEBUG_WARN("USI2 message checksum error.\n");
 	}
 	else 
 	{
@@ -349,11 +407,14 @@ int main(void)
 	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");
@@ -365,14 +426,16 @@ int main(void)
 		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;
@@ -383,12 +446,11 @@ int main(void)
 	}
 
 	//===============================================
-	// Payment module configuration set to default.
+	// Payment module configuration set to default (BLP Protocol)
 	//===============================================
 	do
 	{
-		rx_len = system_command(UartFd, CMD_RESTORE_DEFAULT, ARRAY_SIZE(CMD_RESTORE_DEFAULT), rx_Array);
-
+		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");
@@ -405,15 +467,162 @@ int main(void)
 			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));
+
 	//===============================================
-	// set payment card detect type.
+	// Enable TLV command (BLP Protocol)
 	//===============================================
 	do
 	{
-		rx_len = system_command(UartFd, CMD_CARD_DETECT, ARRAY_SIZE(CMD_CARD_DETECT), rx_Array);
+		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");
@@ -433,30 +642,189 @@ int main(void)
 	}while((rx_Array[0] != ACK) || (rx_len !=1));
 
 	//===============================================
-	// set to protocol_2 
+	// Disable soft card wallet application (BLP Protocol)
 	//===============================================
 	do
 	{
-		rx_len =system_command(UartFd, CMD_USI2, ARRAY_SIZE(CMD_USI2), rx_Array);
+		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 protocol to USI2 success.\n");
+			DEBUG_INFO("Set error beep style success.\n");
 			failCount = 0;
 		}
 		else
 		{
-			DEBUG_WARN("Set protocol to USI2 fail (<%02x>).\n", rx_Array[0]);
+			DEBUG_WARN("Set error beep style fail (<%02x>).\n", rx_Array[0]);
 			failCount++;
 		}
 
 		if(failCount > RETRY_LIMIT)
 		{
-			DEBUG_ERROR("Set protocol to USI2 fail over retry limit.\n");
+			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
 	//===============================================
@@ -465,19 +833,58 @@ int main(void)
 		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))
+			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)
 			{
-				DEBUG_INFO("Polling C8 command get response.\n");
-				Wait_C9 = true;
-				failCount = 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)
 			{
 				//=============================================
@@ -486,33 +893,33 @@ int main(void)
 				tcflush(UartFd,TCIOFLUSH);
 				memset(rx_Array, 0x00, ARRAY_SIZE(rx_Array));
 				rx_len = 0;
-					
+
 				do
 				{
-					sleep(1);
+					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);
-					
-					rx_len = USI2_Parse( rx_Array, rx_Data);
-					if(rx_len > 0)
+					//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 
+						// 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:
@@ -522,11 +929,10 @@ int main(void)
 							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[4], 16);
+								memcpy(C9_Result.u_id, &C9_Result.result_data[5], 16);
 								DEBUG_INFO("Credit card SN:\n");
 								show_data(C9_Result.u_id, 16);
 
-								DEBUG_INFO("Payment card\n");
 								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]));
@@ -594,17 +1000,84 @@ int main(void)
 								}
 								break;
 							case No_Data:
-								DEBUG_INFO("--> No any data.\n");
+								DEBUG_INFO("No any data.\n");
 								break;
 							default:
-								DEBUG_INFO("--> Unknown pos entry.\n");
+								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 
+					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
@@ -614,7 +1087,7 @@ int main(void)
 			}
 		}
 
-		usleep(500000);
+		usleep(1000000);
 	}
 
 	return FAIL;

+ 3 - 0
EVSE/Modularization/Module_Payment.h

@@ -41,6 +41,8 @@
 #include	<stdint.h>
 #include	"define.h"
 
+//#define	X86
+
 #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
@@ -88,6 +90,7 @@ enum CARD_TYPE_CODE
 	Mifare = 0x10,
 	ISO_15693 = 0x20,
 	No_Data	= 0x80,
+	Felica = 0xf0
 };
 
 enum C9_RES_CODE