From 8d172b7326c7743d1474d6f77a290913d1f3399b Mon Sep 17 00:00:00 2001
From: Min Xu <min.xu[A.T]min-info[D.O.T]net>
Date: Tue, 10 Sep 2013 14:26:22 -1000
Subject: [PATCH 4/6] Periodically flush received req_ctx buffer if no new
 data received since last period

Flushing data on RST, nRST and VCC_PHONE_off shouldn't indicate wait_timeout
---
 firmware/src/simtrace/iso7816_uart.c  |   30 +++++++++++++++++++++++++-----
 firmware/src/simtrace/iso7816_uart.h  |    3 +++
 firmware/src/simtrace/main_simtrace.c |    7 +++++--
 firmware/src/simtrace/sim_switch.c    |    2 +-
 4 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c
index 9f7c143..39072a0 100644
--- a/firmware/src/simtrace/iso7816_uart.c
+++ b/firmware/src/simtrace/iso7816_uart.c
@@ -125,12 +125,18 @@ static const u_int8_t di_table[] = {
 	12, 20, 2, 4, 8, 16, 32, 64,
 };
 
-void iso_uart_report_overrun(void) 
+void iso_uart_report_errors(void) 
 {
-	static unsigned lastOverrun = 0;
+	static unsigned lastOverrun = 0, lastParity = 0, lastFrame = 0;
 	if (isoh.stats.overrun != lastOverrun) {
 		DEBUGPCR("UART overrun: %u", lastOverrun = isoh.stats.overrun);
 	}
+	if (isoh.stats.frame_err != lastFrame) {
+		DEBUGPCR("UART frame error: %u", lastFrame = isoh.stats.frame_err);
+	}
+	if (isoh.stats.parity_err != lastParity) {
+		DEBUGPCR("UART parity error: %u", lastParity = isoh.stats.parity_err);
+	}
 }
 
 void iso_uart_stats_dump(void)
@@ -575,6 +581,20 @@ void iso7816_wtime_expired(void)
 	set_state(&isoh, ISO7816_S_WAIT_APDU);
 }
 
+void iso_uart_flush(void) {
+	send_rctx(&isoh);
+}
+
+void iso_uart_idleflush(void) {
+	static struct req_ctx *last_req = NULL;
+	static u_int16_t last_len = 0;
+	if (last_req == isoh.rctx || last_len == isoh.rctx->tot_len) {
+		send_rctx(&isoh);
+	}
+	last_req = isoh.rctx;
+	last_len = isoh.rctx->tot_len;
+}
+
 static __ramfunc void usart_irq(void)
 {
 	u_int32_t csr = usart->US_CSR;
@@ -596,7 +616,7 @@ static __ramfunc void usart_irq(void)
 	if (csr & (AT91C_US_PARE|AT91C_US_FRAME|AT91C_US_OVRE)) {
 		u_int8_t nb_err = usart->US_NER;
 		/* FIXME: some error has occurrerd */
-		DEBUGP("NER=%02x ", nb_err);
+		// DEBUGP("NER=%02x ", nb_err);
 		/* clear the status */
 		usart->US_CR |= AT91C_US_RSTSTA;
 
@@ -619,11 +639,11 @@ static void reset_pin_irq(u_int32_t pio)
 {
 	// When ever reset occured, we make sure to flush out any populated req_ctx
 	if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio)) {
-		iso7816_wtime_expired();
+		iso_uart_flush();
 		DEBUGPCR("nRST");
 		set_state(&isoh, ISO7816_S_RESET);
 	} else {
-		iso7816_wtime_expired();
+		iso_uart_flush();
 		DEBUGPCR("RST");
 		set_state(&isoh, ISO7816_S_WAIT_ATR);
 		isoh.stats.rst++;
diff --git a/firmware/src/simtrace/iso7816_uart.h b/firmware/src/simtrace/iso7816_uart.h
index 68615a3..969e6f9 100644
--- a/firmware/src/simtrace/iso7816_uart.h
+++ b/firmware/src/simtrace/iso7816_uart.h
@@ -2,11 +2,14 @@
 #define SIMTRACE_ISO7816_UART_H
 
 struct simtrace_stats *iso_uart_stats_get(void);
+void iso_uart_report_errors(void);
 void iso_uart_stats_dump(void);
 void iso_uart_dump(void);
 void iso_uart_rst(unsigned int state);
 void iso_uart_rx_mode(void);
 void iso_uart_clk_master(unsigned int master);
 void iso_uart_init(void);
+void iso_uart_flush(void);
+void iso_uart_idleflush(void);
 
 #endif
diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c
index 9c357e1..edbd9b4 100644
--- a/firmware/src/simtrace/main_simtrace.c
+++ b/firmware/src/simtrace/main_simtrace.c
@@ -218,7 +218,7 @@ int _main_dbgu(char key)
 
 void _main_func(void)
 {
-	static unsigned loopLow = 0, loopHigh = 0;
+  	static unsigned loopLow = 0, loopHigh = 0;
 
 	/* first we try to get rid of pending to-be-sent stuff */
 	usb_out_process();
@@ -231,7 +231,10 @@ void _main_func(void)
        	if ((loopLow & 0xFFFF) == 0) {
 		DEBUGPCR("Heart beat %08X", loopHigh++);
 	}
+	if ((loopLow & 0xFFF) == 0) {
+		iso_uart_idleflush();
+	}
 	loopLow++;
 
-	iso_uart_report_overrun();
+	iso_uart_report_errors();
 }
diff --git a/firmware/src/simtrace/sim_switch.c b/firmware/src/simtrace/sim_switch.c
index a374e7d..aca8704 100644
--- a/firmware/src/simtrace/sim_switch.c
+++ b/firmware/src/simtrace/sim_switch.c
@@ -61,7 +61,7 @@ static void vcc_phone_irq(u_int32_t pio)
 {
 	if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, SIMTRACE_PIO_VCC_PHONE)) {
 		DEBUGPCR("VCC_PHONE off");
-		iso7816_wtime_expired();
+		iso_uart_flush();
 	} else {
 		DEBUGPCR("VCC_PHONE on");
 	}
-- 
1.7.9.5

