Change in simtrace2[master]: cardem: use TC_ETU to trigger ATR sending

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Mon Jul 30 13:27:25 UTC 2018


Harald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/10217 )

Change subject: cardem: use TC_ETU to trigger ATR sending
......................................................................

cardem: use TC_ETU to trigger ATR sending

this changes how ATR is handled.
the ATR is also printed when set (as important debug information).
the test is also updated to correspond to the new mechanism (
simulating the timeout before sending the ATR)

Change-Id: I69df797e2feadffa9f5f977cb71b69386cee7cd0
---
M firmware/libcommon/include/card_emu.h
M firmware/libcommon/source/card_emu.c
M firmware/libcommon/source/mode_cardemu.c
M firmware/test/card_emu_tests.c
4 files changed, 104 insertions(+), 30 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved



diff --git a/firmware/libcommon/include/card_emu.h b/firmware/libcommon/include/card_emu.h
index 7144168..a3c1cf2 100644
--- a/firmware/libcommon/include/card_emu.h
+++ b/firmware/libcommon/include/card_emu.h
@@ -1,6 +1,7 @@
 /* ISO7816-3 state machine for the card side
  *
  * (C) 2010-2017 by Harald Welte <hwelte at hmw-consulting.de>
+ * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,3 +55,4 @@
 int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte);
 void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx);
 void card_emu_uart_wait_tx_idle(uint8_t uart_chan);
+void card_emu_uart_interrupt(uint8_t uart_chan);
diff --git a/firmware/libcommon/source/card_emu.c b/firmware/libcommon/source/card_emu.c
index 25ec36a..51fd923 100644
--- a/firmware/libcommon/source/card_emu.c
+++ b/firmware/libcommon/source/card_emu.c
@@ -1,6 +1,7 @@
 /* ISO7816-3 state machine for the card side
  *
  * (C) 2010-2017 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -296,32 +297,39 @@
 		card_emu_uart_enable(ch->uart_chan, 0);
 		break;
 	case ISO_S_WAIT_ATR:
-		set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
 		/* Reset to initial Fi / Di ratio */
 		ch->fi = 1;
 		ch->di = 1;
 		emu_update_fidi(ch);
+		/* the ATR should only be sent 400 to 40k clock cycles after the RESET.
+		 * we use the tc_etu mechanism to wait this time.
+		 * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
+		 */
+		tc_etu_set_wtime(ch->tc_chan, 2);
+		/* ensure the TC_ETU timer is enabled */
+		tc_etu_enable(ch->tc_chan);
+		break;
+	case ISO_S_IN_ATR:
 		/* initialize to default WI, this will be overwritten if we
-		 * receive TC2, and it will be programmed into hardware after
+		 * send TC2, and it will be programmed into hardware after
 		 * ATR is finished */
 		ch->wi = ISO7816_3_DEFAULT_WI;
 		/* update waiting time to initial waiting time */
 		ch->waiting_time = ISO7816_3_INIT_WTIME;
+		/* set initial waiting time */
 		tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
 		/* Set ATR sub-state to initial state */
 		ch->atr.idx = 0;
-		//set_atr_state(ch, ATR_S_WAIT_TS);
-		/* Notice that we are just coming out of reset */
-		//ch->sh.flags |= SIMTRACE_FLAG_ATR;
+		/* enable USART transmission to reader */
 		card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
-		break;
+		/* trigger USART TX IRQ to sent first ATR byte TS */
+		card_emu_uart_interrupt(ch->uart_chan);
 		break;
 	case ISO_S_WAIT_TPDU:
 		/* enable the receiver, disable transmitter */
 		set_tpdu_state(ch, TPDU_S_WAIT_CLA);
 		card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
 		break;
-	case ISO_S_IN_ATR:
 	case ISO_S_IN_PTS:
 	case ISO_S_IN_TPDU:
 		/* do nothing */
@@ -329,6 +337,47 @@
 	}
 }
 
+/**********************************************************************
+ * ATR handling
+ **********************************************************************/
+
+/*! Transmit ATR data to reader
+ *  @param[in] ch card interface connected to reader
+ *  @return numbers of bytes transmitted
+ */
+static int tx_byte_atr(struct card_handle *ch)
+{
+	if (NULL == ch) {
+		TRACE_ERROR("ATR TX: no card handle provided\n\r");
+		return 0;
+	}
+	if (ISO_S_IN_ATR != ch->state) {
+		TRACE_ERROR("%u: ATR TX: no in ATR state\n\r", ch->num);
+		return 0;
+	}
+
+	/* Transmit ATR */
+	if (ch->atr.idx < ch->atr.len) {
+		uint8_t byte = ch->atr.atr[ch->atr.idx++];
+		card_emu_uart_tx(ch->uart_chan, byte);
+		TRACE_DEBUG("%u: ATR TX: %02x\n\r", ch->num, byte);
+		return 1;
+	} else { /* The ATR has been completely transmitted */
+		/* TODO update WI using optional TC2 and then update WT */
+		//ch->wi = ISO7816_3_DEFAULT_WI;
+		/* update waiting time */
+		//ch->waiting_time = ISO7816_3_INIT_WTIME;
+		//tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
+		/* reset PTS to initial state */
+		set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
+		/* go to next state */
+		card_set_state(ch, ISO_S_WAIT_TPDU);
+		return 0;
+	}
+
+	/* return number of bytes transmitted */
+	return 1;
+}
 
 /**********************************************************************
  * PTS / PPS handling
@@ -793,17 +842,7 @@
 
 	switch (ch->state) {
 	case ISO_S_IN_ATR:
-		if (ch->atr.idx < ch->atr.len) {
-			uint8_t byte;
-			byte = ch->atr.atr[ch->atr.idx++];
-			rc = 1;
-
-			card_emu_uart_tx(ch->uart_chan, byte);
-
-			/* detect end of ATR */
-			if (ch->atr.idx >= ch->atr.len)
-				card_set_state(ch, ISO_S_WAIT_TPDU);
-		}
+		rc = tx_byte_atr(ch);
 		break;
 	case ISO_S_IN_PTS:
 		rc = tx_byte_pts(ch);
