<p>laforge would like tsaitgaist to <strong>review</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/simtrace2/+/23620">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cardem: use USART timeout for waiting time<br><br>the reset/ATR handling has been heavily updated/fixed.<br>instead of using the timer counter peripheral to handle<br>the waiting time and corresponding timeout, the USART peripheral<br>internal timeout mechanism is used.<br>this is particularly important for the SIMtrace board since the<br>clock signal is not connected to the timer counter.<br>thus this change adds card emulation support for SIMtrace boards.<br><br>Fi and Di have been properly rename to F and D since the "i"<br>stands only for an "indicated" value, not the actual value.<br>this does not change the USB protocol (the variable have just been<br>renamed).<br>additional variables store more information about the card<br>capabilities<br><br>NOTE: it has only be tested for the SIMtrace board<br><br>Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5<br>---<br>M contrib/jenkins.sh<br>M firmware/apps/cardem/Makefile<br>M firmware/apps/cardem/main.c<br>M firmware/apps/trace/Makefile<br>M firmware/libboard/qmod/include/board.h<br>M firmware/libboard/simtrace/include/board.h<br>M firmware/libcommon/include/card_emu.h<br>M firmware/libcommon/include/simtrace_prot.h<br>M firmware/libcommon/include/tc_etu.h<br>M firmware/libcommon/source/card_emu.c<br>M firmware/libcommon/source/mode_cardemu.c<br>M firmware/libcommon/source/tc_etu.c<br>M firmware/libosmocore/include/osmocom/core/utils.h<br>M host/src/simtrace2-cardem-pcsc.c<br>14 files changed, 365 insertions(+), 66 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/20/23620/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh</span><br><span>index 1d6ff37..3f2eb7e 100755</span><br><span>--- a/contrib/jenkins.sh</span><br><span>+++ b/contrib/jenkins.sh</span><br><span>@@ -28,7 +28,7 @@</span><br><span> export LD_LIBRARY_PATH="$inst/lib"</span><br><span> </span><br><span> BUILDS=""</span><br><span style="color: hsl(0, 100%, 40%);">-BUILDS+="simtrace/dfu simtrace/trace "</span><br><span style="color: hsl(120, 100%, 40%);">+BUILDS+="simtrace/dfu simtrace/trace simtrace/cardem "</span><br><span> BUILDS+="qmod/dfu qmod/cardem "</span><br><span> BUILDS+="owhw/dfu owhw/cardem "</span><br><span> </span><br><span>diff --git a/firmware/apps/cardem/Makefile b/firmware/apps/cardem/Makefile</span><br><span>index d5f68a5..d2039a5 100644</span><br><span>--- a/firmware/apps/cardem/Makefile</span><br><span>+++ b/firmware/apps/cardem/Makefile</span><br><span>@@ -1,3 +1,3 @@</span><br><span> C_FILES += $(C_LIBUSB_RT)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-C_FILES += card_emu.c cciddriver.c iso7816_3.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c</span><br><span style="color: hsl(120, 100%, 40%);">+C_FILES += card_emu.c iso7816_fidi.c iso7816_3.c iso7816_4.c mode_cardemu.c simtrace_iso7816.c tc_etu.c usb.c</span><br><span>diff --git a/firmware/apps/cardem/main.c b/firmware/apps/cardem/main.c</span><br><span>index a30a211..e1ab8fb 100644</span><br><span>--- a/firmware/apps/cardem/main.c</span><br><span>+++ b/firmware/apps/cardem/main.c</span><br><span>@@ -165,7 +165,7 @@</span><br><span>    while (USBD_GetState() < USBD_STATE_CONFIGURED) {</span><br><span>                 WDT_Restart(WDT);</span><br><span>            check_exec_dbg_cmd();</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+#if 1</span><br><span>            if (i >= MAX_USB_ITER * 3) {</span><br><span>                      TRACE_ERROR("Resetting board (USB could "</span><br><span>                              "not be configured)\n\r");</span><br><span>diff --git a/firmware/apps/trace/Makefile b/firmware/apps/trace/Makefile</span><br><span>index 75c43e8..ddea898 100644</span><br><span>--- a/firmware/apps/trace/Makefile</span><br><span>+++ b/firmware/apps/trace/Makefile</span><br><span>@@ -1,3 +1,3 @@</span><br><span> C_FILES += $(C_LIBUSB_RT)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c</span><br><span style="color: hsl(120, 100%, 40%);">+C_FILES += iso7816_4.c iso7816_fidi.c simtrace_iso7816.c sniffer.c usb.c</span><br><span>diff --git a/firmware/libboard/qmod/include/board.h b/firmware/libboard/qmod/include/board.h</span><br><span>index 5165434..6f95d12 100644</span><br><span>--- a/firmware/libboard/qmod/include/board.h</span><br><span>+++ b/firmware/libboard/qmod/include/board.h</span><br><span>@@ -111,4 +111,7 @@</span><br><span> #define CARDEMU_SECOND_UART</span><br><span> #define DETECT_VCC_BY_ADC</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/** sysmoQMOD only supports card emulation */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef APPLICATION_cardem</span><br><span> #define HAVE_CARDEM</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h</span><br><span>index 5302c8b..65e6197 100644</span><br><span>--- a/firmware/libboard/simtrace/include/board.h</span><br><span>+++ b/firmware/libboard/simtrace/include/board.h</span><br><span>@@ -153,10 +153,18 @@</span><br><span> </span><br><span> /** Supported modes */</span><br><span> /* SIMtrace board supports sniffer mode */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef APPLICATION_trace</span><br><span> #define HAVE_SNIFFER</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> /* SIMtrace board supports CCID mode */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef APPLICATION_ccid</span><br><span> //#define HAVE_CCID</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> /* SIMtrace board supports card emulation mode */</span><br><span style="color: hsl(0, 100%, 40%);">-//#define HAVE_CARDEM</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef APPLICATION_cardem</span><br><span style="color: hsl(120, 100%, 40%);">+#define HAVE_CARDEM</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> /* SIMtrace board supports man-in-the-middle mode */</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef APPLICATION_mitm</span><br><span> //#define HAVE_MITM</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/firmware/libcommon/include/card_emu.h b/firmware/libcommon/include/card_emu.h</span><br><span>index 8a73d5c..494d1e6 100644</span><br><span>--- a/firmware/libcommon/include/card_emu.h</span><br><span>+++ b/firmware/libcommon/include/card_emu.h</span><br><span>@@ -58,10 +58,43 @@</span><br><span> void card_emu_have_new_uart_tx(struct card_handle *ch);</span><br><span> void card_emu_report_status(struct card_handle *ch, bool report_on_irq);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! call when the waiting time has half-expired</span><br><span style="color: hsl(120, 100%, 40%);">+ *  param[in] ch card for which the waiting time half expired</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_halfed(void *ch);</span><br><span style="color: hsl(120, 100%, 40%);">+/*! call when the waiting time has expired</span><br><span style="color: hsl(120, 100%, 40%);">+ *  param[in] ch card for which the waiting time expired</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_expired(void *ch);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define ENABLE_TX     0x01</span><br><span> #define ENABLE_RX       0x02</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+// the following functions are callbacks implement in mode_cardemu.c</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! update F and D on USART peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] usart USART peripheral to configure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] f clock rate conversion integer F value</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] d baud rate adjustment factor D value</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @note this should happen after reset and protocol select (through PPS or implicit)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_update_fd(uint8_t uart_chan, uint16_t f, uint8_t d);</span><br><span style="color: hsl(120, 100%, 40%);">+/*! update WT on USART peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] usart USART peripheral to configure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] wt inactivity Waiting Time before card_emu_wt_expired is called (0 to disable)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt);</span><br><span style="color: hsl(120, 100%, 40%);">+/*! reset waiting timeout count down on USART peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] usart USART peripheral to configure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_reset_wt(uint8_t uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+/*! set I/O line high</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] usart USART peripheral to configure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] set if I/O line should be set high (true), or cleared low (false)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_io_set(uint8_t uart_chan, bool set);</span><br><span> int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte);</span><br><span> void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx);</span><br><span> void card_emu_uart_wait_tx_idle(uint8_t uart_chan);</span><br><span>diff --git a/firmware/libcommon/include/simtrace_prot.h b/firmware/libcommon/include/simtrace_prot.h</span><br><span>index eca844a..e4832bb 100644</span><br><span>--- a/firmware/libcommon/include/simtrace_prot.h</span><br><span>+++ b/firmware/libcommon/include/simtrace_prot.h</span><br><span>@@ -230,11 +230,10 @@</span><br><span>     uint32_t flags;</span><br><span>      /* phone-applied target voltage in mV */</span><br><span>     uint16_t voltage_mv;</span><br><span style="color: hsl(0, 100%, 40%);">-    /* Fi/Di related information */</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t fi;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t di;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t wi;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint32_t waiting_time;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t f; /*!< index of F and f_max values as encoded in ISO/IEC 7816-3:2006(E) Table 7 */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t d; /*!< index of D value as encoded in ISO/IEC 7816-3:2006(E) Table 8 */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t wi; /*!< Waiting Integer as defined in ISO/IEC 7816-3:2006(E) Section 10.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t wt; /*!< Waiting Time in ETU as defined in ISO/IEC 7816-3:2006(E) Section 8.1 */</span><br><span> } __attribute__ ((packed));</span><br><span> </span><br><span> /* CEMU_USB_MSGT_DO_PTS */</span><br><span>diff --git a/firmware/libcommon/include/tc_etu.h b/firmware/libcommon/include/tc_etu.h</span><br><span>index 663ae5a..8817a41 100644</span><br><span>--- a/firmware/libcommon/include/tc_etu.h</span><br><span>+++ b/firmware/libcommon/include/tc_etu.h</span><br><span>@@ -7,5 +7,3 @@</span><br><span> void tc_etu_enable(uint8_t chan_nr);</span><br><span> void tc_etu_disable(uint8_t chan_nr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-extern void tc_etu_wtime_half_expired(void *handle);</span><br><span style="color: hsl(0, 100%, 40%);">-extern void tc_etu_wtime_expired(void *handle);</span><br><span>diff --git a/firmware/libcommon/source/card_emu.c b/firmware/libcommon/source/card_emu.c</span><br><span>index 269c7c6..fb532d5 100644</span><br><span>--- a/firmware/libcommon/source/card_emu.c</span><br><span>+++ b/firmware/libcommon/source/card_emu.c</span><br><span>@@ -1,7 +1,7 @@</span><br><span> /* ISO7816-3 state machine for the card side</span><br><span>  *</span><br><span>  * (C) 2010-2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de></span><br><span>  *</span><br><span>  * This program is free software; you can redistribute it and/or modify</span><br><span>  * it under the terms of the GNU General Public License as published by</span><br><span>@@ -26,6 +26,7 @@</span><br><span> </span><br><span> #include "utils.h"</span><br><span> #include "trace.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "iso7816_3.h"</span><br><span> #include "iso7816_fidi.h"</span><br><span> #include "tc_etu.h"</span><br><span> #include "card_emu.h"</span><br><span>@@ -154,18 +155,53 @@</span><br><span>   bool in_reset;  /*< if card is in reset (true = RST low/asserted, false = RST high/ released) */</span><br><span>  bool clocked;   /*< if clock is active ( true = active, false = inactive) */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* timing parameters, from PTS */</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t fi;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t di;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t wi;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>  uint8_t tc_chan;        /* TC channel number */</span><br><span>      uint8_t uart_chan;      /* UART channel */</span><br><span> </span><br><span>       uint8_t in_ep;          /* USB IN EP */</span><br><span>      uint8_t irq_ep;         /* USB IN EP */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     uint32_t waiting_time;  /* in clocks */</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! clock rate conversion integer F</span><br><span style="color: hsl(120, 100%, 40%);">+    *  @implements ISO/IEC 7816-3:2006(E) section 7.1</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @note this represents the current value used</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t f;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! baud rate adjustment factor D</span><br><span style="color: hsl(120, 100%, 40%);">+      *  @implements ISO/IEC 7816-3:2006(E) section 7.1</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @note this represents the current value used</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t d;</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! clock frequency in Hz</span><br><span style="color: hsl(120, 100%, 40%);">+      *  @implements ISO/IEC 7816-3:2006(E) section 7.1</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @note the USART peripheral in slave mode does not provide the current value. we could measure it but this is not really useful. instead we remember the maximum possible value corresponding to the selected F value</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t f_cur;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! clock rate conversion integer Fi</span><br><span style="color: hsl(120, 100%, 40%);">+   *  @implements ISO/IEC 7816-3:2006(E) Table 7</span><br><span style="color: hsl(120, 100%, 40%);">+         *  @note this represents the maximum value supported by the card, and can be indicated in TA1</span><br><span style="color: hsl(120, 100%, 40%);">+         *  @note this value can be set in TA1</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t fi;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*! baud rate adjustment factor Di</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @implements ISO/IEC 7816-3:2006(E) Table 8</span><br><span style="color: hsl(120, 100%, 40%);">+         *  @note this represents the maximum value supported by the card, and can be indicated in TA1</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t di;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! clock frequency, in Hz</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @implements ISO/IEC 7816-3:2006(E) Table 7</span><br><span style="color: hsl(120, 100%, 40%);">+         *  @note this represents the maximum value supported by the card, and can be indicated in TA1</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t f_max;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! Waiting Integer</span><br><span style="color: hsl(120, 100%, 40%);">+    *  @implements ISO/IEC 7816-3:2006(E) Section 10.2</span><br><span style="color: hsl(120, 100%, 40%);">+    *  @note this value can be set in TA2</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t wi;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! Waiting Time, in ETU</span><br><span style="color: hsl(120, 100%, 40%);">+       *  @implements ISO/IEC 7816-3:2006(E) Section 8.1</span><br><span style="color: hsl(120, 100%, 40%);">+     *  @note this depends on Fi, Di, and WI if T=0 is used</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t wt;</span><br><span> </span><br><span>     /* ATR state machine */</span><br><span>      struct {</span><br><span>@@ -206,7 +242,9 @@</span><br><span> {</span><br><span>  struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef BOARD_simtrace</span><br><span>        tc_etu_disable(ch->tc_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>  /* release any buffers we may still own */</span><br><span>   if (ch->uart_tx_msg) {</span><br><span>@@ -390,13 +428,44 @@</span><br><span>    case ISO_S_WAIT_POWER:</span><br><span>       case ISO_S_WAIT_CLK:</span><br><span>         case ISO_S_WAIT_RST:</span><br><span style="color: hsl(0, 100%, 40%);">-            /* disable Rx and Tx of UART */</span><br><span style="color: hsl(0, 100%, 40%);">-         card_emu_uart_enable(ch->uart_chan, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            card_emu_uart_enable(ch->uart_chan, 0); // disable Rx and Tx of UART</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+                card_emu_uart_update_wt(ch->uart_chan, 0); // disable timeout</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ISO_S_WAIT_POWER == new_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  card_emu_uart_io_set(ch->uart_chan, false); // pull I/O line low</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      card_emu_uart_io_set(ch->uart_chan, true); // pull I/O line high</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>            break;</span><br><span>       case ISO_S_WAIT_ATR:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                // reset the ETU-related values</span><br><span style="color: hsl(120, 100%, 40%);">+               ch->f = ISO7816_3_DEFAULT_FD;</span><br><span style="color: hsl(120, 100%, 40%);">+              ch->d = ISO7816_3_DEFAULT_DD;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+             card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             // reset values optionally specified in the ATR</span><br><span style="color: hsl(120, 100%, 40%);">+               ch->fi = ISO7816_3_DEFAULT_FI;</span><br><span style="color: hsl(120, 100%, 40%);">+             ch->di = ISO7816_3_DEFAULT_DI;</span><br><span style="color: hsl(120, 100%, 40%);">+             ch->wi = ISO7816_3_DEFAULT_WI;</span><br><span style="color: hsl(120, 100%, 40%);">+             int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get default waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+         if (wt <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     TRACE_FATAL("%u: invalid WT %ld\r\n", ch->num, wt);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             ch->wt = wt;</span><br><span style="color: hsl(120, 100%, 40%);">+               card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // enable TX to be able to use the timeout</span><br><span style="color: hsl(120, 100%, 40%);">+         /* the ATR should only be sent 400 to 40k clock cycles after the RESET.</span><br><span style="color: hsl(120, 100%, 40%);">+                * we use the UART timeout mechanism to wait this time.</span><br><span style="color: hsl(120, 100%, 40%);">+                * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.</span><br><span style="color: hsl(120, 100%, 40%);">+          */</span><br><span style="color: hsl(120, 100%, 40%);">+           card_emu_uart_update_wt(ch->uart_chan, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span>                 /* Reset to initial Fi / Di ratio */</span><br><span style="color: hsl(0, 100%, 40%);">-            ch->fi = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-          ch->di = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                ch->f = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+         ch->d = 1;</span><br><span>                emu_update_fidi(ch);</span><br><span>                 /* the ATR should only be sent 400 to 40k clock cycles after the RESET.</span><br><span>               * we use the tc_etu mechanism to wait this time.</span><br><span>@@ -405,16 +474,20 @@</span><br><span>            tc_etu_set_wtime(ch->tc_chan, 2);</span><br><span>                 /* enable the TC/ETU counter once reset has been released */</span><br><span>                 tc_etu_enable(ch->tc_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>             break;</span><br><span>       case ISO_S_IN_ATR:</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef BOARD_simtrace</span><br><span>           /* initialize to default WI, this will be overwritten if we</span><br><span>           * send TC2, and it will be programmed into hardware after</span><br><span>            * ATR is finished */</span><br><span>                ch->wi = ISO7816_3_DEFAULT_WI;</span><br><span>            /* update waiting time to initial waiting time */</span><br><span style="color: hsl(0, 100%, 40%);">-               ch->waiting_time = ISO7816_3_INIT_WTIME;</span><br><span style="color: hsl(120, 100%, 40%);">+           ch->wt = ISO7816_3_INIT_WTIME;</span><br><span>            /* set initial waiting time */</span><br><span style="color: hsl(0, 100%, 40%);">-          tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);</span><br><span style="color: hsl(120, 100%, 40%);">+                tc_etu_set_wtime(ch->tc_chan, ch->wt);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                 /* Set ATR sub-state to initial state */</span><br><span>             ch->atr.idx = 0;</span><br><span>          /* enable USART transmission to reader */</span><br><span>@@ -489,9 +562,15 @@</span><br><span>                             }</span><br><span>                    }</span><br><span>            }</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+              /* FIXME update waiting time in case of card is specific mode */</span><br><span style="color: hsl(120, 100%, 40%);">+              /* reset PTS to initial state */</span><br><span style="color: hsl(120, 100%, 40%);">+              set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span>               /* update waiting time (see ISO 7816-3 10.2) */</span><br><span style="color: hsl(0, 100%, 40%);">-         ch->waiting_time = ch->wi * 960 * ch->fi;</span><br><span style="color: hsl(0, 100%, 40%);">-              tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);</span><br><span style="color: hsl(120, 100%, 40%);">+                ch->wt = ch->wi * 960 * ch->fi;</span><br><span style="color: hsl(120, 100%, 40%);">+              tc_etu_set_wtime(ch->tc_chan, ch->wt);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                 /* go to next state */</span><br><span>               card_set_state(ch, ISO_S_WAIT_TPDU);</span><br><span>                 return 0;</span><br><span>@@ -557,9 +636,12 @@</span><br><span>     return PTS_S_WAIT_REQ_PCK | is_resp;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int</span><br><span style="color: hsl(0, 100%, 40%);">-process_byte_pts(struct card_handle *ch, uint8_t byte)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! process incoming PTS byte</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] ch card handle on which the byte has been received</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] byte received PTS byte</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @return new iso7816_3_card_state or -1 at the end of PTS request</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_byte_pts(struct card_handle *ch, uint8_t byte)</span><br><span> {</span><br><span>    switch (ch->pts.state) {</span><br><span>  case PTS_S_WAIT_REQ_PTSS:</span><br><span>@@ -625,11 +707,17 @@</span><br><span>            break;</span><br><span>       case PTS_S_WAIT_RESP_PTS1:</span><br><span>           byte = ch->pts.resp[_PTS1];</span><br><span style="color: hsl(0, 100%, 40%);">-          /* This must be TA1 */</span><br><span style="color: hsl(0, 100%, 40%);">-          ch->fi = byte >> 4;</span><br><span style="color: hsl(0, 100%, 40%);">-            ch->di = byte & 0xf;</span><br><span style="color: hsl(0, 100%, 40%);">-             TRACE_DEBUG("%u: found Fi=%u Di=%u\r\n", ch->num,</span><br><span style="color: hsl(0, 100%, 40%);">-                      ch->fi, ch->di);</span><br><span style="color: hsl(120, 100%, 40%);">+            // TODO the value should have been validated when receiving the request</span><br><span style="color: hsl(120, 100%, 40%);">+               ch->f = iso7816_3_fi_table[byte >> 4]; // save selected Fn</span><br><span style="color: hsl(120, 100%, 40%);">+           if (0 == ch->f) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  TRACE_ERROR("%u: invalid F index in PPS response: %u\r\n", ch->num, byte >> 4);</span><br><span style="color: hsl(120, 100%, 40%);">+                    // TODO become unresponsive to signal error condition</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             ch->d = iso7816_3_di_table[byte & 0xf]; // save selected Dn</span><br><span style="color: hsl(120, 100%, 40%);">+            if (0 == ch->d) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  TRACE_ERROR("%u: invalid D index in PPS response: %u\r\n", ch->num, byte & 0xf);</span><br><span style="color: hsl(120, 100%, 40%);">+                     // TODO become unresponsive to signal error condition</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span>            break;</span><br><span>       case PTS_S_WAIT_RESP_PTS2:</span><br><span>           byte = ch->pts.resp[_PTS2];</span><br><span>@@ -654,10 +742,23 @@</span><br><span>       switch (ch->pts.state) {</span><br><span>  case PTS_S_WAIT_RESP_PCK:</span><br><span>            card_emu_uart_wait_tx_idle(ch->uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+          card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set selected baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+              int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get new waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+             if (wt <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     TRACE_ERROR("%u: invalid WT calculated: %ld\r\n", ch->num, wt);</span><br><span style="color: hsl(120, 100%, 40%);">+                  // TODO become unresponsive to signal error condition</span><br><span style="color: hsl(120, 100%, 40%);">+         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ch->wt = wt;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             // FIXME disable WT</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span>           /* update baud rate generator with Fi/Di */</span><br><span>          emu_update_fidi(ch);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                 /* Wait for the next TPDU */</span><br><span>                 card_set_state(ch, ISO_S_WAIT_TPDU);</span><br><span style="color: hsl(120, 100%, 40%);">+          set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);</span><br><span>              break;</span><br><span>       default:</span><br><span>             /* calculate the next state and set it */</span><br><span>@@ -725,6 +826,10 @@</span><br><span> {</span><br><span>        if (ch->tpdu.state == new_ts)</span><br><span>             return;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ISO_S_IN_TPDU != ch->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: setting TPDU state in %s state\r\n", ch->num,</span><br><span style="color: hsl(120, 100%, 40%);">+                   get_value_string(iso7816_3_card_state_names, ch->state));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </span><br><span>        TRACE_DEBUG("%u: 7816 TPDU state %s -> %s\r\n", ch->num,</span><br><span>             get_value_string(tpdu_state_names, ch->tpdu.state),</span><br><span>@@ -732,15 +837,20 @@</span><br><span>       ch->tpdu.state = new_ts;</span><br><span> </span><br><span>      switch (new_ts) {</span><br><span style="color: hsl(0, 100%, 40%);">-       case TPDU_S_WAIT_CLA:</span><br><span style="color: hsl(0, 100%, 40%);">-   case TPDU_S_WAIT_RX:</span><br><span style="color: hsl(0, 100%, 40%);">-            card_emu_uart_enable(ch->uart_chan, ENABLE_RX);</span><br><span style="color: hsl(120, 100%, 40%);">+    case TPDU_S_WAIT_CLA: // we will be waiting for the next incoming TDPU</span><br><span style="color: hsl(120, 100%, 40%);">+                card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch back to receiving mode</span><br><span style="color: hsl(120, 100%, 40%);">+           card_emu_uart_update_wt(ch->uart_chan, 0); // disable waiting time since we don't expect any data</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TPDU_S_WAIT_INS: // the reader started sending the TPDU header</span><br><span style="color: hsl(120, 100%, 40%);">+           card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest of the header/body</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TPDU_S_WAIT_RX: // the reader should send us the TPDU body data</span><br><span style="color: hsl(120, 100%, 40%);">+          card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch to receive mode to receive the body</span><br><span style="color: hsl(120, 100%, 40%);">+              card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest body</span><br><span>             break;</span><br><span>       case TPDU_S_WAIT_PB:</span><br><span style="color: hsl(0, 100%, 40%);">-            /* we just completed the TPDU header from reader to card</span><br><span style="color: hsl(0, 100%, 40%);">-                 * and now need to disable the receiver, enable the</span><br><span style="color: hsl(0, 100%, 40%);">-              * transmitter and transmit the procedure byte */</span><br><span style="color: hsl(0, 100%, 40%);">-               card_emu_uart_enable(ch->uart_chan, ENABLE_TX);</span><br><span style="color: hsl(120, 100%, 40%);">+            card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // header is completely received, now we need to transmit the procedure byte</span><br><span style="color: hsl(120, 100%, 40%);">+               card_emu_uart_update_wt(ch->uart_chan, ch->wt); // prepare to extend the waiting time once half of it is reached</span><br><span>               break;</span><br><span>       default:</span><br><span>             break;</span><br><span>@@ -1024,11 +1134,11 @@</span><br><span>             sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;</span><br><span>   if (ch->in_reset)</span><br><span>                 sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;</span><br><span style="color: hsl(0, 100%, 40%);">-    /* FIXME: voltage + card insert */</span><br><span style="color: hsl(0, 100%, 40%);">-      sts->fi = ch->fi;</span><br><span style="color: hsl(0, 100%, 40%);">- sts->di = ch->di;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* FIXME set voltage and card insert values */</span><br><span style="color: hsl(120, 100%, 40%);">+        sts->f = ch->f;</span><br><span style="color: hsl(120, 100%, 40%);">+ sts->d = ch->d;</span><br><span>        sts->wi = ch->wi;</span><br><span style="color: hsl(0, 100%, 40%);">- sts->waiting_time = ch->waiting_time;</span><br><span style="color: hsl(120, 100%, 40%);">+   sts->wt = ch->wt;</span><br><span> </span><br><span>  usb_buf_upd_len_and_submit(msg);</span><br><span> }</span><br><span>@@ -1083,9 +1193,7 @@</span><br><span>        case CARD_IO_RST:</span><br><span>            if (active == 0 && ch->in_reset) {</span><br><span>                        TRACE_INFO("%u: RST released\r\n", ch->num);</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (ch->vcc_active && ch->clocked) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              /* enable the TC/ETU counter once reset has been released */</span><br><span style="color: hsl(0, 100%, 40%);">-                            tc_etu_enable(ch->tc_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (ch->vcc_active && ch->clocked && ISO_S_WAIT_RST == ch->state) {</span><br><span>                                 /* prepare to send the ATR */</span><br><span>                                card_set_state(ch, ISO_S_WAIT_ATR);</span><br><span>                  }</span><br><span>@@ -1094,9 +1202,14 @@</span><br><span>                   TRACE_INFO("%u: RST asserted\r\n", ch->num);</span><br><span>                    card_handle_reset(ch);</span><br><span>                       chg_mask |= CEMU_STATUS_F_RESET_ACTIVE;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+                        card_set_state(ch, ISO_S_WAIT_RST);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>          }</span><br><span>            ch->in_reset = active;</span><br><span>            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       }</span><br><span> </span><br><span>        switch (ch->state) {</span><br><span>@@ -1143,7 +1256,7 @@</span><br><span> }</span><br><span> </span><br><span> /* hardware driver informs us that one (more) ETU has expired */</span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_wtime_half_expired(void *handle)</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_halfed(void *handle)</span><br><span> {</span><br><span>         struct card_handle *ch = handle;</span><br><span>     /* transmit NULL procedure byte well before waiting time expires */</span><br><span>@@ -1153,7 +1266,8 @@</span><br><span>          case TPDU_S_WAIT_PB:</span><br><span>                 case TPDU_S_WAIT_TX:</span><br><span>                         putchar('N');</span><br><span style="color: hsl(0, 100%, 40%);">-                   card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                        card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL); // we are waiting for data from the user. send a procedure byte to ask the reader to wait more time</span><br><span style="color: hsl(120, 100%, 40%);">+                    card_emu_uart_reset_wt(ch->uart_chan); // reset WT</span><br><span>                        break;</span><br><span>               default:</span><br><span>                     break;</span><br><span>@@ -1165,7 +1279,7 @@</span><br><span> }</span><br><span> </span><br><span> /* hardware driver informs us that one (more) ETU has expired */</span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_wtime_expired(void *handle)</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_expired(void *handle)</span><br><span> {</span><br><span>      struct card_handle *ch = handle;</span><br><span>     switch (ch->state) {</span><br><span>@@ -1174,6 +1288,7 @@</span><br><span>              card_set_state(ch, ISO_S_IN_ATR);</span><br><span>            break;</span><br><span>       default:</span><br><span style="color: hsl(120, 100%, 40%);">+              // TODO become unresponsive</span><br><span>          TRACE_ERROR("%u: wtime_exp\r\n", ch->num);</span><br><span>              break;</span><br><span>       }</span><br><span>@@ -1224,6 +1339,7 @@</span><br><span> </span><br><span>        INIT_LLIST_HEAD(&ch->uart_tx_queue);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       /* initialize the card_handle with reasonable defaults */</span><br><span>    ch->num = slot_num;</span><br><span>       ch->irq_ep = irq_ep;</span><br><span>      ch->in_ep = in_ep;</span><br><span>@@ -1232,21 +1348,26 @@</span><br><span>      ch->in_reset = in_reset;</span><br><span>  ch->clocked = clocked;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ch->fi = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  ch->di = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        ch->fi = ISO7816_3_DEFAULT_FI;</span><br><span style="color: hsl(120, 100%, 40%);">+     ch->di = ISO7816_3_DEFAULT_DI;</span><br><span>    ch->wi = ISO7816_3_DEFAULT_WI;</span><br><span style="color: hsl(120, 100%, 40%);">+     ch->wt = ISO7816_3_DEFAULT_WT;;</span><br><span> </span><br><span>       ch->tc_chan = tc_chan;</span><br><span>    ch->uart_chan = uart_chan;</span><br><span style="color: hsl(0, 100%, 40%);">-   ch->waiting_time = ISO7816_3_INIT_WTIME;</span><br><span> </span><br><span>      ch->atr.idx = 0;</span><br><span>  ch->atr.len = sizeof(default_atr);</span><br><span>        memcpy(ch->atr.atr, default_atr, ch->atr.len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        card_handle_reset(ch);</span><br><span style="color: hsl(120, 100%, 40%);">+        ch->pts.state = PTS_S_WAIT_REQ_PTSS;</span><br><span style="color: hsl(120, 100%, 40%);">+       ch->tpdu.state = TPDU_S_WAIT_CLA;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      card_handle_reset(ch);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+        /* simtrace uses uart timer instead */</span><br><span>       tc_etu_init(ch->tc_chan, ch);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>         return ch;</span><br><span> }</span><br><span>diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c</span><br><span>index c6c129d..32d3b17 100644</span><br><span>--- a/firmware/libcommon/source/mode_cardemu.c</span><br><span>+++ b/firmware/libcommon/source/mode_cardemu.c</span><br><span>@@ -22,6 +22,7 @@</span><br><span> #include "simtrace.h"</span><br><span> #include "ringbuffer.h"</span><br><span> #include "card_emu.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "iso7816_3.h"</span><br><span> #include "iso7816_fidi.h"</span><br><span> #include "utils.h"</span><br><span> #include <osmocom/core/linuxlist.h></span><br><span>@@ -54,11 +55,15 @@</span><br><span>      struct card_handle *ch;</span><br><span>      struct llist_head usb_out_queue;</span><br><span>     struct ringbuf rb;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t wt; /*!< receiver waiting time to trigger timeout (0 to deactivate it) */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t wt_remaining; /*!< remaining waiting time */</span><br><span style="color: hsl(120, 100%, 40%);">+      bool wt_halfed; /*!< if at least half of the waiting time passed */</span><br><span>       struct Usart_info usart_info;</span><br><span>        int usb_pending_old;</span><br><span>         uint8_t ep_out;</span><br><span>      uint8_t ep_in;</span><br><span>       uint8_t ep_int;</span><br><span style="color: hsl(120, 100%, 40%);">+       const Pin pin_io;</span><br><span>    const Pin pin_insert;</span><br><span> #ifdef DETECT_VCC_BY_ADC</span><br><span>    uint32_t vcc_uv;</span><br><span>@@ -81,6 +86,7 @@</span><br><span>                 .ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT,</span><br><span>              .ep_in = SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,</span><br><span>                .ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT,</span><br><span style="color: hsl(120, 100%, 40%);">+           .pin_io = PIN_USIM1_IO,</span><br><span> #ifdef PIN_SET_USIM1_PRES</span><br><span>                 .pin_insert = PIN_SET_USIM1_PRES,</span><br><span> #endif</span><br><span>@@ -96,6 +102,7 @@</span><br><span>             .ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT,</span><br><span>              .ep_in = SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,</span><br><span>                .ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT,</span><br><span style="color: hsl(120, 100%, 40%);">+           .pin_io = PIN_USIM2_IO,</span><br><span> #ifdef PIN_SET_USIM2_PRES</span><br><span>                 .pin_insert = PIN_SET_USIM2_PRES,</span><br><span> #endif</span><br><span>@@ -146,7 +153,11 @@</span><br><span>            * receiver enabled during transmit */</span><br><span>               USART_SetReceiverEnabled(usart, 1);</span><br><span>          usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+          USART_EnableIt(usart, US_IER_TXRDY | US_IER_TIMEOUT);</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span>                 USART_EnableIt(usart, US_IER_TXRDY);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                 USART_SetTransmitterEnabled(usart, 1);</span><br><span>               break;</span><br><span>       case ENABLE_RX:</span><br><span>@@ -156,7 +167,11 @@</span><br><span>               USART_SetTransmitterEnabled(usart, 1);</span><br><span>               wait_tx_idle(usart);</span><br><span>                 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+          USART_EnableIt(usart, US_IER_RXRDY | US_IER_TIMEOUT);</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span>                 USART_EnableIt(usart, US_IER_RXRDY);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                 USART_SetReceiverEnabled(usart, 1);</span><br><span>          break;</span><br><span>       case 0:</span><br><span>@@ -198,11 +213,18 @@</span><br><span> /* FIXME: integrate this with actual irq handler */</span><br><span> static void usart_irq_rx(uint8_t inst_num)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       OSMO_ASSERT(inst_num < ARRAY_SIZE(cardem_inst));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (inst_num >= ARRAY_SIZE(cardem_inst)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         TRACE_ERROR("%u: UART channel out of bounds\r\n", inst_num);</span><br><span style="color: hsl(120, 100%, 40%);">+                return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span>    Usart *usart = get_usart_by_chan(inst_num);</span><br><span>  struct cardem_inst *ci = &cardem_inst[inst_num];</span><br><span>         uint32_t csr;</span><br><span>        uint8_t byte = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t errflags = (US_CSR_OVRE | US_CSR_FRAME | US_CSR_PARE | US_CSR_NACK | (1 << 10));</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+       errflags |= US_CSR_TIMEOUT;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>      csr = usart->US_CSR & usart->US_IMR; // save state/flags before they get changed</span><br><span> </span><br><span>@@ -217,10 +239,33 @@</span><br><span>                       USART_DisableIt(usart, US_IER_TXRDY); // stop the TX ready signal if not byte has been transmitted</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) { // error flag set</span><br><span style="color: hsl(120, 100%, 40%);">+    if (csr & errflags) { // error flag set</span><br><span>          usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; // reset UART state to clear flag</span><br><span>              TRACE_ERROR("%u USART error on 0x%x status: 0x%lx\n", ci->num, byte, csr); // warn user about error</span><br><span>     }</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef BOARD_simtrace</span><br><span style="color: hsl(120, 100%, 40%);">+      // handle timeout</span><br><span style="color: hsl(120, 100%, 40%);">+     if (csr & US_CSR_TIMEOUT) { // RX has been inactive for some time</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ci->wt_remaining <= (usart->US_RTOR & 0xffff)) { // waiting time has passed</span><br><span style="color: hsl(120, 100%, 40%);">+                  ci->wt_remaining = 0; // timeout reached (will stop the timer)</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ci->wt_remaining -= (usart->US_RTOR & 0xffff); // be sure to subtract the actual timeout since the new might not have been set and reloaded yet</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (0 == ci->wt_remaining) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       card_emu_wt_expired(ci->ch); // let the state know WT has expired</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (ci->wt_remaining <= ci->wt / 2 && !ci->wt_halfed) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    ci->wt_halfed = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                      card_emu_wt_halfed(ci->ch); // let the state know WT has half expired</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ci->wt_remaining > 0xffff) { // value exceeds the USART TO range</span><br><span style="color: hsl(120, 100%, 40%);">+                    usart->US_RTOR = 0xffff; // use the MAX</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      usart->US_RTOR = ci->wt_remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             usart->US_CR |= US_CR_STTTO; // clear timeout flag (and stop timeout until next character is received)</span><br><span style="color: hsl(120, 100%, 40%);">+             usart->US_CR |= US_CR_RETTO; // restart the counter (it wt is 0, the timeout is not started)</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> }</span><br><span> </span><br><span> /*! ISR called for USART0 */</span><br><span>@@ -249,6 +294,91 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+// call-back from card_emu.c to change UART baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_update_fd(uint8_t uart_chan, uint16_t f, uint8_t d)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle</span><br><span style="color: hsl(120, 100%, 40%);">+        if (NULL == usart) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!iso7816_3_valid_f(f)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: invalid F: %u\r\n", uart_chan, f);</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!iso7816_3_valid_d(d)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: invalid D: %u\r\n", uart_chan, d);</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t ratio = f / d;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ratio > 0 && ratio < 2048) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* make sure USART uses new F/D ratio */</span><br><span style="color: hsl(120, 100%, 40%);">+              usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX; // disable USART before changing baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+              usart->US_FIDI = (ratio & 0x7ff); // change baud rate (ratio)</span><br><span style="color: hsl(120, 100%, 40%);">+          usart->US_CR |= US_CR_RXEN | US_CR_STTTO; // re-enable USART (and stop timeout)</span><br><span style="color: hsl(120, 100%, 40%);">+            TRACE_INFO("%u: USART F/D set to %u/%u\r\n", uart_chan, f, d);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              TRACE_ERROR("%u: USART could not set F/D to %u/%u\r\n", uart_chan, f, d);</span><br><span style="color: hsl(120, 100%, 40%);">+           // TODO become unresponsive</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (uart_chan >= ARRAY_SIZE(cardem_inst)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     struct cardem_inst *ci = &cardem_inst[uart_chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle</span><br><span style="color: hsl(120, 100%, 40%);">+        if (NULL == usart) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ci->wt = wt; // save value</span><br><span style="color: hsl(120, 100%, 40%);">+ card_emu_uart_reset_wt(uart_chan); // reset and start timer</span><br><span style="color: hsl(120, 100%, 40%);">+   TRACE_INFO("%u: USART WT set to %lu ETU\r\n", uart_chan, wt);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_reset_wt(uint8_t uart_chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (uart_chan >= ARRAY_SIZE(cardem_inst)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     struct cardem_inst *ci = &cardem_inst[uart_chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle</span><br><span style="color: hsl(120, 100%, 40%);">+        if (NULL == usart) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ci->wt_remaining = ci->wt; // reload WT value</span><br><span style="color: hsl(120, 100%, 40%);">+   ci->wt_halfed = false; // reset half expired</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ci->wt_remaining > 0xffff) { // value exceeds the USART TO range</span><br><span style="color: hsl(120, 100%, 40%);">+            usart->US_RTOR = 0xffff; // use the MAX</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              usart->US_RTOR = ci->wt_remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     usart->US_CR |= US_CR_RETTO; // restart the counter (if wt is 0, the timeout is not started)</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_io_set(uint8_t uart_chan, bool set)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (uart_chan >= ARRAY_SIZE(cardem_inst)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     struct cardem_inst *ci = &cardem_inst[uart_chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (set) {</span><br><span style="color: hsl(120, 100%, 40%);">+            PIO_Set(&ci->pin_io);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              PIO_Clear(&ci->pin_io);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* call-back from card_emu.c to force a USART interrupt */</span><br><span> void card_emu_uart_interrupt(uint8_t uart_chan)</span><br><span> {</span><br><span>@@ -462,6 +592,10 @@</span><br><span>                                    SIMTRACE_CARDEM_USB_EP_USIM1_INT, cardem_inst[0].vcc_active,</span><br><span>                                         cardem_inst[0].rst_active, cardem_inst[0].vcc_active);</span><br><span>     sim_switch_use_physical(0, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef DETECT_VCC_BY_ADC</span><br><span style="color: hsl(120, 100%, 40%);">+     usim1_vcc_irqhandler(NULL); // check VCC/CLK state</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+    usim1_rst_irqhandler(NULL); // force RST state</span><br><span> </span><br><span> #ifdef CARDEMU_SECOND_UART</span><br><span>     INIT_LLIST_HEAD(&cardem_inst[1].usb_out_queue);</span><br><span>diff --git a/firmware/libcommon/source/tc_etu.c b/firmware/libcommon/source/tc_etu.c</span><br><span>index 04a7324..f5f8918 100644</span><br><span>--- a/firmware/libcommon/source/tc_etu.c</span><br><span>+++ b/firmware/libcommon/source/tc_etu.c</span><br><span>@@ -23,6 +23,9 @@</span><br><span> </span><br><span> #include "chip.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_halfed(void *handle);</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wt_expired(void *handle);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* pins for Channel 0 of TC-block 0, we only use TCLK + TIOB */</span><br><span> #define PIN_TCLK0  {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT }</span><br><span> #define PIN_TIOA0       {PIO_PA0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span>@@ -85,7 +88,7 @@</span><br><span>              te->nr_events++;</span><br><span>          if (te->nr_events == te->wait_events/2) {</span><br><span>                      /* Indicate that half the waiting tim has expired */</span><br><span style="color: hsl(0, 100%, 40%);">-                    tc_etu_wtime_half_expired(te->handle);</span><br><span style="color: hsl(120, 100%, 40%);">+                     card_emu_wt_halfed(te->handle);</span><br><span>           }</span><br><span>            if (te->nr_events >= te->wait_events) {</span><br><span>                     TcChannel *chan = te->chan;</span><br><span>@@ -96,7 +99,7 @@</span><br><span>                   chan->TC_CCR = TC_CCR_CLKEN;</span><br><span> </span><br><span>                  /* Indicate that the waiting tim has expired */</span><br><span style="color: hsl(0, 100%, 40%);">-                 tc_etu_wtime_expired(te->handle);</span><br><span style="color: hsl(120, 100%, 40%);">+                  card_emu_wt_expired(te->handle);</span><br><span>          }</span><br><span>    }</span><br><span> }</span><br><span>diff --git a/firmware/libosmocore/include/osmocom/core/utils.h b/firmware/libosmocore/include/osmocom/core/utils.h</span><br><span>index 63a73ab..8f0e385 100644</span><br><span>--- a/firmware/libosmocore/include/osmocom/core/utils.h</span><br><span>+++ b/firmware/libosmocore/include/osmocom/core/utils.h</span><br><span>@@ -36,7 +36,7 @@</span><br><span> int get_string_value(const struct value_string *vs, const char *str);</span><br><span> </span><br><span> char osmo_bcd2char(uint8_t bcd);</span><br><span style="color: hsl(0, 100%, 40%);">-/* only works for numbers in ascci */</span><br><span style="color: hsl(120, 100%, 40%);">+/* only works for numbers in ASCII */</span><br><span> uint8_t osmo_char2bcd(char c);</span><br><span> </span><br><span> int osmo_hexparse(const char *str, uint8_t *b, int max_len);</span><br><span>@@ -60,7 +60,7 @@</span><br><span>   rem -= ret;                                             \</span><br><span> } while (0)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Helper macro to terminate when an assertion failes</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Helper macro to terminate when an assertion fails</span><br><span>  *  \param[in] exp Predicate to verify</span><br><span>  *  This function will generate a backtrace and terminate the program if</span><br><span>  *  the predicate evaluates to false (0).</span><br><span>@@ -75,7 +75,7 @@</span><br><span> /*! duplicate a string using talloc and release its prior content (if any)</span><br><span>  * \param[in] ctx Talloc context to use for allocation</span><br><span>  * \param[out] dst pointer to string, will be updated with ptr to new string</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] newstr String that will be copieed to newly allocated string */</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] newstr String that will be copied to newly allocated string */</span><br><span> static inline void osmo_talloc_replace_string(void *ctx, char **dst, const char *newstr)</span><br><span> {</span><br><span>         if (*dst)</span><br><span>diff --git a/host/src/simtrace2-cardem-pcsc.c b/host/src/simtrace2-cardem-pcsc.c</span><br><span>index f11330c..d8fb531 100644</span><br><span>--- a/host/src/simtrace2-cardem-pcsc.c</span><br><span>+++ b/host/src/simtrace2-cardem-pcsc.c</span><br><span>@@ -93,9 +93,9 @@</span><br><span>   struct cardemu_usb_msg_status *status;</span><br><span>       status = (struct cardemu_usb_msg_status *) buf;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-            status->flags, status->fi, status->di, status->wi,</span><br><span style="color: hsl(0, 100%, 40%);">-          status->waiting_time);</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("=> STATUS: flags=0x%x, F=%u, D=%u, WI=%u WT=%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               status->flags, status->f, status->d, status->wi,</span><br><span style="color: hsl(120, 100%, 40%);">+          status->wt);</span><br><span> </span><br><span>  return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/simtrace2/+/23620">change 23620</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/simtrace2/+/23620"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: simtrace2 </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5 </div>
<div style="display:none"> Gerrit-Change-Number: 23620 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: tsaitgaist <kredon@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>