<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/simtrace2/+/23620">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">card_emu: Use USART timeout for waiting time<br><br>Instead of using the timer/counter peripheral to handle the waiting time<br>and corresponding timeout, the USART peripheral internal timeout<br>mechanism is used.<br><br>This is particularly important for the SIMtrace board since there<br>(contrary to other boards) the I/O signal is not wired to a TIO pin<br>of the timer/counter block, and hence Rx/Tx data cannot reset that<br>timer/counter.<br><br>As a result of this migration, cardem is now supported not only on<br>owhw + qmod, but also on the simtrace board.<br><br>The guts of this change have been lifted out of Change-Id<br>Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5 by Kevin Redon, which was<br>unfortunately touching various different topics at the same time and<br>hence was split up. Some improvements are the introduction of the<br>ENABLE_TX_TIMER_ONLY mode, which avoids the USART interrupt handler<br>getting hammered with TXRDY between release of RST and start of the ATR.<br><br>Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5<br>Related: OS#1704<br>---<br>M firmware/apps/cardem/Makefile<br>M firmware/apps/trace/Makefile<br>M firmware/apps/triple_play/Makefile<br>M firmware/libcommon/include/card_emu.h<br>M firmware/libcommon/source/card_emu.c<br>M firmware/libcommon/source/mode_cardemu.c<br>M firmware/test/card_emu_tests.c<br>7 files changed, 141 insertions(+), 53 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/firmware/apps/cardem/Makefile b/firmware/apps/cardem/Makefile</span><br><span>index 75c43e8..c0d903f 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_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 cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c</span><br><span>diff --git a/firmware/apps/trace/Makefile b/firmware/apps/trace/Makefile</span><br><span>index 75c43e8..c0d903f 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 += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c</span><br><span>diff --git a/firmware/apps/triple_play/Makefile b/firmware/apps/triple_play/Makefile</span><br><span>index df89448..be06c11 100644</span><br><span>--- a/firmware/apps/triple_play/Makefile</span><br><span>+++ b/firmware/apps/triple_play/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 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_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c</span><br><span>diff --git a/firmware/libcommon/include/card_emu.h b/firmware/libcommon/include/card_emu.h</span><br><span>index 8a73d5c..58e24cd 100644</span><br><span>--- a/firmware/libcommon/include/card_emu.h</span><br><span>+++ b/firmware/libcommon/include/card_emu.h</span><br><span>@@ -31,7 +31,6 @@</span><br><span> </span><br><span> /** initialise card slot</span><br><span>  *  @param[in] slot_num slot number (arbitrary number)</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] tc_chan timer counter channel (to measure the ETU)</span><br><span>  *  @param[in] uart_chan UART peripheral channel</span><br><span>  *  @param[in] in_ep USB IN end point number</span><br><span>  *  @param[in] irq_ep USB INTerrupt end point number</span><br><span>@@ -40,7 +39,7 @@</span><br><span>  *  @param[in] clocked initial CLK signat state (true = active)</span><br><span>  *  @return main card handle reference</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);</span><br><span style="color: hsl(120, 100%, 40%);">+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);</span><br><span> </span><br><span> /* process a single byte received from the reader */</span><br><span> void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte);</span><br><span>@@ -58,10 +57,17 @@</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(0, 100%, 40%);">-#define ENABLE_TX       0x01</span><br><span style="color: hsl(0, 100%, 40%);">-#define ENABLE_RX   0x02</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wtime_half_expired(void *ch);</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_wtime_expired(void *ch);</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%);">+#define ENABLE_TX                0x01</span><br><span style="color: hsl(120, 100%, 40%);">+#define ENABLE_RX         0x02</span><br><span style="color: hsl(120, 100%, 40%);">+#define ENABLE_TX_TIMER_ONLY      0x03</span><br><span> </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%);">+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt);</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_reset_wt(uint8_t uart_chan);</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/source/card_emu.c b/firmware/libcommon/source/card_emu.c</span><br><span>index 0ba6eb0..cefc957 100644</span><br><span>--- a/firmware/libcommon/source/card_emu.c</span><br><span>+++ b/firmware/libcommon/source/card_emu.c</span><br><span>@@ -27,7 +27,6 @@</span><br><span> #include "utils.h"</span><br><span> #include "trace.h"</span><br><span> #include "iso7816_fidi.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "tc_etu.h"</span><br><span> #include "card_emu.h"</span><br><span> #include "simtrace_prot.h"</span><br><span> #include "usb_buf.h"</span><br><span>@@ -177,7 +176,6 @@</span><br><span>      *  \note this depends on Fi, Di, and WI if T=0 is used */</span><br><span>   uint32_t waiting_time;  /* in etu */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        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>@@ -222,7 +220,7 @@</span><br><span> {</span><br><span>   struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   tc_etu_disable(ch->tc_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+       card_emu_uart_update_wt(ch->uart_chan, 0);</span><br><span> </span><br><span>    /* release any buffers we may still own */</span><br><span>   if (ch->uart_tx_msg) {</span><br><span>@@ -383,8 +381,6 @@</span><br><span>                         ch->F_index, ch->D_index, rc);</span><br><span>              /* make sure UART uses new F/D ratio */</span><br><span>              card_emu_uart_update_fidi(ch->uart_chan, rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                /* notify ETU timer about this */</span><br><span style="color: hsl(0, 100%, 40%);">-               tc_etu_set_etu(ch->tc_chan, rc);</span><br><span>  } else</span><br><span>               TRACE_INFO("%u: computed F/D ratio %d unsupported\r\n",</span><br><span>                       ch->num, rc);</span><br><span>@@ -408,6 +404,8 @@</span><br><span>    case ISO_S_WAIT_RST:</span><br><span>                 /* disable Rx and Tx of UART */</span><br><span>              card_emu_uart_enable(ch->uart_chan, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* disable timeout */</span><br><span style="color: hsl(120, 100%, 40%);">+         card_emu_uart_update_wt(ch->uart_chan, 0);</span><br><span>                break;</span><br><span>       case ISO_S_WAIT_ATR:</span><br><span>                 /* Reset to initial Fi / Di ratio */</span><br><span>@@ -416,13 +414,13 @@</span><br><span>                 ch->wi = ISO7816_3_DEFAULT_WI;</span><br><span>            ch->waiting_time = ISO7816_3_INIT_WTIME;</span><br><span>          emu_update_fidi(ch);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* enable TX to be able to use the timeout */</span><br><span style="color: hsl(120, 100%, 40%);">+         card_emu_uart_enable(ch->uart_chan, ENABLE_TX_TIMER_ONLY);</span><br><span>                /* the ATR should only be sent 400 to 40k clock cycles after the RESET.</span><br><span style="color: hsl(0, 100%, 40%);">-          * we use the tc_etu mechanism to wait this time.</span><br><span style="color: hsl(120, 100%, 40%);">+              * we use the UART timeout mechanism to wait this time.</span><br><span>               * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.</span><br><span>                 */</span><br><span style="color: hsl(0, 100%, 40%);">-             tc_etu_set_wtime(ch->tc_chan, 2);</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%);">+                card_emu_uart_update_wt(ch->uart_chan, 2);</span><br><span>                break;</span><br><span>       case ISO_S_IN_ATR:</span><br><span>           /* initialize to default WI, this will be overwritten if we</span><br><span>@@ -432,7 +430,7 @@</span><br><span>            /* update waiting time to initial waiting time */</span><br><span>            ch->waiting_time = 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%);">+                card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);</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>@@ -509,7 +507,6 @@</span><br><span>              }</span><br><span>            /* update waiting time (see ISO 7816-3 10.2) */</span><br><span>              ch->waiting_time = ch->wi * 960 * iso7816_3_fi_table[ch->F_index];</span><br><span style="color: hsl(0, 100%, 40%);">-             tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);</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>@@ -677,6 +674,7 @@</span><br><span>              emu_update_fidi(ch);</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>@@ -752,14 +750,28 @@</span><br><span> </span><br><span>        switch (new_ts) {</span><br><span>    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(120, 100%, 40%);">+          /* switch back to receiving mode */</span><br><span>          card_emu_uart_enable(ch->uart_chan, ENABLE_RX);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* disable waiting time since we don't expect any data */</span><br><span style="color: hsl(120, 100%, 40%);">+         card_emu_uart_update_wt(ch->uart_chan, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TPDU_S_WAIT_INS:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* start waiting for the rest of the header/body */</span><br><span style="color: hsl(120, 100%, 40%);">+           card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TPDU_S_WAIT_RX:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* switch to receive mode to receive the body */</span><br><span style="color: hsl(120, 100%, 40%);">+              card_emu_uart_enable(ch->uart_chan, ENABLE_RX);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* start waiting for the body */</span><br><span style="color: hsl(120, 100%, 40%);">+              card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);</span><br><span>              break;</span><br><span>       case TPDU_S_WAIT_PB:</span><br><span>                 /* we just completed the TPDU header from reader to card</span><br><span>              * and now need to disable the receiver, enable the</span><br><span>           * transmitter and transmit the procedure byte */</span><br><span>            card_emu_uart_enable(ch->uart_chan, ENABLE_TX);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* prepare to extend the waiting time once half of it is reached */</span><br><span style="color: hsl(120, 100%, 40%);">+           card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);</span><br><span>              break;</span><br><span>       default:</span><br><span>             break;</span><br><span>@@ -1103,8 +1115,6 @@</span><br><span>               if (active == 0 && ch->in_reset) {</span><br><span>                        TRACE_INFO("%u: RST released\r\n", ch->num);</span><br><span>                    if (ch->vcc_active && ch->clocked && ch->state == ISO_S_WAIT_RST) {</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>                               /* prepare to send the ATR */</span><br><span>                                card_set_state(ch, ISO_S_WAIT_ATR);</span><br><span>                  }</span><br><span>@@ -1163,7 +1173,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_wtime_half_expired(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>@@ -1173,7 +1183,10 @@</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(120, 100%, 40%);">+                 /* we are waiting for data from the user. Send a procedure byte to ask the</span><br><span style="color: hsl(120, 100%, 40%);">+                     * reader to wait more time */</span><br><span>                       card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                        card_emu_uart_reset_wt(ch->uart_chan);</span><br><span>                    break;</span><br><span>               default:</span><br><span>                     break;</span><br><span>@@ -1185,7 +1198,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_wtime_expired(void *handle)</span><br><span> {</span><br><span>   struct card_handle *ch = handle;</span><br><span>     switch (ch->state) {</span><br><span>@@ -1231,7 +1244,7 @@</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)</span><br><span style="color: hsl(120, 100%, 40%);">+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)</span><br><span> {</span><br><span>     struct card_handle *ch;</span><br><span> </span><br><span>@@ -1256,7 +1269,6 @@</span><br><span>  ch->Di_index = ch->D_index = 1;</span><br><span>        ch->wi = ISO7816_3_DEFAULT_WI;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ch->tc_chan = tc_chan;</span><br><span>    ch->uart_chan = uart_chan;</span><br><span>        ch->waiting_time = ISO7816_3_INIT_WTIME;</span><br><span> </span><br><span>@@ -1269,7 +1281,5 @@</span><br><span> </span><br><span>  card_handle_reset(ch);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      tc_etu_init(ch->tc_chan, ch);</span><br><span style="color: hsl(0, 100%, 40%);">-</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 4886983..8531eb5 100644</span><br><span>--- a/firmware/libcommon/source/mode_cardemu.c</span><br><span>+++ b/firmware/libcommon/source/mode_cardemu.c</span><br><span>@@ -55,6 +55,14 @@</span><br><span>    struct llist_head usb_out_queue;</span><br><span>     struct ringbuf rb;</span><br><span>   struct Usart_info usart_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              /*! receiver waiting time to trigger timeout (0 to deactivate it) */</span><br><span style="color: hsl(120, 100%, 40%);">+          uint32_t total;</span><br><span style="color: hsl(120, 100%, 40%);">+               /*! remaining waiting time (we may need multiple timer runs to reach total */</span><br><span style="color: hsl(120, 100%, 40%);">+         uint32_t remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+           /*! did we already notify about half the time having expired? */</span><br><span style="color: hsl(120, 100%, 40%);">+              bool half_time_notified;</span><br><span style="color: hsl(120, 100%, 40%);">+      } wt;</span><br><span>        int usb_pending_old;</span><br><span>         uint8_t ep_out;</span><br><span>      uint8_t ep_in;</span><br><span>@@ -140,12 +148,23 @@</span><br><span>       Usart *usart = get_usart_by_chan(uart_chan);</span><br><span>         switch (rxtx) {</span><br><span>      case ENABLE_TX:</span><br><span style="color: hsl(0, 100%, 40%);">-         USART_DisableIt(usart, ~US_IER_TXRDY);</span><br><span style="color: hsl(120, 100%, 40%);">+                USART_DisableIt(usart, ~(US_IER_TXRDY | US_IER_TIMEOUT));</span><br><span>            /* as irritating as it is, we actually want to keep the</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(0, 100%, 40%);">-           USART_EnableIt(usart, US_IER_TXRDY);</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%);">+         USART_SetTransmitterEnabled(usart, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ENABLE_TX_TIMER_ONLY:</span><br><span style="color: hsl(120, 100%, 40%);">+            /* enable the transmitter without generating TXRDY interrupts</span><br><span style="color: hsl(120, 100%, 40%);">+          * just so that the timer can run */</span><br><span style="color: hsl(120, 100%, 40%);">+          USART_DisableIt(usart, ~US_IER_TIMEOUT);</span><br><span style="color: hsl(120, 100%, 40%);">+              /* as irritating as it is, we actually want to keep the</span><br><span style="color: hsl(120, 100%, 40%);">+                * receiver enabled during transmit */</span><br><span style="color: hsl(120, 100%, 40%);">+                USART_SetReceiverEnabled(usart, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+           usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;</span><br><span style="color: hsl(120, 100%, 40%);">+         USART_EnableIt(usart, US_IER_TIMEOUT);</span><br><span>               USART_SetTransmitterEnabled(usart, 1);</span><br><span>               break;</span><br><span>       case ENABLE_RX:</span><br><span>@@ -225,11 +244,40 @@</span><br><span>      }</span><br><span> </span><br><span>        /* check if any error flags are set */</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))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|US_CSR_NACK|(1<<10))) {</span><br><span>            /* clear any error flags */</span><br><span>          usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;</span><br><span>                TRACE_ERROR("%u USART error on 0x%x status: 0x%lx\n", ci->num, byte, csr);</span><br><span>      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* check if the timeout has expired. We "abuse" the receive timer for tracking</span><br><span style="color: hsl(120, 100%, 40%);">+       * how many etu have expired since we last sent a byte.  See section</span><br><span style="color: hsl(120, 100%, 40%);">+   * 33.7.3.11 "Receiver Time-out" of the SAM3S8 Data Sheet */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (csr & US_CSR_TIMEOUT) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* RX has been inactive for some time */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* waiting time is over; will stop the timer */</span><br><span style="color: hsl(120, 100%, 40%);">+                       ci->wt.remaining = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* subtract the actual timeout since the new might not have been set and</span><br><span style="color: hsl(120, 100%, 40%);">+                       * reloaded yet */</span><br><span style="color: hsl(120, 100%, 40%);">+                    ci->wt.remaining -= (usart->US_RTOR & 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ci->wt.remaining == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* let the FSM know that WT has expired */</span><br><span style="color: hsl(120, 100%, 40%);">+                    card_emu_wtime_expired(ci->ch);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* let the FS know that half of the WT has expired */</span><br><span style="color: hsl(120, 100%, 40%);">+                 card_emu_wtime_half_expired(ci->ch);</span><br><span style="color: hsl(120, 100%, 40%);">+                       ci->wt.half_time_notified = true;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* if value exceeds the USART TO range, use the maximum for now */</span><br><span style="color: hsl(120, 100%, 40%);">+            usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* 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_STTTO;</span><br><span style="color: hsl(120, 100%, 40%);">+               /* restart the counter (it wt is 0, the timeout is not started) */</span><br><span style="color: hsl(120, 100%, 40%);">+            usart->US_CR |= US_CR_RETTO;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span> }</span><br><span> </span><br><span> /*! ISR called for USART0 */</span><br><span>@@ -258,6 +306,42 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Update WT on USART peripheral.  Will automatically re-start timer with new value.</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_wtime_expired is called (0 to disable) */</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%);">+   OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));</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);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ci->wt.total != wt) {</span><br><span style="color: hsl(120, 100%, 40%);">+          TRACE_DEBUG("%u: USART WT changed from %lu to %lu ETU\r\n", uart_chan,</span><br><span style="color: hsl(120, 100%, 40%);">+                          ci->wt.total, 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%);">+   ci->wt.total = wt;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* reset and start the timer */</span><br><span style="color: hsl(120, 100%, 40%);">+       card_emu_uart_reset_wt(uart_chan);</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%);">+/*! Reset and re-start 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%);">+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%);">+     OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));</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);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* FIXME: guard against race with interrupt handler */</span><br><span style="color: hsl(120, 100%, 40%);">+        ci->wt.remaining = ci->wt.total;</span><br><span style="color: hsl(120, 100%, 40%);">+        ci->wt.half_time_notified = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* if value exceeds the USART TO range, use the maximum for now */</span><br><span style="color: hsl(120, 100%, 40%);">+    usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* restart the counter (if wt is 0, the timeout is not started) */</span><br><span style="color: hsl(120, 100%, 40%);">+    usart->US_CR |= US_CR_RETTO;</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>@@ -450,7 +534,7 @@</span><br><span>     do {} while (!adc_triggered); /* wait for first ADC reading */</span><br><span> #endif /* DETECT_VCC_BY_ADC */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,</span><br><span style="color: hsl(120, 100%, 40%);">+       cardem_inst[0].ch = card_emu_init(0, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,</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>@@ -473,7 +557,7 @@</span><br><span>         do {} while (!adc_triggered); /* wait for first ADC reading */</span><br><span> #endif /* DETECT_VCC_BY_ADC */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,</span><br><span style="color: hsl(120, 100%, 40%);">+       cardem_inst[1].ch = card_emu_init(1, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,</span><br><span>                                           SIMTRACE_CARDEM_USB_EP_USIM2_INT, cardem_inst[1].vcc_active,</span><br><span>                                         cardem_inst[1].rst_active, cardem_inst[1].vcc_active);</span><br><span>     sim_switch_use_physical(1, 1);</span><br><span>diff --git a/firmware/test/card_emu_tests.c b/firmware/test/card_emu_tests.c</span><br><span>index 2a1d682..69159a8 100644</span><br><span>--- a/firmware/test/card_emu_tests.c</span><br><span>+++ b/firmware/test/card_emu_tests.c</span><br><span>@@ -50,6 +50,9 @@</span><br><span>      case ENABLE_TX:</span><br><span>              rts = "TX";</span><br><span>                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ENABLE_TX_TIMER_ONLY:</span><br><span style="color: hsl(120, 100%, 40%);">+            rts = "TX-TIMER-ONLY";</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       case ENABLE_RX:</span><br><span>              rts = "RX";</span><br><span>                break;</span><br><span>@@ -66,29 +69,14 @@</span><br><span>         printf("uart_interrupt(uart_chan=%u)\n", uart_chan);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)</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> {</span><br><span style="color: hsl(0, 100%, 40%);">-        printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("%s(uart_chan=%u, wtime=%u)\n", __func__, uart_chan, wt);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)</span><br><span style="color: hsl(120, 100%, 40%);">+void card_emu_uart_reset_wt(uint8_t uart_chan)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_init(uint8_t chan_nr, void *handle)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        printf("tc_etu_init(tc_chan=%u)\n", chan_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_enable(uint8_t chan_nr)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void tc_etu_disable(uint8_t chan_nr)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("%s(uart_chan=%u\n", __func__, uart_chan);</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -136,7 +124,7 @@</span><br><span>       /* release from reset and verify th ATR */</span><br><span>   card_emu_io_statechg(ch, CARD_IO_RST, 0);</span><br><span>    /* simulate waiting time before ATR expired */</span><br><span style="color: hsl(0, 100%, 40%);">-  tc_etu_wtime_expired(ch);</span><br><span style="color: hsl(120, 100%, 40%);">+     card_emu_wtime_expired(ch);</span><br><span>  verify_atr(ch);</span><br><span> }</span><br><span> </span><br><span>@@ -408,7 +396,7 @@</span><br><span>       struct card_handle *ch;</span><br><span>      unsigned int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT, false, true, false);</span><br><span style="color: hsl(120, 100%, 40%);">+   ch = card_emu_init(0, 42, PHONE_DATAIN, PHONE_INT, false, true, false);</span><br><span>      assert(ch);</span><br><span> </span><br><span>      usb_buf_init();</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: 5 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Hoernchen <ewild@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: tsaitgaist <kredon@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>