@@ -898,9 +937,8 @@
 			if (ch->vcc_active && ch->clocked) {
 				/* enable the TC/ETU counter once reset has been released */
 				tc_etu_enable(ch->tc_chan);
+				/* prepare to send the ATR */
 				card_set_state(ch, ISO_S_WAIT_ATR);
-				/* FIXME: wait 400 to 40k clock cycles before sending ATR */
-				card_set_state(ch, ISO_S_IN_ATR);
 			}
 		} else if (active && !ch->in_reset) {
 			TRACE_INFO("%u: RST asserted\r\n", ch->num);
@@ -921,7 +959,15 @@
 	ch->atr.len = len;
 	ch->atr.idx = 0;
 
-	/* FIXME: race condition with trasmitting ATR to reader? */
+#if TRACE_LEVEL >= TRACE_LEVEL_INFO 
+	uint8_t i;
+	TRACE_INFO("%u: ATR set: ", ch->num);
+	for (i = 0; i < ch->atr.len; i++) {
+		TRACE_INFO_WP("%02x ", atr[i]);
+	}
+	TRACE_INFO_WP("\n\r");
+#endif
+	/* FIXME: race condition with transmitting ATR to reader? */
 
 	return 0;
 }
@@ -952,7 +998,15 @@
 void tc_etu_wtime_expired(void *handle)
 {
 	struct card_handle *ch = handle;
-	TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
+	switch (ch->state) {
+	case ISO_S_WAIT_ATR:
+		/* ISO 7816-3 6.2.1 time tc has passed, we can now send the ATR */
+		card_set_state(ch, ISO_S_IN_ATR);
+		break;
+	default:
+		TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
+		break;
+	}
 }
 
 /* shortest ATR found in smartcard_list.txt */
diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c
index 57d541b..76b3a01 100644
--- a/firmware/libcommon/source/mode_cardemu.c
+++ b/firmware/libcommon/source/mode_cardemu.c
@@ -1,6 +1,7 @@
 /* card emulation mode
  *
  * (C) 2015-2017 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -98,15 +99,11 @@
 
 static Usart *get_usart_by_chan(uint8_t uart_chan)
 {
-	switch (uart_chan) {
-	case 0:
-		return USART1;
-#ifdef CARDEMU_SECOND_UART
-	case 1:
-		return USART0;
-#endif
+	if (uart_chan < ARRAY_SIZE(cardem_inst)) {
+		return cardem_inst[uart_chan].usart_info.base;
+	} else {
+		return NULL;
 	}
-	return NULL;
 }
 
 /***********************************************************************
@@ -244,6 +241,20 @@
 	return 0;
 }
 
+/* call-back from card_emu.c to force a USART interrupt */
+void card_emu_uart_interrupt(uint8_t uart_chan)
+{
+	Usart *usart = get_usart_by_chan(uart_chan);
+	if (!usart) {
+		return;
+	}
+	if (USART0 == usart) {
+		NVIC_SetPendingIRQ(USART0_IRQn);
+	} else if (USART1 == usart) {
+		NVIC_SetPendingIRQ(USART1_IRQn);
+	}
+}
+
 /***********************************************************************
  * ADC for VCC voltage detection
  ***********************************************************************/
diff --git a/firmware/test/card_emu_tests.c b/firmware/test/card_emu_tests.c
index 3ea0678..09b2e0d 100644
--- a/firmware/test/card_emu_tests.c
+++ b/firmware/test/card_emu_tests.c
@@ -65,6 +65,11 @@
 	printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
 }
 
+void card_emu_uart_interrupt(uint8_t uart_chan)
+{
+	printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
+}
+
 void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
 {
 	printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
@@ -120,6 +125,8 @@
 
 	/* release from reset and verify th ATR */
 	card_emu_io_statechg(ch, CARD_IO_RST, 0);
+	/* simulate waiting time before ATR expired */
+	tc_etu_wtime_expired(ch);
 	verify_atr(ch);
 }
 

-- 
To view, visit https://gerrit.osmocom.org/10217
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I69df797e2feadffa9f5f977cb71b69386cee7cd0
Gerrit-Change-Number: 10217
Gerrit-PatchSet: 3
Gerrit-Owner: Kévin Redon <kredon at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180730/07b39730/attachment.htm>


More information about the gerrit-log mailing list