<p>Hoernchen has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16235">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">make it work, async uart (mode 0x1/0x7 does not matter), requires delay<br><br>Change-Id: Ia9d3b099181c24feabdb6a5fddb8db6c44efb72d<br>---<br>M ccid_common/ccid_slot_fsm.c<br>M ccid_common/iso7816_fsm.c<br>M sysmoOCTSIM/config/hpl_sercom_config.h<br>M sysmoOCTSIM/cuart_driver_asf4_usart_async.c<br>M sysmoOCTSIM/driver_init.c<br>M sysmoOCTSIM/gcc/Makefile<br>M sysmoOCTSIM/libosmo_emb.c<br>M sysmoOCTSIM/main.c<br>M sysmoOCTSIM/talloc.c<br>M sysmoOCTSIM/usb/class/ccid/device/ccid_df.c<br>M sysmoOCTSIM/usb_descriptors.c<br>A sysmoOCTSIM/usb_descriptors.h<br>12 files changed, 1,055 insertions(+), 762 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/35/16235/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c</span><br><span>index 621bef7..870cf35 100644</span><br><span>--- a/ccid_common/ccid_slot_fsm.c</span><br><span>+++ b/ccid_common/ccid_slot_fsm.c</span><br><span>@@ -80,9 +80,10 @@</span><br><span>       osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_POWER_UP_IND, NULL);</span><br><span>     cs->icc_powered = true;</span><br><span>   card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK, true);</span><br><span style="color: hsl(0, 100%, 40%);">-    usleep(10000);</span><br><span style="color: hsl(0, 100%, 40%);">-  card_uart_ctrl(ss->cuart, CUART_CTL_RST, false);</span><br><span style="color: hsl(120, 100%, 40%);">+   delay_us(10000);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_RESET_REL_IND, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+     card_uart_ctrl(ss->cuart, CUART_CTL_RST, false);</span><br><span> </span><br><span>      msgb_free(msg);</span><br><span>      /* continues in iso_fsm_clot_user_cb once ATR is received */</span><br><span>@@ -151,8 +152,10 @@</span><br><span> </span><br><span>      if (enable) {</span><br><span>                card_uart_ctrl(ss->cuart, CUART_CTL_POWER, true);</span><br><span style="color: hsl(120, 100%, 40%);">+          cs->icc_powered = true;</span><br><span>   } else {</span><br><span>             card_uart_ctrl(ss->cuart, CUART_CTL_POWER, false);</span><br><span style="color: hsl(120, 100%, 40%);">+         cs->icc_powered = false;</span><br><span>  }</span><br><span> }</span><br><span> </span><br><span>@@ -185,31 +188,35 @@</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+extern void *g_tall_ctx;</span><br><span> static int iso_fsm_slot_init(struct ccid_slot *cs)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- void *ctx = NULL; /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+ void *ctx = g_tall_ctx; /* FIXME */</span><br><span>  struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);</span><br><span>        struct card_uart *cuart = talloc_zero(ctx, struct card_uart);</span><br><span style="color: hsl(0, 100%, 40%);">-   char id_buf[16];</span><br><span style="color: hsl(0, 100%, 40%);">-        char *devname = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char id_buf[16] = "SIM0";</span><br><span style="color: hsl(120, 100%, 40%);">+   char devname[] = "foobar";</span><br><span>         int rc;</span><br><span> </span><br><span>  LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);</span><br><span> </span><br><span>      /* HACK: make this in some way configurable so it works both in the firmware</span><br><span>          * and on the host (functionfs) */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (cs->slot_nr == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              cs->icc_present = true;</span><br><span style="color: hsl(0, 100%, 40%);">-              devname = "/dev/ttyUSB5";</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(120, 100%, 40%);">+//   if (cs->slot_nr == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          cs->icc_present = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//          devname = "/dev/ttyUSB5";</span><br><span style="color: hsl(120, 100%, 40%);">+// }</span><br><span style="color: hsl(120, 100%, 40%);">+     devname[0] = cs->slot_nr +0x30;</span><br><span style="color: hsl(120, 100%, 40%);">+    devname[1] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       //sprintf(devname, "%d", cs->slot_nr);</span><br><span> </span><br><span>      if (!cuart)</span><br><span>          return -ENOMEM;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     snprintf(id_buf, sizeof(id_buf), "SIM%d", cs->slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+  //snprintf(id_buf, sizeof(id_buf), "SIM%d", cs->slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+        id_buf[3] = cs->slot_nr +0x30;</span><br><span>    if (devname) {</span><br><span style="color: hsl(0, 100%, 40%);">-          rc = card_uart_open(cuart, "tty", devname);</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = card_uart_open(cuart, "asf4", devname);</span><br><span>               if (rc < 0) {</span><br><span>                     LOGPCS(cs, LOGL_ERROR, "Cannot open UART %s: %d\n", devname, rc);</span><br><span>                  talloc_free(cuart);</span><br><span>diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c</span><br><span>index 21378e0..beda7ab 100644</span><br><span>--- a/ccid_common/iso7816_fsm.c</span><br><span>+++ b/ccid_common/iso7816_fsm.c</span><br><span>@@ -633,6 +633,10 @@</span><br><span>                                  osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TCK,</span><br><span>                                                                  guard_time_ms, T_GUARD);</span><br><span>                                  break;</span><br><span style="color: hsl(120, 100%, 40%);">+                                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      /* no TCK present, ATR complete; notify parent */</span><br><span style="color: hsl(120, 100%, 40%);">+                                     osmo_fsm_inst_state_chg(fi, ATR_S_DONE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                                        osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_DONE_IND, atp->atr);</span><br><span>                             }</span><br><span>                    } else {</span><br><span>                             break;</span><br><span>diff --git a/sysmoOCTSIM/config/hpl_sercom_config.h b/sysmoOCTSIM/config/hpl_sercom_config.h</span><br><span>index beac040..4526665 100644</span><br><span>--- a/sysmoOCTSIM/config/hpl_sercom_config.h</span><br><span>+++ b/sysmoOCTSIM/config/hpl_sercom_config.h</span><br><span>@@ -52,7 +52,7 @@</span><br><span> // <i> Number of stop bits in USART frame</span><br><span> // <id> usart_stop_bit</span><br><span> #ifndef CONF_SERCOM_0_USART_SBMODE</span><br><span style="color: hsl(0, 100%, 40%);">-#define CONF_SERCOM_0_USART_SBMODE 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONF_SERCOM_0_USART_SBMODE 1</span><br><span> #endif</span><br><span> </span><br><span> // <o> Baud rate <1-3000000></span><br><span>@@ -70,7 +70,7 @@</span><br><span> // <i> Define ISO7816 protocol type as 0.</span><br><span> // <id> usart_iso7816_type</span><br><span> #ifndef CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T</span><br><span style="color: hsl(0, 100%, 40%);">-#define CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T 0x1</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T 0x0</span><br><span> #endif</span><br><span> </span><br><span> // <o> ISO7816 Inhibit Not Acknowledge</span><br><span>diff --git a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c</span><br><span>index 3be0d65..f9856f3 100644</span><br><span>--- a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c</span><br><span>+++ b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c</span><br><span>@@ -47,6 +47,16 @@</span><br><span>  card_uart_notification(cuart, CUART_E_TX_COMPLETE, io_descr->tx_buffer);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_usart_async.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <hpl_usart_sync.h></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%);">+static void _SIM_error_cb(const struct usart_async_descriptor *const descr){</span><br><span style="color: hsl(120, 100%, 40%);">+ volatile uint32_t status = hri_sercomusart_read_STATUS_reg(descr->device.hw);</span><br><span style="color: hsl(120, 100%, 40%);">+      volatile uint32_t data = hri_sercomusart_read_DATA_reg(descr->device.hw);</span><br><span style="color: hsl(120, 100%, 40%);">+  volatile uint32_t errrs = hri_sercomusart_read_RXERRCNT_reg(descr->device.hw);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(0 == 1)</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* the below ugli-ness is required as the usart_async_descriptor doesn't have</span><br><span>  * some kind of 'private' member that could provide the call-back anty kind of</span><br><span>@@ -124,6 +134,139 @@</span><br><span>    SIM4_tx_cb, SIM5_tx_cb, SIM6_tx_cb, SIM7_tx_cb,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <math.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "atmel_start.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "atmel_start_pins.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "config/hpl_gclk_config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "iso7816_3.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** possible clock sources for the SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+ *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t sercom_glck_sources[] = {GCLK_PCHCTRL_GEN_GCLK2_Val, GCLK_PCHCTRL_GEN_GCLK4_Val, GCLK_PCHCTRL_GEN_GCLK6_Val};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /** possible clock frequencies in MHz for the SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+  *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+static const double sercom_glck_freqs[] = {100E6 / CONF_GCLK_GEN_2_DIV, 100E6 / CONF_GCLK_GEN_4_DIV, 120E6 / CONF_GCLK_GEN_6_DIV};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** the GCLK ID for the SERCOM SIM peripherals</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @note: used as index for PCHCTRL</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t SIM_peripheral_GCLK_ID[] = {SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE};</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%);">+/** change baud rate of card slot</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] baudrate baud rate in bps to set</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool slot_set_baudrate(uint8_t slotnr, uint32_t baudrate)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // calculate the error corresponding to the clock sources</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t bauds[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(120, 100%, 40%);">+        double errors[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(120, 100%, 40%);">+ for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              double freq = sercom_glck_freqs[i]; // remember possible SERCOM frequency</span><br><span style="color: hsl(120, 100%, 40%);">+             uint32_t min = freq/16. *  (1. - 65535. / 65536.); // calculate the minimum baud rate for this frequency</span><br><span style="color: hsl(120, 100%, 40%);">+              uint32_t max = freq/16. *  (1. - 1. / 65536.); // calculate the maximum baud rate for this frequency</span><br><span style="color: hsl(120, 100%, 40%);">+          if (baudrate < min || baudrate > max) { // baud rate it out of supported range</span><br><span style="color: hsl(120, 100%, 40%);">+                  errors[i] = NAN;</span><br><span style="color: hsl(120, 100%, 40%);">+              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      uint16_t baud = round(65536. * (1. - 16. * (baudrate/freq)));</span><br><span style="color: hsl(120, 100%, 40%);">+                 bauds[i] = baud;</span><br><span style="color: hsl(120, 100%, 40%);">+                      double actual = freq/16. *  (1. - baud / 65536.);</span><br><span style="color: hsl(120, 100%, 40%);">+                     errors[i] = fabs(1.0 - (actual / baudrate));</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%);">+   // find the smallest error</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t best = ARRAY_SIZE(sercom_glck_freqs);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (isnan(errors[i])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (best >= ARRAY_SIZE(sercom_glck_freqs)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       best = i;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (errors[i] < errors[best]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     best = i;</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%);">+     if (best >= ARRAY_SIZE(sercom_glck_freqs)) { // found no clock supporting this baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</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%);">+   // set clock and baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+    struct usart_async_descriptor* slot = SIM_peripheral_descriptors[slotnr]; // get slot</span><br><span style="color: hsl(120, 100%, 40%);">+ if (NULL == slot) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("(%u) switching SERCOM clock to GCLK%u (freq = %lu kHz) and baud rate to %lu bps (baud = %u)\r\n", slotnr, (best + 1) * 2, (uint32_t)(round(sercom_glck_freqs[best] / 1000)), baudrate, bauds[best]);</span><br><span style="color: hsl(120, 100%, 40%);">+        while (!usart_async_is_tx_empty(slot)); // wait for transmission to complete (WARNING no timeout)</span><br><span style="color: hsl(120, 100%, 40%);">+     usart_async_disable(slot); // disable SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+       hri_gclk_clear_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos)); // disable clock for this peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+    while (hri_gclk_get_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos))); // wait until clock is really disabled</span><br><span style="color: hsl(120, 100%, 40%);">+    // it does not seem we need to completely disable the peripheral using hri_mclk_clear_APBDMASK_SERCOMn_bit</span><br><span style="color: hsl(120, 100%, 40%);">+    hri_gclk_write_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], sercom_glck_sources[best] | (1 << GCLK_PCHCTRL_CHEN_Pos)); // set peripheral core clock and re-enable it</span><br><span style="color: hsl(120, 100%, 40%);">+       usart_async_set_baud_rate(slot, bauds[best]); // set the new baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+        usart_async_enable(slot); // re-enable SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return true;</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%);">+/** change ISO baud rate of card slot</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] clkdiv can clock divider</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] f clock rate conversion integer F</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] d baud rate adjustment factor D</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool slot_set_isorate(uint8_t slotnr, enum ncn8025_sim_clkdiv clkdiv, uint16_t f, uint8_t d)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (clkdiv != SIM_CLKDIV_1 && clkdiv != SIM_CLKDIV_2 && clkdiv != SIM_CLKDIV_4 && clkdiv != SIM_CLKDIV_8) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</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%);">+          return false;</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%);">+          return false;</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%);">+   // set clockdiv</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+     ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (settings.clkdiv != clkdiv) {</span><br><span style="color: hsl(120, 100%, 40%);">+              settings.clkdiv = clkdiv;</span><br><span style="color: hsl(120, 100%, 40%);">+             ncn8025_set(slotnr, &settings);</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%);">+   // calculate desired frequency</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t freq = 20000000UL; // maximum frequency</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (clkdiv) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIM_CLKDIV_1:</span><br><span style="color: hsl(120, 100%, 40%);">+            freq /= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SIM_CLKDIV_2:</span><br><span style="color: hsl(120, 100%, 40%);">+            freq /= 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SIM_CLKDIV_4:</span><br><span style="color: hsl(120, 100%, 40%);">+            freq /= 4;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SIM_CLKDIV_8:</span><br><span style="color: hsl(120, 100%, 40%);">+            freq /= 8;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</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%);">+   // set baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t baudrate = (freq * d) / f; // calculate actual baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+     return slot_set_baudrate(slotnr, baudrate); // set baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /***********************************************************************</span><br><span>  * Interface with card_uart (cuart) core</span><br><span>  ***********************************************************************/</span><br><span>@@ -146,10 +289,15 @@</span><br><span>       cuart->u.asf4.usa_pd = usa_pd;</span><br><span>    cuart->u.asf4.slot_nr = slot_nr;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    usart_async_register_callback(usa_pd, USART_ASYNC_RXC_CB, SIM_rx_cb[slot_nr]);</span><br><span>       usart_async_register_callback(usa_pd, USART_ASYNC_TXC_CB, SIM_tx_cb[slot_nr]);</span><br><span style="color: hsl(120, 100%, 40%);">+        usart_async_register_callback(usa_pd, USART_ASYNC_ERROR_CB, _SIM_error_cb);</span><br><span>  usart_async_enable(usa_pd);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span style="color: hsl(120, 100%, 40%);">+      slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -197,19 +345,31 @@</span><br><span> </span><br><span>    switch (ctl) {</span><br><span>       case CUART_CTL_RX:</span><br><span style="color: hsl(0, 100%, 40%);">-              if (arg)</span><br><span style="color: hsl(120, 100%, 40%);">+              if (arg){</span><br><span>                    sercom->USART.CTRLB.bit.RXEN = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-            else</span><br><span style="color: hsl(120, 100%, 40%);">+                  sercom->USART.CTRLB.bit.TXEN = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      delay_us(100);</span><br><span>                       sercom->USART.CTRLB.bit.RXEN = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                  sercom->USART.CTRLB.bit.TXEN = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span>            break;</span><br><span>       case CUART_CTL_RST:</span><br><span>          ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span>                settings.rstin = arg ? true : false;</span><br><span>                 ncn8025_set(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+         usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd);</span><br><span>                break;</span><br><span>       case CUART_CTL_POWER:</span><br><span>                ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span>                settings.cmdvcc = arg ? true : false;</span><br><span style="color: hsl(120, 100%, 40%);">+         settings.led = arg ? true : false;</span><br><span style="color: hsl(120, 100%, 40%);">+            settings.vsel = SIM_VOLT_5V0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span style="color: hsl(120, 100%, 40%);">+              if(arg)</span><br><span style="color: hsl(120, 100%, 40%);">+                       slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              ncn8025_set(cuart->u.asf4.slot_nr, &settings);</span><br><span>                break;</span><br><span>       case CUART_CTL_WTIME:</span><br><span>diff --git a/sysmoOCTSIM/driver_init.c b/sysmoOCTSIM/driver_init.c</span><br><span>index 620ed6c..c373dc2 100644</span><br><span>--- a/sysmoOCTSIM/driver_init.c</span><br><span>+++ b/sysmoOCTSIM/driver_init.c</span><br><span>@@ -12,25 +12,25 @@</span><br><span> #include <hal_init.h></span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM0_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM0_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM1_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM1_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM2_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM2_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM3_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM3_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM4_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM4_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM5_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM5_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SIM6_BUFFER_SIZE 16</span><br><span style="color: hsl(120, 100%, 40%);">+#define SIM6_BUFFER_SIZE 512</span><br><span> </span><br><span> /*! The buffer size for USART */</span><br><span> #define UART_DEBUG_BUFFER_SIZE 256</span><br><span>diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile</span><br><span>index 4840fea..9873159 100644</span><br><span>--- a/sysmoOCTSIM/gcc/Makefile</span><br><span>+++ b/sysmoOCTSIM/gcc/Makefile</span><br><span>@@ -8,7 +8,7 @@</span><br><span> CROSS_COMPILE= arm-none-eabi-</span><br><span> </span><br><span> CFLAGS_CPU=-D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</span><br><span style="color: hsl(0, 100%, 40%);">-CFLAGS=-x c -mthumb -DDEBUG -Os -ffunction-sections -fdata-sections -mlong-calls \</span><br><span style="color: hsl(120, 100%, 40%);">+CFLAGS=-x c -mthumb -DDEBUG -O0 -ffunction-sections -fdata-sections -mlong-calls \</span><br><span>        -g3 -Wall -c -std=gnu99 $(CFLAGS_CPU)</span><br><span> </span><br><span> CC = $(CROSS_COMPILE)gcc</span><br><span>diff --git a/sysmoOCTSIM/libosmo_emb.c b/sysmoOCTSIM/libosmo_emb.c</span><br><span>index 1914568..5209e20 100644</span><br><span>--- a/sysmoOCTSIM/libosmo_emb.c</span><br><span>+++ b/sysmoOCTSIM/libosmo_emb.c</span><br><span>@@ -157,8 +157,8 @@</span><br><span>        /* logging */</span><br><span>        log_init(&log_info, g_tall_ctx);</span><br><span>         stderr_target = log_target_create_stderr_raw();</span><br><span style="color: hsl(0, 100%, 40%);">- log_add_target(stderr_target);</span><br><span style="color: hsl(0, 100%, 40%);">-  log_set_all_filter(stderr_target, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ //log_add_target(stderr_target);</span><br><span style="color: hsl(120, 100%, 40%);">+      //log_set_all_filter(stderr_target, 1);</span><br><span> </span><br><span>  /* timer */</span><br><span>  SysTick_Config(SystemCoreClock / 1000);</span><br><span>diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c</span><br><span>index 15e2004..e27e3dd 100644</span><br><span>--- a/sysmoOCTSIM/main.c</span><br><span>+++ b/sysmoOCTSIM/main.c</span><br><span>@@ -40,46 +40,51 @@</span><br><span> </span><br><span> #include "command.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-// TODO put declaration in more global file</span><br><span style="color: hsl(0, 100%, 40%);">-// TODO for now SIM7 is not present because used for debug</span><br><span style="color: hsl(0, 100%, 40%);">-static struct usart_async_descriptor* SIM_peripheral_descriptors[] = {&SIM0, &SIM1, &SIM2, &SIM3, &SIM4, &SIM5, &SIM6, NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ccid_device.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "usb_descriptors.h"</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct ccid_slot_ops iso_fsm_slot_ops;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ccid_instance g_ci;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/** number of bytes transmitted on the SIM peripheral */</span><br><span style="color: hsl(0, 100%, 40%);">-static volatile bool SIM_tx_count[8];</span><br><span style="color: hsl(120, 100%, 40%);">+//// TODO put declaration in more global file</span><br><span style="color: hsl(120, 100%, 40%);">+//// TODO for now SIM7 is not present because used for debug</span><br><span style="color: hsl(120, 100%, 40%);">+//static struct usart_async_descriptor* SIM_peripheral_descriptors[] = {&SIM0, &SIM1, &SIM2, &SIM3, &SIM4, &SIM5, &SIM6, NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+///** number of bytes transmitted on the SIM peripheral */</span><br><span style="color: hsl(120, 100%, 40%);">+//static volatile bool SIM_tx_count[8];</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//static void SIM_rx_cb(const struct usart_async_descriptor *const io_descr)</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%);">+///** called when the transmission is complete</span><br><span style="color: hsl(120, 100%, 40%);">+// *  e.g. this is when the byte has been sent and there is no data to transmit anymore</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static void SIM_tx_cb(const struct usart_async_descriptor *const io_descr)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//     // find slotnr for corresponding USART</span><br><span style="color: hsl(120, 100%, 40%);">+//      uint8_t slotnr;</span><br><span style="color: hsl(120, 100%, 40%);">+//     for (slotnr = 0; slotnr < ARRAY_SIZE(SIM_peripheral_descriptors) && SIM_peripheral_descriptors[slotnr] != io_descr; slotnr++);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//       // set flag</span><br><span style="color: hsl(120, 100%, 40%);">+// if (slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)) {</span><br><span style="color: hsl(120, 100%, 40%);">+//           SIM_tx_count[slotnr] = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//        }</span><br><span style="color: hsl(120, 100%, 40%);">+//}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void SIM_rx_cb(const struct usart_async_descriptor *const io_descr)</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/** called when the transmission is complete</span><br><span style="color: hsl(0, 100%, 40%);">- *  e.g. this is when the byte has been sent and there is no data to transmit anymore</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static void SIM_tx_cb(const struct usart_async_descriptor *const io_descr)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   // find slotnr for corresponding USART</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t slotnr;</span><br><span style="color: hsl(0, 100%, 40%);">- for (slotnr = 0; slotnr < ARRAY_SIZE(SIM_peripheral_descriptors) && SIM_peripheral_descriptors[slotnr] != io_descr; slotnr++);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       // set flag</span><br><span style="color: hsl(0, 100%, 40%);">-     if (slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               SIM_tx_count[slotnr] = true;</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/** possible clock sources for the SERCOM peripheral</span><br><span style="color: hsl(0, 100%, 40%);">- *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const uint8_t sercom_glck_sources[] = {GCLK_PCHCTRL_GEN_GCLK2_Val, GCLK_PCHCTRL_GEN_GCLK4_Val, GCLK_PCHCTRL_GEN_GCLK6_Val};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/** possible clock frequencies in MHz for the SERCOM peripheral</span><br><span style="color: hsl(0, 100%, 40%);">- *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const double sercom_glck_freqs[] = {100E6 / CONF_GCLK_GEN_2_DIV, 100E6 / CONF_GCLK_GEN_4_DIV, 120E6 / CONF_GCLK_GEN_6_DIV};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/** the GCLK ID for the SERCOM SIM peripherals</span><br><span style="color: hsl(0, 100%, 40%);">- *  @note: used as index for PCHCTRL</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const uint8_t SIM_peripheral_GCLK_ID[] = {SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE};</span><br><span style="color: hsl(120, 100%, 40%);">+///** possible clock sources for the SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+// *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static const uint8_t sercom_glck_sources[] = {GCLK_PCHCTRL_GEN_GCLK2_Val, GCLK_PCHCTRL_GEN_GCLK4_Val, GCLK_PCHCTRL_GEN_GCLK6_Val};</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+///** possible clock frequencies in MHz for the SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+// *  warning: the definition must match the GCLK configuration</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static const double sercom_glck_freqs[] = {100E6 / CONF_GCLK_GEN_2_DIV, 100E6 / CONF_GCLK_GEN_4_DIV, 120E6 / CONF_GCLK_GEN_6_DIV};</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+///** the GCLK ID for the SERCOM SIM peripherals</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @note: used as index for PCHCTRL</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static const uint8_t SIM_peripheral_GCLK_ID[] = {SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE};</span><br><span> </span><br><span> static void ccid_app_init(void);</span><br><span> </span><br><span>@@ -101,15 +106,15 @@</span><br><span>      * (there are 8 inputs + traces to drive!) */</span><br><span>        hri_port_set_PINCFG_DRVSTR_bit(PORT, 0, 11);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        // enable SIM interfaces</span><br><span style="color: hsl(0, 100%, 40%);">-        for (uint8_t i = 0; i < ARRAY_SIZE(SIM_peripheral_descriptors); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               if (NULL == SIM_peripheral_descriptors[i]) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-               usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_RXC_CB, SIM_rx_cb); // required for RX to work, even if the callback does nothing</span><br><span style="color: hsl(0, 100%, 40%);">-              usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_TXC_CB, SIM_tx_cb); // to count the number of bytes transmitted since we are using it asynchronously</span><br><span style="color: hsl(0, 100%, 40%);">-           usart_async_enable(SIM_peripheral_descriptors[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(120, 100%, 40%);">+//   // enable SIM interfaces</span><br><span style="color: hsl(120, 100%, 40%);">+//    for (uint8_t i = 0; i < ARRAY_SIZE(SIM_peripheral_descriptors); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//           if (NULL == SIM_peripheral_descriptors[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+//           }</span><br><span style="color: hsl(120, 100%, 40%);">+//           usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_RXC_CB, SIM_rx_cb); // required for RX to work, even if the callback does nothing</span><br><span style="color: hsl(120, 100%, 40%);">+//          usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_TXC_CB, SIM_tx_cb); // to count the number of bytes transmitted since we are using it asynchronously</span><br><span style="color: hsl(120, 100%, 40%);">+//               usart_async_enable(SIM_peripheral_descriptors[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+//  }</span><br><span> </span><br><span>        ccid_app_init();</span><br><span> }</span><br><span>@@ -199,7 +204,9 @@</span><br><span>  struct msgb *msg;</span><br><span>    int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     OSMO_ASSERT(!ep_q->in_progress);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ep_q->in_progress)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  msg = msgb_dequeue_irqsafe(&ep_q->list);</span><br><span>      if (!msg)</span><br><span>            return 0;</span><br><span>@@ -248,6 +255,7 @@</span><br><span>      msg = msgb_dequeue_irqsafe(&g_ccid_s.free_q);</span><br><span>    if (!msg)</span><br><span>            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_reset(msg);</span><br><span>     ep_q->in_progress = msg;</span><br><span> </span><br><span>      rc = ccid_df_read_out(msgb_data(msg), msgb_tailroom(msg));</span><br><span>@@ -270,6 +278,7 @@</span><br><span>     msgb_put(msg, transferred);</span><br><span>  /* append to list of pending-to-be-handed messages */</span><br><span>        llist_add_tail_at(&msg->list, &g_ccid_s.out_ep.list);</span><br><span style="color: hsl(120, 100%, 40%);">+      g_ccid_s.out_ep.in_progress = NULL;</span><br><span> </span><br><span>      /* submit another [free] msgb to receive the next transfer */</span><br><span>        submit_next_out();</span><br><span>@@ -341,8 +350,11 @@</span><br><span>    struct msgb *msg;</span><br><span>    unsigned int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 0; i < 8; i++)</span><br><span style="color: hsl(0, 100%, 40%);">-              new_mask |= ncn8025_interrupt_level(i) << i;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 8; i++){</span><br><span style="color: hsl(120, 100%, 40%);">+           bool level = ncn8025_interrupt_level(i);</span><br><span style="color: hsl(120, 100%, 40%);">+              new_mask |= level << i;</span><br><span style="color: hsl(120, 100%, 40%);">+         g_ci.slot[i].icc_present = level;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span>        /* notify the user/host about any changes */</span><br><span>         if (g_ccid_s.card_insert_mask != new_mask) {</span><br><span>@@ -375,614 +387,614 @@</span><br><span>       }</span><br><span>    return slotnr;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+///** change baud rate of card slot</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] baudrate baud rate in bps to set</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static bool slot_set_baudrate(uint8_t slotnr, uint32_t baudrate)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//   ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     // calculate the error corresponding to the clock sources</span><br><span style="color: hsl(120, 100%, 40%);">+//   uint16_t bauds[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(120, 100%, 40%);">+//      double errors[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(120, 100%, 40%);">+//       for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//            double freq = sercom_glck_freqs[i]; // remember possible SERCOM frequency</span><br><span style="color: hsl(120, 100%, 40%);">+//           uint32_t min = freq / (2 * (255 + 1)); // calculate the minimum baud rate for this frequency</span><br><span style="color: hsl(120, 100%, 40%);">+//                uint32_t max = freq / (2 * (0 + 1)); // calculate the maximum baud rate for this frequency</span><br><span style="color: hsl(120, 100%, 40%);">+//          if (baudrate < min || baudrate > max) { // baud rate it out of supported range</span><br><span style="color: hsl(120, 100%, 40%);">+//                        errors[i] = NAN;</span><br><span style="color: hsl(120, 100%, 40%);">+//            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+//                    uint16_t baud = round(freq / (2 * baudrate) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//                   bauds[i] = baud;</span><br><span style="color: hsl(120, 100%, 40%);">+//                    double actual = freq / (2 * (baud + 1));</span><br><span style="color: hsl(120, 100%, 40%);">+//                    errors[i] = fabs(1.0 - (actual / baudrate));</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%);">+//       // find the smallest error</span><br><span style="color: hsl(120, 100%, 40%);">+//  uint8_t best = ARRAY_SIZE(sercom_glck_freqs);</span><br><span style="color: hsl(120, 100%, 40%);">+//       for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//            if (isnan(errors[i])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+//           }</span><br><span style="color: hsl(120, 100%, 40%);">+//           if (best >= ARRAY_SIZE(sercom_glck_freqs)) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                     best = i;</span><br><span style="color: hsl(120, 100%, 40%);">+//           } else if (errors[i] < errors[best]) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                   best = i;</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%);">+//   if (best >= ARRAY_SIZE(sercom_glck_freqs)) { // found no clock supporting this baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+//         return false;</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%);">+//       // set clock and baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+//  struct usart_async_descriptor* slot = SIM_peripheral_descriptors[slotnr]; // get slot</span><br><span style="color: hsl(120, 100%, 40%);">+//       if (NULL == slot) {</span><br><span style="color: hsl(120, 100%, 40%);">+//         return false;</span><br><span style="color: hsl(120, 100%, 40%);">+//       }</span><br><span style="color: hsl(120, 100%, 40%);">+//   printf("(%u) switching SERCOM clock to GCLK%u (freq = %lu kHz) and baud rate to %lu bps (baud = %u)\r\n", slotnr, (best + 1) * 2, (uint32_t)(round(sercom_glck_freqs[best] / 1000)), baudrate, bauds[best]);</span><br><span style="color: hsl(120, 100%, 40%);">+//      while (!usart_async_is_tx_empty(slot)); // wait for transmission to complete (WARNING no timeout)</span><br><span style="color: hsl(120, 100%, 40%);">+//   usart_async_disable(slot); // disable SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+//     hri_gclk_clear_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos)); // disable clock for this peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+//  while (hri_gclk_get_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos))); // wait until clock is really disabled</span><br><span style="color: hsl(120, 100%, 40%);">+//  // it does not seem we need to completely disable the peripheral using hri_mclk_clear_APBDMASK_SERCOMn_bit</span><br><span style="color: hsl(120, 100%, 40%);">+//  hri_gclk_write_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], sercom_glck_sources[best] | (1 << GCLK_PCHCTRL_CHEN_Pos)); // set peripheral core clock and re-enable it</span><br><span style="color: hsl(120, 100%, 40%);">+//     usart_async_set_baud_rate(slot, bauds[best]); // set the new baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+//      usart_async_enable(slot); // re-enable SERCOM peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//        return true;</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%);">+///** change ISO baud rate of card slot</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] clkdiv can clock divider</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] f clock rate conversion integer F</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] d baud rate adjustment factor D</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static bool slot_set_isorate(uint8_t slotnr, enum ncn8025_sim_clkdiv clkdiv, uint16_t f, uint8_t d)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//        // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+//     ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+// if (clkdiv != SIM_CLKDIV_1 && clkdiv != SIM_CLKDIV_2 && clkdiv != SIM_CLKDIV_4 && clkdiv != SIM_CLKDIV_8) {</span><br><span style="color: hsl(120, 100%, 40%);">+//         return false;</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%);">+//                return false;</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%);">+//                return false;</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%);">+//       // set clockdiv</span><br><span style="color: hsl(120, 100%, 40%);">+//     struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (settings.clkdiv != clkdiv) {</span><br><span style="color: hsl(120, 100%, 40%);">+//            settings.clkdiv = clkdiv;</span><br><span style="color: hsl(120, 100%, 40%);">+//           ncn8025_set(slotnr, &settings);</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%);">+//       // calculate desired frequency</span><br><span style="color: hsl(120, 100%, 40%);">+//      uint32_t freq = 20000000UL; // maximum frequency</span><br><span style="color: hsl(120, 100%, 40%);">+//    switch (clkdiv) {</span><br><span style="color: hsl(120, 100%, 40%);">+//   case SIM_CLKDIV_1:</span><br><span style="color: hsl(120, 100%, 40%);">+//          freq /= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+//          break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case SIM_CLKDIV_2:</span><br><span style="color: hsl(120, 100%, 40%);">+//          freq /= 2;</span><br><span style="color: hsl(120, 100%, 40%);">+//          break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case SIM_CLKDIV_4:</span><br><span style="color: hsl(120, 100%, 40%);">+//          freq /= 4;</span><br><span style="color: hsl(120, 100%, 40%);">+//          break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case SIM_CLKDIV_8:</span><br><span style="color: hsl(120, 100%, 40%);">+//          freq /= 8;</span><br><span style="color: hsl(120, 100%, 40%);">+//          break;</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%);">+//       // set baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+//    uint32_t baudrate = (freq * d) / f; // calculate actual baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+//   return slot_set_baudrate(slotnr, baudrate); // set baud rate</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%);">+///** write data to card</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] data data to be transmitted</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] length length of data to be transmitted</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @return error code</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static int slot_card_write(uint8_t slotnr, const uint8_t* data, uint16_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//        // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+//     ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+// if (0 == length || NULL == data) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          return ERR_INVALID_ARG;</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%);">+//       struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(120, 100%, 40%);">+//    ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0; // disable receive (to avoid the echo back)</span><br><span style="color: hsl(120, 100%, 40%);">+//     SIM_tx_count[slotnr] = false; // reset TX complete</span><br><span style="color: hsl(120, 100%, 40%);">+//  for (uint16_t i = 0; i < length; i++) { // transmit data</span><br><span style="color: hsl(120, 100%, 40%);">+//         while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING blocking)</span><br><span style="color: hsl(120, 100%, 40%);">+//                if (1 != io_write(&sim->io, &data[i], 1)) { // put but in transmit buffer</span><br><span style="color: hsl(120, 100%, 40%);">+//                        return ERR_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%);">+//   while (!SIM_tx_count[slotnr]); // wait until transmission is complete (WARNING blocking)</span><br><span style="color: hsl(120, 100%, 40%);">+//    ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // enable receive again</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     return ERR_NONE;</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%);">+///** read data from card</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[out] data buffer for read data to be stored</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] length length of data to be read</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] wt Waiting Time in ETU</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @return error code</span><br><span style="color: hsl(120, 100%, 40%);">+// *  TODO fix WT/ETU duration</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static int slot_card_read(uint8_t slotnr, uint8_t* data, uint16_t length, uint32_t wt)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//       // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+//     ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+// if (0 == length || NULL == data) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          return ERR_INVALID_ARG;</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%);">+//       struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//        ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // ensure RX is enabled</span><br><span style="color: hsl(120, 100%, 40%);">+// uint32_t timeout = wt; // reset waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+//        for (uint16_t i = 0; i < length; i++) { // read all data</span><br><span style="color: hsl(120, 100%, 40%);">+//         while (timeout && !usart_async_is_rx_not_empty(sim)) { // verify if data is present</span><br><span style="color: hsl(120, 100%, 40%);">+//                 delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(120, 100%, 40%);">+//                     timeout--;</span><br><span style="color: hsl(120, 100%, 40%);">+//          }</span><br><span style="color: hsl(120, 100%, 40%);">+//           if (0 == timeout) { // timeout reached</span><br><span style="color: hsl(120, 100%, 40%);">+//                      return ERR_TIMEOUT;</span><br><span style="color: hsl(120, 100%, 40%);">+//         }</span><br><span style="color: hsl(120, 100%, 40%);">+//           timeout = wt; // reset waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+//         if (1 != io_read(&sim->io, &data[i], 1)) { // read one byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                      return ERR_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 style="color: hsl(120, 100%, 40%);">+//       return ERR_NONE;</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%);">+///** transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] slotnr slot number on which to transfer the TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] header TPDU header to send</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[io] data TPDU data to transfer</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] data_length length of TPDU data to transfer</span><br><span style="color: hsl(120, 100%, 40%);">+// *  @param[in] write if the data should be written (true) or read (false)</span><br><span style="color: hsl(120, 100%, 40%);">+// * TODO fix WT</span><br><span style="color: hsl(120, 100%, 40%);">+// * TODO the data length can be deduce from the header</span><br><span style="color: hsl(120, 100%, 40%);">+// */</span><br><span style="color: hsl(120, 100%, 40%);">+//static int slot_tpdu_xfer(uint8_t slotnr, const uint8_t* header, uint8_t* data, uint16_t data_length, bool write)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//  // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+//     ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+// if (NULL == header || (data_length > 0 && NULL == data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               return ERR_INVALID_ARG;</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%);">+//       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+//     struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; // get USART peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+//    usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//      // send command header</span><br><span style="color: hsl(120, 100%, 40%);">+//      printf("(%d) TPDU: ", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//    for (uint8_t i = 0; i < 5; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                printf("%02x ", header[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+//       }</span><br><span style="color: hsl(120, 100%, 40%);">+//   rc = slot_card_write(slotnr, header, 5); // transmit header</span><br><span style="color: hsl(120, 100%, 40%);">+// if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("error in command header transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//          return rc;</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%);">+//       // read procedure byte, and handle data</span><br><span style="color: hsl(120, 100%, 40%);">+//     uint8_t pb = 0x60; // wait more procedure byte</span><br><span style="color: hsl(120, 100%, 40%);">+//      uint16_t data_i = 0; // progress in the data transfer</span><br><span style="color: hsl(120, 100%, 40%);">+//       while (0x60 == pb) { // wait for SW</span><br><span style="color: hsl(120, 100%, 40%);">+//         rc = slot_card_read(slotnr, &pb, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+//              if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                       printf("error while receiving PB/SW1 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//                      return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+//          }</span><br><span style="color: hsl(120, 100%, 40%);">+//           printf("%02x ", pb);</span><br><span style="color: hsl(120, 100%, 40%);">+//              if (0x60 == pb) { // NULL byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                      // just wait more time</span><br><span style="color: hsl(120, 100%, 40%);">+//              } else if ((0x60 == (pb & 0xf0)) || (0x90 == (pb & 0xf0))) { // SW1 byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                    // left the rest of the code handle it</span><br><span style="color: hsl(120, 100%, 40%);">+//              } else if (header[1] == pb) { // ACK byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                   // transfer rest of the data</span><br><span style="color: hsl(120, 100%, 40%);">+//                        if (data_i >= data_length) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                             printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//                             return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+//                    }</span><br><span style="color: hsl(120, 100%, 40%);">+//                   if (write) { // transmit remaining command data</span><br><span style="color: hsl(120, 100%, 40%);">+//                             rc = slot_card_write(slotnr, &data[data_i], data_length - data_i); // transmit command data</span><br><span style="color: hsl(120, 100%, 40%);">+//                             if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                                       printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//                                    return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+//                          }</span><br><span style="color: hsl(120, 100%, 40%);">+//                   } else { // receive remaining command data</span><br><span style="color: hsl(120, 100%, 40%);">+//                          rc = slot_card_read(slotnr, &data[data_i], data_length - data_i, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+//                         if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                                       printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//                                     return rc;</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%);">+//                   for (uint16_t i = data_i; i < data_length; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                                printf("%02x ", data[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+//                 }</span><br><span style="color: hsl(120, 100%, 40%);">+//                   data_i = data_length; // remember we transferred the data</span><br><span style="color: hsl(120, 100%, 40%);">+//                   pb = 0x60; // wait for SW1</span><br><span style="color: hsl(120, 100%, 40%);">+//          } else if (header[1] == (pb ^ 0xff)) { // ACK byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                  // transfer only one byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                   if (data_i >= data_length) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                             printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//                             return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+//                    }</span><br><span style="color: hsl(120, 100%, 40%);">+//                   if (write) { // transmit command data byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                          rc = slot_card_write(slotnr, &data[data_i], 1); // transmit command data</span><br><span style="color: hsl(120, 100%, 40%);">+//                                if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                                       printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//                                    return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+//                          }</span><br><span style="color: hsl(120, 100%, 40%);">+//                   } else { // receive command data byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                               rc = slot_card_read(slotnr, &data[data_i], 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+//                            if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                                       printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//                                     return rc;</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%);">+//                   printf("%02x ", data[data_i]);</span><br><span style="color: hsl(120, 100%, 40%);">+//                    data_i += 1; // remember we transferred one data byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                       pb = 0x60; // wait for SW1</span><br><span style="color: hsl(120, 100%, 40%);">+//          } else { // invalid byte</span><br><span style="color: hsl(120, 100%, 40%);">+//                    return ERR_INVALID_DATA;</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%);">+//       // read SW2</span><br><span style="color: hsl(120, 100%, 40%);">+// uint8_t sw2;</span><br><span style="color: hsl(120, 100%, 40%);">+//        rc = slot_card_read(slotnr, &sw2, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("error in receiving SW2 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//            return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+//  }</span><br><span style="color: hsl(120, 100%, 40%);">+//   printf("%02x", sw2);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//  printf("\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//   return ERR_NONE;</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%);">+//DEFUN(sim_status, cmd_sim_status, "sim-status", "Get state of specified NCN8025")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//     struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//        if (slotnr < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+//          return;</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// printf("SIM%d: ", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//        ncn8025_dump(&settings);</span><br><span style="color: hsl(120, 100%, 40%);">+//        printf("\r\n");</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%);">+//DEFUN(sim_power, cmd_sim_power, "sim-power", "Enable/disable SIM card power")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//        struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//        int enable;</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (slotnr < 0)</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 (argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          printf("You have to specify 0=disable or 1=enable\r\n");</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%);">+//   enable = atoi(argv[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (enable)</span><br><span style="color: hsl(120, 100%, 40%);">+//         settings.cmdvcc = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//     else</span><br><span style="color: hsl(120, 100%, 40%);">+//                settings.cmdvcc = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//    ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_reset, cmd_sim_reset, "sim-reset", "Enable/disable SIM reset")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//   struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//        int enable;</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (slotnr < 0)</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 (argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          printf("You have to specify 0=disable or 1=enable\r\n");</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%);">+//   enable = atoi(argv[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (enable)</span><br><span style="color: hsl(120, 100%, 40%);">+//         settings.rstin = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//      else</span><br><span style="color: hsl(120, 100%, 40%);">+//                settings.rstin = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_clkdiv, cmd_sim_clkdiv, "sim-clkdiv", "Set SIM clock divider (1,2,4,8)")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+// struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//        int clkdiv;</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (slotnr < 0)</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 (argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          printf("You have to specify a valid divider (1,2,4,8)\r\n");</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%);">+//   clkdiv = atoi(argv[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (clkdiv != 1 && clkdiv != 2 && clkdiv != 4 && clkdiv != 8) {</span><br><span style="color: hsl(120, 100%, 40%);">+//             printf("You have to specify a valid divider (1,2,4,8)\r\n");</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%);">+//   ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// switch (clkdiv) {</span><br><span style="color: hsl(120, 100%, 40%);">+//   case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+//             settings.clkdiv = SIM_CLKDIV_1;</span><br><span style="color: hsl(120, 100%, 40%);">+//             break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+//             settings.clkdiv = SIM_CLKDIV_2;</span><br><span style="color: hsl(120, 100%, 40%);">+//             break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+//             settings.clkdiv = SIM_CLKDIV_4;</span><br><span style="color: hsl(120, 100%, 40%);">+//             break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+//             settings.clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(120, 100%, 40%);">+//             break;</span><br><span style="color: hsl(120, 100%, 40%);">+//      }</span><br><span style="color: hsl(120, 100%, 40%);">+//   ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_voltage, cmd_sim_voltage, "sim-voltage", "Set SIM voltage (5/3/1.8)")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//    struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//    if (slotnr < 0)</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 (argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          printf("You have to specify a valid voltage (5/3/1.8)\r\n");</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%);">+//   ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (!strcmp(argv[2], "5"))</span><br><span style="color: hsl(120, 100%, 40%);">+//                settings.vsel = SIM_VOLT_5V0;</span><br><span style="color: hsl(120, 100%, 40%);">+//       else if (!strcmp(argv[2], "3"))</span><br><span style="color: hsl(120, 100%, 40%);">+//           settings.vsel = SIM_VOLT_3V0;</span><br><span style="color: hsl(120, 100%, 40%);">+//       else if (!strcmp(argv[2], "1.8"))</span><br><span style="color: hsl(120, 100%, 40%);">+//         settings.vsel = SIM_VOLT_1V8;</span><br><span style="color: hsl(120, 100%, 40%);">+//       else {</span><br><span style="color: hsl(120, 100%, 40%);">+//              printf("You have to specify a valid voltage (5/3/1.8)\r\n");</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%);">+//   ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_led, cmd_sim_led, "sim-led", "Set SIM LED (1=on, 0=off)")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//        struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//    if (slotnr < 0)</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 (argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+//          printf("You have to specify 0=disable or 1=enable\r\n");</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%);">+//   ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (atoi(argv[2]))</span><br><span style="color: hsl(120, 100%, 40%);">+//          settings.led = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//        else</span><br><span style="color: hsl(120, 100%, 40%);">+//                settings.led = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//       ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_atr, cmd_sim_atr, "sim-atr", "Read ATR from SIM card")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//   struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//    if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {</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%);">+//       // check if card is present (and read current settings)</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (!settings.simpres) {</span><br><span style="color: hsl(120, 100%, 40%);">+//            printf("(%d) error: no card present\r\n", slotnr);</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%);">+//       // switch card off (assert reset and disable power)</span><br><span style="color: hsl(120, 100%, 40%);">+// // note: ISO/IEC 7816-3:2006 section 6.4 provides the deactivation sequence, but not the minimum corresponding times</span><br><span style="color: hsl(120, 100%, 40%);">+//        settings.rstin = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//      settings.cmdvcc = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//    settings.led = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//        ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     // TODO wait some time for card to be completely deactivated</span><br><span style="color: hsl(120, 100%, 40%);">+//        usart_async_flush_rx_buffer(SIM_peripheral_descriptors[slotnr]); // flush RX buffer to start from scratch</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%);">+//   // set clock to lowest frequency (20 MHz / 8 = 2.5 MHz)</span><br><span style="color: hsl(120, 100%, 40%);">+//     // note: according to ISO/IEC 7816-3:2006 section 5.2.3 the minimum value is 1 MHz, and maximum is 5 MHz during activation</span><br><span style="color: hsl(120, 100%, 40%);">+//  settings.clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(120, 100%, 40%);">+//     // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span style="color: hsl(120, 100%, 40%);">+//    slot_set_isorate(slotnr, settings.clkdiv, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);</span><br><span style="color: hsl(120, 100%, 40%);">+//      // set card voltage to 3.0 V (the most supported)</span><br><span style="color: hsl(120, 100%, 40%);">+//   // note: according to ISO/IEC 7816-3:2006 no voltage should damage the card, and you should cycle from low to high</span><br><span style="color: hsl(120, 100%, 40%);">+//  settings.vsel = SIM_VOLT_3V0;</span><br><span style="color: hsl(120, 100%, 40%);">+//       // provide power (the NCN8025 should perform the activation according to spec)</span><br><span style="color: hsl(120, 100%, 40%);">+//      // note: activation sequence is documented in ISO/IEC 7816-3:2006 section 6.2</span><br><span style="color: hsl(120, 100%, 40%);">+//       settings.cmdvcc = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     // wait for Tb=400 cycles before re-asserting reset</span><br><span style="color: hsl(120, 100%, 40%);">+// delay_us(400 * 10000 / 2500); // 400 cycles * 1000 for us, 2.5 MHz / 1000 for us</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//        // de-assert reset to switch card back on</span><br><span style="color: hsl(120, 100%, 40%);">+//   settings.rstin = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//     ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//     // wait for Tc=40000 cycles for transmission to start</span><br><span style="color: hsl(120, 100%, 40%);">+//       uint32_t cycles = 40000;</span><br><span style="color: hsl(120, 100%, 40%);">+//    while (cycles && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                delay_us(10);</span><br><span style="color: hsl(120, 100%, 40%);">+//               cycles -= 25; // 10 us = 25 cycles at 2.5 MHz</span><br><span style="color: hsl(120, 100%, 40%);">+//       }</span><br><span style="color: hsl(120, 100%, 40%);">+//   if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//             delay_us(12 * 372 / 1 / 2); // wait more than one byte (approximate freq down to 2 MHz)</span><br><span style="color: hsl(120, 100%, 40%);">+//     }</span><br><span style="color: hsl(120, 100%, 40%);">+//   // verify if one byte has been received</span><br><span style="color: hsl(120, 100%, 40%);">+//     if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//             printf("(%d) error: card not responsive\r\n", slotnr);</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%);">+//       // read ATR (just do it until there is no traffic anymore)</span><br><span style="color: hsl(120, 100%, 40%);">+//  // TODO the ATR should be parsed to read the right number of bytes, instead we just wait until to end of WT</span><br><span style="color: hsl(120, 100%, 40%);">+// printf("(%d) ATR: ", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//     uint8_t atr_byte;</span><br><span style="color: hsl(120, 100%, 40%);">+//   while (usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//           if (1 == io_read(&SIM_peripheral_descriptors[slotnr]->io, &atr_byte, 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                       printf("%02x ", atr_byte);</span><br><span style="color: hsl(120, 100%, 40%);">+//                }</span><br><span style="color: hsl(120, 100%, 40%);">+//           uint16_t wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU</span><br><span style="color: hsl(120, 100%, 40%);">+//          while (wt && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                    delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(120, 100%, 40%);">+//                     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%);">+//   printf("\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//       /* disable LED */</span><br><span style="color: hsl(120, 100%, 40%);">+//   settings.led = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//       ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(sim_iccid, cmd_sim_iccid, "sim-iccid", "Read ICCID from SIM card")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//   struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+//   int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//    if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {</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%);">+//       // read current settings and check if card is present and powered</span><br><span style="color: hsl(120, 100%, 40%);">+//   ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+// if (!settings.simpres) {</span><br><span style="color: hsl(120, 100%, 40%);">+//            printf("(%d) error: no card present\r\n", slotnr);</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 (!settings.cmdvcc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//             printf("(%d) error: card not powered\r\n", slotnr);</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 (settings.rstin) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("(%d) error: card under reset\r\n", slotnr);</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%);">+//       // enable LED</span><br><span style="color: hsl(120, 100%, 40%);">+//       if (!settings.led) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                settings.led = true;</span><br><span style="color: hsl(120, 100%, 40%);">+//                ncn8025_set(slotnr, &settings);</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%);">+//       // select MF</span><br><span style="color: hsl(120, 100%, 40%);">+//        printf("(%d) SELECT MF\r\n", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//     const uint8_t select_header[] = {0xa0, 0xa4, 0x00, 0x00, 0x02}; // see TS 102.221 sec. 11.1.1</span><br><span style="color: hsl(120, 100%, 40%);">+//       const uint8_t select_data_mf[] = {0x3f, 0x00}; // see TS 102.221 sec. 13.1</span><br><span style="color: hsl(120, 100%, 40%);">+//  int rc = slot_tpdu_xfer(slotnr, select_header, (uint8_t*)select_data_mf, ARRAY_SIZE(select_data_mf), true); // transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+//        if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("error while SELECT MF (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//     }</span><br><span style="color: hsl(120, 100%, 40%);">+//   // ignore response data</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+// // select EF_ICCID</span><br><span style="color: hsl(120, 100%, 40%);">+//  printf("(%d) SELECT EF_ICCID\r\n", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//       const uint8_t select_data_ef_iccid[] = {0x2f, 0xe2}; // see TS 102.221 sec. 13.2</span><br><span style="color: hsl(120, 100%, 40%);">+//    rc = slot_tpdu_xfer(slotnr, select_header, (uint8_t*)select_data_ef_iccid, ARRAY_SIZE(select_data_ef_iccid), true); // transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+//        if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("error while SELECT EF_ICCID (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//       }</span><br><span style="color: hsl(120, 100%, 40%);">+//   // ignore response data</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+// // read EF_ICCID</span><br><span style="color: hsl(120, 100%, 40%);">+//    printf("(%d) READ EF_ICCID\r\n", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+// uint8_t iccid[10];</span><br><span style="color: hsl(120, 100%, 40%);">+//  uint8_t read_binary[] = {0xa0, 0xb0, 0x00, 0x00, ARRAY_SIZE(iccid)}; // see TS 102.221 sec. 11.1.3</span><br><span style="color: hsl(120, 100%, 40%);">+//  rc = slot_tpdu_xfer(slotnr, read_binary, iccid, ARRAY_SIZE(iccid), false); // transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+// if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+//               printf("error while READ ICCID (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+//    }</span><br><span style="color: hsl(120, 100%, 40%);">+//   // ignore response data</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+// printf("(%d) ICCID: ", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+//   for (uint8_t i = 0; i < ARRAY_SIZE(iccid); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                uint8_t nibble = iccid[i] & 0xf;</span><br><span style="color: hsl(120, 100%, 40%);">+//                if (0xf == nibble) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+//              }</span><br><span style="color: hsl(120, 100%, 40%);">+//           printf("%x", nibble);</span><br><span style="color: hsl(120, 100%, 40%);">+//             nibble = iccid[i] >> 4;</span><br><span style="color: hsl(120, 100%, 40%);">+//               if (0xf == nibble) {</span><br><span style="color: hsl(120, 100%, 40%);">+//                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+//              }</span><br><span style="color: hsl(120, 100%, 40%);">+//           printf("%x", nibble);</span><br><span style="color: hsl(120, 100%, 40%);">+//     }</span><br><span style="color: hsl(120, 100%, 40%);">+//   printf("\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//       // disable LED</span><br><span style="color: hsl(120, 100%, 40%);">+//      settings.led = false;</span><br><span style="color: hsl(120, 100%, 40%);">+//       ncn8025_set(slotnr, &settings);</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%);">+//DEFUN(get_time, cmd_get_time, "get-time", "Read Time from RTC")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//    struct calendar_date_time dt;</span><br><span style="color: hsl(120, 100%, 40%);">+//       calendar_get_date_time(&CALENDAR_0, &dt);</span><br><span style="color: hsl(120, 100%, 40%);">+//   printf("%04u-%02u-%02u %02u:%02u:%02u\r\n", dt.date.year, dt.date.month, dt.date.day,</span><br><span style="color: hsl(120, 100%, 40%);">+//             dt.time.hour, dt.time.min, dt.time.sec);</span><br><span style="color: hsl(120, 100%, 40%);">+//}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/** change baud rate of card slot</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] baudrate baud rate in bps to set</span><br><span style="color: hsl(0, 100%, 40%);">- *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static bool slot_set_baudrate(uint8_t slotnr, uint32_t baudrate)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     // calculate the error corresponding to the clock sources</span><br><span style="color: hsl(0, 100%, 40%);">-       uint16_t bauds[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(0, 100%, 40%);">-  double errors[ARRAY_SIZE(sercom_glck_freqs)];</span><br><span style="color: hsl(0, 100%, 40%);">-   for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                double freq = sercom_glck_freqs[i]; // remember possible SERCOM frequency</span><br><span style="color: hsl(0, 100%, 40%);">-               uint32_t min = freq / (2 * (255 + 1)); // calculate the minimum baud rate for this frequency</span><br><span style="color: hsl(0, 100%, 40%);">-            uint32_t max = freq / (2 * (0 + 1)); // calculate the maximum baud rate for this frequency</span><br><span style="color: hsl(0, 100%, 40%);">-              if (baudrate < min || baudrate > max) { // baud rate it out of supported range</span><br><span style="color: hsl(0, 100%, 40%);">-                    errors[i] = NAN;</span><br><span style="color: hsl(0, 100%, 40%);">-                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        uint16_t baud = round(freq / (2 * baudrate) - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-                       bauds[i] = baud;</span><br><span style="color: hsl(0, 100%, 40%);">-                        double actual = freq / (2 * (baud + 1));</span><br><span style="color: hsl(0, 100%, 40%);">-                        errors[i] = fabs(1.0 - (actual / baudrate));</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       // find the smallest error</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t best = ARRAY_SIZE(sercom_glck_freqs);</span><br><span style="color: hsl(0, 100%, 40%);">-   for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (isnan(errors[i])) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (best >= ARRAY_SIZE(sercom_glck_freqs)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 best = i;</span><br><span style="color: hsl(0, 100%, 40%);">-               } else if (errors[i] < errors[best]) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       best = i;</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%);">-       if (best >= ARRAY_SIZE(sercom_glck_freqs)) { // found no clock supporting this baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-             return false;</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%);">-       // set clock and baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-      struct usart_async_descriptor* slot = SIM_peripheral_descriptors[slotnr]; // get slot</span><br><span style="color: hsl(0, 100%, 40%);">-   if (NULL == slot) {</span><br><span style="color: hsl(0, 100%, 40%);">-             return false;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       printf("(%u) switching SERCOM clock to GCLK%u (freq = %lu kHz) and baud rate to %lu bps (baud = %u)\r\n", slotnr, (best + 1) * 2, (uint32_t)(round(sercom_glck_freqs[best] / 1000)), baudrate, bauds[best]);</span><br><span style="color: hsl(0, 100%, 40%);">-  while (!usart_async_is_tx_empty(slot)); // wait for transmission to complete (WARNING no timeout)</span><br><span style="color: hsl(0, 100%, 40%);">-       usart_async_disable(slot); // disable SERCOM peripheral</span><br><span style="color: hsl(0, 100%, 40%);">- hri_gclk_clear_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos)); // disable clock for this peripheral</span><br><span style="color: hsl(0, 100%, 40%);">-      while (hri_gclk_get_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos))); // wait until clock is really disabled</span><br><span style="color: hsl(0, 100%, 40%);">-      // it does not seem we need to completely disable the peripheral using hri_mclk_clear_APBDMASK_SERCOMn_bit</span><br><span style="color: hsl(0, 100%, 40%);">-      hri_gclk_write_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], sercom_glck_sources[best] | (1 << GCLK_PCHCTRL_CHEN_Pos)); // set peripheral core clock and re-enable it</span><br><span style="color: hsl(0, 100%, 40%);">- usart_async_set_baud_rate(slot, bauds[best]); // set the new baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-  usart_async_enable(slot); // re-enable SERCOM peripheral</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        return true;</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%);">-/** change ISO baud rate of card slot</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] slotnr slot number for which the baud rate should be set</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] clkdiv can clock divider</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] f clock rate conversion integer F</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] d baud rate adjustment factor D</span><br><span style="color: hsl(0, 100%, 40%);">- *  @return if the baud rate has been set, else a parameter is out of range</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static bool slot_set_isorate(uint8_t slotnr, enum ncn8025_sim_clkdiv clkdiv, uint16_t f, uint8_t d)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        // input checks</span><br><span style="color: hsl(0, 100%, 40%);">- ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(0, 100%, 40%);">-     if (clkdiv != SIM_CLKDIV_1 && clkdiv != SIM_CLKDIV_2 && clkdiv != SIM_CLKDIV_4 && clkdiv != SIM_CLKDIV_8) {</span><br><span style="color: hsl(0, 100%, 40%);">-             return false;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!iso7816_3_valid_f(f)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!iso7816_3_valid_d(d)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</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%);">-       // set clockdiv</span><br><span style="color: hsl(0, 100%, 40%);">- struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (settings.clkdiv != clkdiv) {</span><br><span style="color: hsl(0, 100%, 40%);">-                settings.clkdiv = clkdiv;</span><br><span style="color: hsl(0, 100%, 40%);">-               ncn8025_set(slotnr, &settings);</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%);">-       // calculate desired frequency</span><br><span style="color: hsl(0, 100%, 40%);">-  uint32_t freq = 20000000UL; // maximum frequency</span><br><span style="color: hsl(0, 100%, 40%);">-        switch (clkdiv) {</span><br><span style="color: hsl(0, 100%, 40%);">-       case SIM_CLKDIV_1:</span><br><span style="color: hsl(0, 100%, 40%);">-              freq /= 1;</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SIM_CLKDIV_2:</span><br><span style="color: hsl(0, 100%, 40%);">-              freq /= 2;</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SIM_CLKDIV_4:</span><br><span style="color: hsl(0, 100%, 40%);">-              freq /= 4;</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SIM_CLKDIV_8:</span><br><span style="color: hsl(0, 100%, 40%);">-              freq /= 8;</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</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%);">-       // set baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-        uint32_t baudrate = (freq * d) / f; // calculate actual baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-       return slot_set_baudrate(slotnr, baudrate); // set baud rate</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%);">-/** write data to card</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] data data to be transmitted</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] length length of data to be transmitted</span><br><span style="color: hsl(0, 100%, 40%);">- *  @return error code</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int slot_card_write(uint8_t slotnr, const uint8_t* data, uint16_t length)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    // input checks</span><br><span style="color: hsl(0, 100%, 40%);">- ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(0, 100%, 40%);">-     if (0 == length || NULL == data) {</span><br><span style="color: hsl(0, 100%, 40%);">-              return ERR_INVALID_ARG;</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%);">-       struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(0, 100%, 40%);">-        ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0; // disable receive (to avoid the echo back)</span><br><span style="color: hsl(0, 100%, 40%);">- SIM_tx_count[slotnr] = false; // reset TX complete</span><br><span style="color: hsl(0, 100%, 40%);">-      for (uint16_t i = 0; i < length; i++) { // transmit data</span><br><span style="color: hsl(0, 100%, 40%);">-             while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING blocking)</span><br><span style="color: hsl(0, 100%, 40%);">-            if (1 != io_write(&sim->io, &data[i], 1)) { // put but in transmit buffer</span><br><span style="color: hsl(0, 100%, 40%);">-                    return ERR_IO;</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%);">-       while (!SIM_tx_count[slotnr]); // wait until transmission is complete (WARNING blocking)</span><br><span style="color: hsl(0, 100%, 40%);">-        ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // enable receive again</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     return ERR_NONE;</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%);">-/** read data from card</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[out] data buffer for read data to be stored</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] length length of data to be read</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] wt Waiting Time in ETU</span><br><span style="color: hsl(0, 100%, 40%);">- *  @return error code</span><br><span style="color: hsl(0, 100%, 40%);">- *  TODO fix WT/ETU duration</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int slot_card_read(uint8_t slotnr, uint8_t* data, uint16_t length, uint32_t wt)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   // input checks</span><br><span style="color: hsl(0, 100%, 40%);">- ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(0, 100%, 40%);">-     if (0 == length || NULL == data) {</span><br><span style="color: hsl(0, 100%, 40%);">-              return ERR_INVALID_ARG;</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%);">-       struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // ensure RX is enabled</span><br><span style="color: hsl(0, 100%, 40%);">-     uint32_t timeout = wt; // reset waiting time</span><br><span style="color: hsl(0, 100%, 40%);">-    for (uint16_t i = 0; i < length; i++) { // read all data</span><br><span style="color: hsl(0, 100%, 40%);">-             while (timeout && !usart_async_is_rx_not_empty(sim)) { // verify if data is present</span><br><span style="color: hsl(0, 100%, 40%);">-                     delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-                 timeout--;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (0 == timeout) { // timeout reached</span><br><span style="color: hsl(0, 100%, 40%);">-                  return ERR_TIMEOUT;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-               timeout = wt; // reset waiting time</span><br><span style="color: hsl(0, 100%, 40%);">-             if (1 != io_read(&sim->io, &data[i], 1)) { // read one byte</span><br><span style="color: hsl(0, 100%, 40%);">-                  return ERR_IO;</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return ERR_NONE;</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%);">-/** transfer TPDU</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] slotnr slot number on which to transfer the TPDU</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] header TPDU header to send</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[io] data TPDU data to transfer</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] data_length length of TPDU data to transfer</span><br><span style="color: hsl(0, 100%, 40%);">- *  @param[in] write if the data should be written (true) or read (false)</span><br><span style="color: hsl(0, 100%, 40%);">- * TODO fix WT</span><br><span style="color: hsl(0, 100%, 40%);">- * TODO the data length can be deduce from the header</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int slot_tpdu_xfer(uint8_t slotnr, const uint8_t* header, uint8_t* data, uint16_t data_length, bool write)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  // input checks</span><br><span style="color: hsl(0, 100%, 40%);">- ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(0, 100%, 40%);">-     if (NULL == header || (data_length > 0 && NULL == data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           return ERR_INVALID_ARG;</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%);">-       int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; // get USART peripheral</span><br><span style="color: hsl(0, 100%, 40%);">-        usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      // send command header</span><br><span style="color: hsl(0, 100%, 40%);">-  printf("(%d) TPDU: ", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-        for (uint8_t i = 0; i < 5; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            printf("%02x ", header[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       rc = slot_card_write(slotnr, header, 5); // transmit header</span><br><span style="color: hsl(0, 100%, 40%);">-     if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("error in command header transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-              return rc;</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%);">-       // read procedure byte, and handle data</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t pb = 0x60; // wait more procedure byte</span><br><span style="color: hsl(0, 100%, 40%);">-  uint16_t data_i = 0; // progress in the data transfer</span><br><span style="color: hsl(0, 100%, 40%);">-   while (0x60 == pb) { // wait for SW</span><br><span style="color: hsl(0, 100%, 40%);">-             rc = slot_card_read(slotnr, &pb, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(0, 100%, 40%);">-          if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   printf("error while receiving PB/SW1 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                  return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("%02x ", pb);</span><br><span style="color: hsl(0, 100%, 40%);">-          if (0x60 == pb) { // NULL byte</span><br><span style="color: hsl(0, 100%, 40%);">-                  // just wait more time</span><br><span style="color: hsl(0, 100%, 40%);">-          } else if ((0x60 == (pb & 0xf0)) || (0x90 == (pb & 0xf0))) { // SW1 byte</span><br><span style="color: hsl(0, 100%, 40%);">-                        // left the rest of the code handle it</span><br><span style="color: hsl(0, 100%, 40%);">-          } else if (header[1] == pb) { // ACK byte</span><br><span style="color: hsl(0, 100%, 40%);">-                       // transfer rest of the data</span><br><span style="color: hsl(0, 100%, 40%);">-                    if (data_i >= data_length) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                         return ERR_INVALID_DATA;</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (write) { // transmit remaining command data</span><br><span style="color: hsl(0, 100%, 40%);">-                         rc = slot_card_write(slotnr, &data[data_i], data_length - data_i); // transmit command data</span><br><span style="color: hsl(0, 100%, 40%);">-                         if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                   printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                                        return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                       } else { // receive remaining command data</span><br><span style="color: hsl(0, 100%, 40%);">-                              rc = slot_card_read(slotnr, &data[data_i], data_length - data_i, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(0, 100%, 40%);">-                             if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                   printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                                 return rc;</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%);">-                       for (uint16_t i = data_i; i < data_length; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                            printf("%02x ", data[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                     }</span><br><span style="color: hsl(0, 100%, 40%);">-                       data_i = data_length; // remember we transferred the data</span><br><span style="color: hsl(0, 100%, 40%);">-                       pb = 0x60; // wait for SW1</span><br><span style="color: hsl(0, 100%, 40%);">-              } else if (header[1] == (pb ^ 0xff)) { // ACK byte</span><br><span style="color: hsl(0, 100%, 40%);">-                      // transfer only one byte</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (data_i >= data_length) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                         return ERR_INVALID_DATA;</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (write) { // transmit command data byte</span><br><span style="color: hsl(0, 100%, 40%);">-                              rc = slot_card_write(slotnr, &data[data_i], 1); // transmit command data</span><br><span style="color: hsl(0, 100%, 40%);">-                            if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                   printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                                        return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                       } else { // receive command data byte</span><br><span style="color: hsl(0, 100%, 40%);">-                           rc = slot_card_read(slotnr, &data[data_i], 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(0, 100%, 40%);">-                                if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                   printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                                 return rc;</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%);">-                       printf("%02x ", data[data_i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                        data_i += 1; // remember we transferred one data byte</span><br><span style="color: hsl(0, 100%, 40%);">-                   pb = 0x60; // wait for SW1</span><br><span style="color: hsl(0, 100%, 40%);">-              } else { // invalid byte</span><br><span style="color: hsl(0, 100%, 40%);">-                        return ERR_INVALID_DATA;</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       // read SW2</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t sw2;</span><br><span style="color: hsl(0, 100%, 40%);">-    rc = slot_card_read(slotnr, &sw2, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("error in receiving SW2 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-                return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       printf("%02x", sw2);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  printf("\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-       return ERR_NONE;</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%);">-DEFUN(sim_status, cmd_sim_status, "sim-status", "Get state of specified NCN8025")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     printf("SIM%d: ", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-    ncn8025_dump(&settings);</span><br><span style="color: hsl(0, 100%, 40%);">-    printf("\r\n");</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%);">-DEFUN(sim_power, cmd_sim_power, "sim-power", "Enable/disable SIM card power")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-    int enable;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("You have to specify 0=disable or 1=enable\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       enable = atoi(argv[2]);</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (enable)</span><br><span style="color: hsl(0, 100%, 40%);">-             settings.cmdvcc = true;</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">-            settings.cmdvcc = false;</span><br><span style="color: hsl(0, 100%, 40%);">-        ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_reset, cmd_sim_reset, "sim-reset", "Enable/disable SIM reset")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-    int enable;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("You have to specify 0=disable or 1=enable\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       enable = atoi(argv[2]);</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (enable)</span><br><span style="color: hsl(0, 100%, 40%);">-             settings.rstin = true;</span><br><span style="color: hsl(0, 100%, 40%);">-  else</span><br><span style="color: hsl(0, 100%, 40%);">-            settings.rstin = false;</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_clkdiv, cmd_sim_clkdiv, "sim-clkdiv", "Set SIM clock divider (1,2,4,8)")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-    int clkdiv;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("You have to specify a valid divider (1,2,4,8)\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-          return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       clkdiv = atoi(argv[2]);</span><br><span style="color: hsl(0, 100%, 40%);">- if (clkdiv != 1 && clkdiv != 2 && clkdiv != 4 && clkdiv != 8) {</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("You have to specify a valid divider (1,2,4,8)\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-          return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     switch (clkdiv) {</span><br><span style="color: hsl(0, 100%, 40%);">-       case 1:</span><br><span style="color: hsl(0, 100%, 40%);">-         settings.clkdiv = SIM_CLKDIV_1;</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case 2:</span><br><span style="color: hsl(0, 100%, 40%);">-         settings.clkdiv = SIM_CLKDIV_2;</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case 4:</span><br><span style="color: hsl(0, 100%, 40%);">-         settings.clkdiv = SIM_CLKDIV_4;</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case 8:</span><br><span style="color: hsl(0, 100%, 40%);">-         settings.clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_voltage, cmd_sim_voltage, "sim-voltage", "Set SIM voltage (5/3/1.8)")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("You have to specify a valid voltage (5/3/1.8)\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-          return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!strcmp(argv[2], "5"))</span><br><span style="color: hsl(0, 100%, 40%);">-            settings.vsel = SIM_VOLT_5V0;</span><br><span style="color: hsl(0, 100%, 40%);">-   else if (!strcmp(argv[2], "3"))</span><br><span style="color: hsl(0, 100%, 40%);">-               settings.vsel = SIM_VOLT_3V0;</span><br><span style="color: hsl(0, 100%, 40%);">-   else if (!strcmp(argv[2], "1.8"))</span><br><span style="color: hsl(0, 100%, 40%);">-             settings.vsel = SIM_VOLT_1V8;</span><br><span style="color: hsl(0, 100%, 40%);">-   else {</span><br><span style="color: hsl(0, 100%, 40%);">-          printf("You have to specify a valid voltage (5/3/1.8)\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-          return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_led, cmd_sim_led, "sim-led", "Set SIM LED (1=on, 0=off)")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (slotnr < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc < 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("You have to specify 0=disable or 1=enable\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (atoi(argv[2]))</span><br><span style="color: hsl(0, 100%, 40%);">-              settings.led = true;</span><br><span style="color: hsl(0, 100%, 40%);">-    else</span><br><span style="color: hsl(0, 100%, 40%);">-            settings.led = false;</span><br><span style="color: hsl(0, 100%, 40%);">-   ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_atr, cmd_sim_atr, "sim-atr", "Read ATR from SIM card")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return;</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%);">-       // check if card is present (and read current settings)</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!settings.simpres) {</span><br><span style="color: hsl(0, 100%, 40%);">-                printf("(%d) error: no card present\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</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%);">-       // switch card off (assert reset and disable power)</span><br><span style="color: hsl(0, 100%, 40%);">-     // note: ISO/IEC 7816-3:2006 section 6.4 provides the deactivation sequence, but not the minimum corresponding times</span><br><span style="color: hsl(0, 100%, 40%);">-    settings.rstin = true;</span><br><span style="color: hsl(0, 100%, 40%);">-  settings.cmdvcc = false;</span><br><span style="color: hsl(0, 100%, 40%);">-        settings.led = true;</span><br><span style="color: hsl(0, 100%, 40%);">-    ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     // TODO wait some time for card to be completely deactivated</span><br><span style="color: hsl(0, 100%, 40%);">-    usart_async_flush_rx_buffer(SIM_peripheral_descriptors[slotnr]); // flush RX buffer to start from scratch</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%);">-        // set clock to lowest frequency (20 MHz / 8 = 2.5 MHz)</span><br><span style="color: hsl(0, 100%, 40%);">- // note: according to ISO/IEC 7816-3:2006 section 5.2.3 the minimum value is 1 MHz, and maximum is 5 MHz during activation</span><br><span style="color: hsl(0, 100%, 40%);">-      settings.clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(0, 100%, 40%);">- // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span style="color: hsl(0, 100%, 40%);">-        slot_set_isorate(slotnr, settings.clkdiv, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);</span><br><span style="color: hsl(0, 100%, 40%);">-  // set card voltage to 3.0 V (the most supported)</span><br><span style="color: hsl(0, 100%, 40%);">-       // note: according to ISO/IEC 7816-3:2006 no voltage should damage the card, and you should cycle from low to high</span><br><span style="color: hsl(0, 100%, 40%);">-      settings.vsel = SIM_VOLT_3V0;</span><br><span style="color: hsl(0, 100%, 40%);">-   // provide power (the NCN8025 should perform the activation according to spec)</span><br><span style="color: hsl(0, 100%, 40%);">-  // note: activation sequence is documented in ISO/IEC 7816-3:2006 section 6.2</span><br><span style="color: hsl(0, 100%, 40%);">-   settings.cmdvcc = true;</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     // wait for Tb=400 cycles before re-asserting reset</span><br><span style="color: hsl(0, 100%, 40%);">-     delay_us(400 * 10000 / 2500); // 400 cycles * 1000 for us, 2.5 MHz / 1000 for us</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        // de-assert reset to switch card back on</span><br><span style="color: hsl(0, 100%, 40%);">-       settings.rstin = false;</span><br><span style="color: hsl(0, 100%, 40%);">- ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     // wait for Tc=40000 cycles for transmission to start</span><br><span style="color: hsl(0, 100%, 40%);">-   uint32_t cycles = 40000;</span><br><span style="color: hsl(0, 100%, 40%);">-        while (cycles && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(0, 100%, 40%);">-            delay_us(10);</span><br><span style="color: hsl(0, 100%, 40%);">-           cycles -= 25; // 10 us = 25 cycles at 2.5 MHz</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(0, 100%, 40%);">-         delay_us(12 * 372 / 1 / 2); // wait more than one byte (approximate freq down to 2 MHz)</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       // verify if one byte has been received</span><br><span style="color: hsl(0, 100%, 40%);">- if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("(%d) error: card not responsive\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                return;</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%);">-       // read ATR (just do it until there is no traffic anymore)</span><br><span style="color: hsl(0, 100%, 40%);">-      // TODO the ATR should be parsed to read the right number of bytes, instead we just wait until to end of WT</span><br><span style="color: hsl(0, 100%, 40%);">-     printf("(%d) ATR: ", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t atr_byte;</span><br><span style="color: hsl(0, 100%, 40%);">-       while (usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(0, 100%, 40%);">-               if (1 == io_read(&SIM_peripheral_descriptors[slotnr]->io, &atr_byte, 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   printf("%02x ", atr_byte);</span><br><span style="color: hsl(0, 100%, 40%);">-            }</span><br><span style="color: hsl(0, 100%, 40%);">-               uint16_t wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU</span><br><span style="color: hsl(0, 100%, 40%);">-              while (wt && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-                 wt--;</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%);">-       printf("\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* disable LED */</span><br><span style="color: hsl(0, 100%, 40%);">-       settings.led = false;</span><br><span style="color: hsl(0, 100%, 40%);">-   ncn8025_set(slotnr, &settings);</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%);">-DEFUN(sim_iccid, cmd_sim_iccid, "sim-iccid", "Read ICCID from SIM card")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ncn8025_settings settings;</span><br><span style="color: hsl(0, 100%, 40%);">-       int slotnr = validate_slotnr(argc, argv, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return;</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%);">-       // read current settings and check if card is present and powered</span><br><span style="color: hsl(0, 100%, 40%);">-       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!settings.simpres) {</span><br><span style="color: hsl(0, 100%, 40%);">-                printf("(%d) error: no card present\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!settings.cmdvcc) {</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("(%d) error: card not powered\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-           return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (settings.rstin) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("(%d) error: card under reset\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-           return;</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%);">-       // enable LED</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!settings.led) {</span><br><span style="color: hsl(0, 100%, 40%);">-            settings.led = true;</span><br><span style="color: hsl(0, 100%, 40%);">-            ncn8025_set(slotnr, &settings);</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%);">-       // select MF</span><br><span style="color: hsl(0, 100%, 40%);">-    printf("(%d) SELECT MF\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">- const uint8_t select_header[] = {0xa0, 0xa4, 0x00, 0x00, 0x02}; // see TS 102.221 sec. 11.1.1</span><br><span style="color: hsl(0, 100%, 40%);">-   const uint8_t select_data_mf[] = {0x3f, 0x00}; // see TS 102.221 sec. 13.1</span><br><span style="color: hsl(0, 100%, 40%);">-      int rc = slot_tpdu_xfer(slotnr, select_header, (uint8_t*)select_data_mf, ARRAY_SIZE(select_data_mf), true); // transfer TPDU</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("error while SELECT MF (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       // ignore response data</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // select EF_ICCID</span><br><span style="color: hsl(0, 100%, 40%);">-      printf("(%d) SELECT EF_ICCID\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-   const uint8_t select_data_ef_iccid[] = {0x2f, 0xe2}; // see TS 102.221 sec. 13.2</span><br><span style="color: hsl(0, 100%, 40%);">-        rc = slot_tpdu_xfer(slotnr, select_header, (uint8_t*)select_data_ef_iccid, ARRAY_SIZE(select_data_ef_iccid), true); // transfer TPDU</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("error while SELECT EF_ICCID (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       // ignore response data</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // read EF_ICCID</span><br><span style="color: hsl(0, 100%, 40%);">-        printf("(%d) READ EF_ICCID\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t iccid[10];</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t read_binary[] = {0xa0, 0xb0, 0x00, 0x00, ARRAY_SIZE(iccid)}; // see TS 102.221 sec. 11.1.3</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = slot_tpdu_xfer(slotnr, read_binary, iccid, ARRAY_SIZE(iccid), false); // transfer TPDU</span><br><span style="color: hsl(0, 100%, 40%);">-     if (ERR_NONE != rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("error while READ ICCID (errno = %d)\r\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-       // ignore response data</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("(%d) ICCID: ", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-       for (uint8_t i = 0; i < ARRAY_SIZE(iccid); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            uint8_t nibble = iccid[i] & 0xf;</span><br><span style="color: hsl(0, 100%, 40%);">-            if (0xf == nibble) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("%x", nibble);</span><br><span style="color: hsl(0, 100%, 40%);">-         nibble = iccid[i] >> 4;</span><br><span style="color: hsl(0, 100%, 40%);">-           if (0xf == nibble) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("%x", nibble);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       printf("\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       // disable LED</span><br><span style="color: hsl(0, 100%, 40%);">-  settings.led = false;</span><br><span style="color: hsl(0, 100%, 40%);">-   ncn8025_set(slotnr, &settings);</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%);">-DEFUN(get_time, cmd_get_time, "get-time", "Read Time from RTC")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct calendar_date_time dt;</span><br><span style="color: hsl(0, 100%, 40%);">-   calendar_get_date_time(&CALENDAR_0, &dt);</span><br><span style="color: hsl(0, 100%, 40%);">-       printf("%04u-%02u-%02u %02u:%02u:%02u\r\n", dt.date.year, dt.date.month, dt.date.day,</span><br><span style="color: hsl(0, 100%, 40%);">-         dt.time.hour, dt.time.min, dt.time.sec);</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%);">-#include <osmocom/core/timer.h></span><br><span style="color: hsl(0, 100%, 40%);">-static struct osmo_timer_list t;</span><br><span style="color: hsl(0, 100%, 40%);">-static void tmr_cb(void *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   printf("timer fired!\r\n");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-DEFUN(test_timer, cmd_test_timer, "test-timer", "Test osmo_timer")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   printf("Setting up timer for 3s...\n\r");</span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_timer_setup(&t, &tmr_cb, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-    osmo_timer_schedule(&t, 3, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(120, 100%, 40%);">+//#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+//static struct osmo_timer_list t;</span><br><span style="color: hsl(120, 100%, 40%);">+//static void tmr_cb(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//     printf("timer fired!\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+//}</span><br><span style="color: hsl(120, 100%, 40%);">+//DEFUN(test_timer, cmd_test_timer, "test-timer", "Test osmo_timer")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//   printf("Setting up timer for 3s...\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+// osmo_timer_setup(&t, &tmr_cb, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+//        osmo_timer_schedule(&t, 3, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+//}</span><br><span> </span><br><span> </span><br><span> extern void testmode_init(void);</span><br><span>@@ -991,25 +1003,25 @@</span><br><span> </span><br><span> #include "talloc.h"</span><br><span> #include "logging.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+//#include <osmocom/core/msgb.h></span><br><span> void *g_tall_ctx;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-DEFUN(_talloc_report, cmd_talloc_report, "talloc-report", "Generate a talloc report")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      talloc_report_full(g_tall_ctx, stdout);</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%);">-DEFUN(talloc_test, cmd_talloc_test, "talloc-test", "Test the talloc allocator")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    for (int i = 0; i < 10; i++)</span><br><span style="color: hsl(0, 100%, 40%);">-         talloc_named_const(g_tall_ctx, 10, "sibling");</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%);">-DEFUN(v_talloc_free, cmd_talloc_free, "talloc-free", "Release all memory")</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        talloc_free(g_tall_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">-        g_tall_ctx = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(120, 100%, 40%);">+//DEFUN(_talloc_report, cmd_talloc_report, "talloc-report", "Generate a talloc report")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//       talloc_report_full(g_tall_ctx, stdout);</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%);">+//DEFUN(talloc_test, cmd_talloc_test, "talloc-test", "Test the talloc allocator")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//        for (int i = 0; i < 10; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+//             talloc_named_const(g_tall_ctx, 10, "sibling");</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%);">+//DEFUN(v_talloc_free, cmd_talloc_free, "talloc-free", "Release all memory")</span><br><span style="color: hsl(120, 100%, 40%);">+//{</span><br><span style="color: hsl(120, 100%, 40%);">+//    talloc_free(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+//    g_tall_ctx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+//}</span><br><span> </span><br><span> /* Section 9.6 of SAMD5x/E5x Family Data Sheet */</span><br><span> static int get_chip_unique_serial(uint8_t *out, size_t len)</span><br><span>@@ -1065,6 +1077,55 @@</span><br><span>             strcat(out, "BACKUP ");</span><br><span> }</span><br><span> </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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t clock_freqs[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        2500000</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%);">+static uint32_t data_rates[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       9600</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct usb_desc_collection usb_fs_descs;</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%);">+static int feed_ccid(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct usb_ep_q *ep_q = &g_ccid_s.out_ep;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     msg = msgb_dequeue_irqsafe(&g_ccid_s.out_ep.list);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ccid_handle_out(&g_ci, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+      return 1;</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%);">+static int ccid_ops_send_in(struct ccid_instance *ci, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    /* add just-received msg to tail of endpoint queue */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* append to list of pending-to-be-handed messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add_tail_at(&msg->list, &g_ccid_s.in_ep.list);</span><br><span style="color: hsl(120, 100%, 40%);">+       submit_next_in();</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</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%);">+static const struct ccid_ops c_ops = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .send_in = ccid_ops_send_in,</span><br><span style="color: hsl(120, 100%, 40%);">+  .send_int = 0,</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NUM_OUT_BUF 7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(void)</span><br><span> {</span><br><span>    char sernr_buf[16*2+1];</span><br><span>@@ -1077,21 +1138,21 @@</span><br><span>    usb_start();</span><br><span> </span><br><span>     board_init();</span><br><span style="color: hsl(0, 100%, 40%);">-   command_init("sysmoOCTSIM> ");</span><br><span style="color: hsl(0, 100%, 40%);">-     command_register(&cmd_sim_status);</span><br><span style="color: hsl(0, 100%, 40%);">-  command_register(&cmd_sim_power);</span><br><span style="color: hsl(0, 100%, 40%);">-   command_register(&cmd_sim_reset);</span><br><span style="color: hsl(0, 100%, 40%);">-   command_register(&cmd_sim_clkdiv);</span><br><span style="color: hsl(0, 100%, 40%);">-  command_register(&cmd_sim_voltage);</span><br><span style="color: hsl(0, 100%, 40%);">- command_register(&cmd_sim_led);</span><br><span style="color: hsl(0, 100%, 40%);">-     command_register(&cmd_sim_atr);</span><br><span style="color: hsl(0, 100%, 40%);">-     command_register(&cmd_sim_iccid);</span><br><span style="color: hsl(0, 100%, 40%);">-   testmode_init();</span><br><span style="color: hsl(0, 100%, 40%);">-        command_register(&cmd_talloc_test);</span><br><span style="color: hsl(0, 100%, 40%);">- command_register(&cmd_talloc_report);</span><br><span style="color: hsl(0, 100%, 40%);">-       command_register(&cmd_talloc_free);</span><br><span style="color: hsl(0, 100%, 40%);">- command_register(&cmd_get_time);</span><br><span style="color: hsl(0, 100%, 40%);">-    command_register(&cmd_test_timer);</span><br><span style="color: hsl(120, 100%, 40%);">+//      command_init("sysmoOCTSIM> ");</span><br><span style="color: hsl(120, 100%, 40%);">+// command_register(&cmd_sim_status);</span><br><span style="color: hsl(120, 100%, 40%);">+//      command_register(&cmd_sim_power);</span><br><span style="color: hsl(120, 100%, 40%);">+//       command_register(&cmd_sim_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+//       command_register(&cmd_sim_clkdiv);</span><br><span style="color: hsl(120, 100%, 40%);">+//      command_register(&cmd_sim_voltage);</span><br><span style="color: hsl(120, 100%, 40%);">+//     command_register(&cmd_sim_led);</span><br><span style="color: hsl(120, 100%, 40%);">+// command_register(&cmd_sim_atr);</span><br><span style="color: hsl(120, 100%, 40%);">+// command_register(&cmd_sim_iccid);</span><br><span style="color: hsl(120, 100%, 40%);">+//       testmode_init();</span><br><span style="color: hsl(120, 100%, 40%);">+//    command_register(&cmd_talloc_test);</span><br><span style="color: hsl(120, 100%, 40%);">+//     command_register(&cmd_talloc_report);</span><br><span style="color: hsl(120, 100%, 40%);">+//   command_register(&cmd_talloc_free);</span><br><span style="color: hsl(120, 100%, 40%);">+//     command_register(&cmd_get_time);</span><br><span style="color: hsl(120, 100%, 40%);">+//        command_register(&cmd_test_timer);</span><br><span> </span><br><span>   printf("\r\n\r\n"</span><br><span>          "=============================================================================\n\r"</span><br><span>@@ -1109,11 +1170,42 @@</span><br><span> </span><br><span>  LOGP(DUSB, LOGL_ERROR, "foobar usb\n");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   command_print_prompt();</span><br><span style="color: hsl(120, 100%, 40%);">+       //FIXME osmo_emb has a pool?</span><br><span style="color: hsl(120, 100%, 40%);">+  msgb_set_talloc_ctx(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ccid_instance_init(&g_ci, &c_ops, &iso_fsm_slot_ops, &usb_fs_descs.ccid.class,</span><br><span style="color: hsl(120, 100%, 40%);">+                           data_rates, clock_freqs, "", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for(int i =0; i < NUM_OUT_BUF; i++){</span><br><span style="color: hsl(120, 100%, 40%);">+               struct msgb *msg = msgb_alloc(300, "ccid");</span><br><span style="color: hsl(120, 100%, 40%);">+         OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+             /* return the message back to the queue of free message buffers */</span><br><span style="color: hsl(120, 100%, 40%);">+            llist_add_tail_at(&msg->list, &g_ccid_s.free_q);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     submit_next_out();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//        command_print_prompt();</span><br><span>      while (true) { // main loop</span><br><span>          command_try_recv();</span><br><span>          poll_card_detect();</span><br><span>          submit_next_irq();</span><br><span style="color: hsl(120, 100%, 40%);">+            feed_ccid();</span><br><span>                 osmo_timers_update();</span><br><span style="color: hsl(120, 100%, 40%);">+         int qs = llist_count_at(&g_ccid_s.free_q);</span><br><span style="color: hsl(120, 100%, 40%);">+                if(qs > NUM_OUT_BUF)</span><br><span style="color: hsl(120, 100%, 40%);">+                       for (int i= 0; i < qs-NUM_OUT_BUF; i++){</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct msgb *msg = msgb_dequeue_irqsafe(&g_ccid_s.free_q);</span><br><span style="color: hsl(120, 100%, 40%);">+                                if (msg)</span><br><span style="color: hsl(120, 100%, 40%);">+                              msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+             if(qs < NUM_OUT_BUF)</span><br><span style="color: hsl(120, 100%, 40%);">+                       for (int i= 0; i < qs-NUM_OUT_BUF; i++){</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct msgb *msg = msgb_alloc(300,"ccid");</span><br><span style="color: hsl(120, 100%, 40%);">+                          OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* return the message back to the queue of free message buffers */</span><br><span style="color: hsl(120, 100%, 40%);">+                            llist_add_tail_at(&msg->list, &g_ccid_s.free_q);</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>        }</span><br><span> }</span><br><span>diff --git a/sysmoOCTSIM/talloc.c b/sysmoOCTSIM/talloc.c</span><br><span>index c5c9062..790f657 100644</span><br><span>--- a/sysmoOCTSIM/talloc.c</span><br><span>+++ b/sysmoOCTSIM/talloc.c</span><br><span>@@ -30,6 +30,10 @@</span><br><span>   inspired by http://swapped.cc/halloc/</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <parts.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include "replace.h"</span><br><span> #include "talloc.h"</span><br><span> </span><br><span>@@ -727,6 +731,9 @@</span><br><span>     size_t total_len = TC_HDR_SIZE + size + prefix_len;</span><br><span>  struct talloc_chunk *parent = NULL;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       // do not allocate while handling interrupts!</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT( !(SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       if (unlikely(context == NULL)) {</span><br><span>             context = null_context;</span><br><span>      }</span><br><span>diff --git a/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c</span><br><span>index 65d3499..665f0fc 100644</span><br><span>--- a/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c</span><br><span>+++ b/sysmoOCTSIM/usb/class/ccid/device/ccid_df.c</span><br><span>@@ -24,6 +24,9 @@</span><br><span> #include "ccid_proto.h"</span><br><span> #include "usb_includes.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "cdcdf_acm_desc.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "usb_descriptors.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifndef USB_CLASS_CCID</span><br><span> #define    USB_CLASS_CCID  11</span><br><span> #endif</span><br><span>@@ -40,9 +43,11 @@</span><br><span> static struct usbdf_driver _ccid_df;</span><br><span> static struct ccid_df_func_data _ccid_df_funcd;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct usb_desc_collection usb_fs_descs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* FIXME: make those configurable, ensure they're sized according to</span><br><span>  * bNumClockSupported / bNumDataRatesSupported */</span><br><span style="color: hsl(0, 100%, 40%);">-static uint32_t ccid_clock_frequencies[] = { LE32(20000) };</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t ccid_clock_frequencies[CCID_NUM_CLK_SUPPORTED] = { LE32(2500),LE32(5000),LE32(10000),LE32(20000) };</span><br><span> static uint32_t ccid_baud_rates[] = { LE32(9600) };</span><br><span> </span><br><span> static int32_t ccid_df_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)</span><br><span>diff --git a/sysmoOCTSIM/usb_descriptors.c b/sysmoOCTSIM/usb_descriptors.c</span><br><span>index 944e43b..f0d1a5c 100644</span><br><span>--- a/sysmoOCTSIM/usb_descriptors.c</span><br><span>+++ b/sysmoOCTSIM/usb_descriptors.c</span><br><span>@@ -4,51 +4,11 @@</span><br><span> #include "usb_protocol_cdc.h"</span><br><span> #include "ccid_proto.h"</span><br><span> #include "cdcdf_acm_desc.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "usb_descriptors.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* aggregate descriptors for the combined CDC-ACM + CCID device that we expose</span><br><span style="color: hsl(0, 100%, 40%);">- * from sysmoQMOD */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum str_desc_num {</span><br><span style="color: hsl(0, 100%, 40%);">-      STR_DESC_MANUF = 1,</span><br><span style="color: hsl(0, 100%, 40%);">-     STR_DESC_PRODUCT,</span><br><span style="color: hsl(0, 100%, 40%);">-       STR_DESC_CONFIG,</span><br><span style="color: hsl(0, 100%, 40%);">-        STR_DESC_INTF_ACM_COMM,</span><br><span style="color: hsl(0, 100%, 40%);">- STR_DESC_INTF_ACM_DATA,</span><br><span style="color: hsl(0, 100%, 40%);">- STR_DESC_INTF_CCID,</span><br><span style="color: hsl(0, 100%, 40%);">-     STR_DESC_SERIAL,</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* a struct of structs representing the concatenated collection of USB descriptors */</span><br><span style="color: hsl(0, 100%, 40%);">-struct usb_desc_collection {</span><br><span style="color: hsl(0, 100%, 40%);">- struct usb_dev_desc dev;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct usb_config_desc cfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     /* CDC-ACM: Two interfaces, one with IRQ EP and one with BULK IN + OUT */</span><br><span style="color: hsl(0, 100%, 40%);">-       struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct usb_iface_desc iface;</span><br><span style="color: hsl(0, 100%, 40%);">-                    struct usb_cdc_hdr_desc cdc_hdr;</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct usb_cdc_call_mgmt_desc cdc_call_mgmt;</span><br><span style="color: hsl(0, 100%, 40%);">-                    struct usb_cdc_acm_desc cdc_acm;</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct usb_cdc_union_desc cdc_union;</span><br><span style="color: hsl(0, 100%, 40%);">-                    struct usb_ep_desc ep[1];</span><br><span style="color: hsl(0, 100%, 40%);">-               } comm;</span><br><span style="color: hsl(0, 100%, 40%);">-         struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                        struct usb_iface_desc iface;</span><br><span style="color: hsl(0, 100%, 40%);">-                    struct usb_ep_desc ep[2];</span><br><span style="color: hsl(0, 100%, 40%);">-               } data;</span><br><span style="color: hsl(0, 100%, 40%);">- } cdc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  /* CCID: One interface with CCID class descriptor and three endpoints */</span><br><span style="color: hsl(0, 100%, 40%);">-        struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct usb_iface_desc iface;</span><br><span style="color: hsl(0, 100%, 40%);">-            struct usb_ccid_class_descriptor class;</span><br><span style="color: hsl(0, 100%, 40%);">-         struct usb_ep_desc ep[3];</span><br><span style="color: hsl(0, 100%, 40%);">-       } ccid;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t str[116];</span><br><span style="color: hsl(0, 100%, 40%);">-} __attribute__((packed));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct usb_desc_collection usb_fs_descs = {</span><br><span style="color: hsl(120, 100%, 40%);">+const struct usb_desc_collection usb_fs_descs = {</span><br><span>       .dev = {</span><br><span>             .bLength = sizeof(struct usb_dev_desc),</span><br><span>              .bDescriptorType = USB_DT_DEVICE,</span><br><span>@@ -176,17 +136,19 @@</span><br><span>                    .bcdCCID = LE16(0x0110),</span><br><span>                     .bMaxSlotIndex = 7,</span><br><span>                  .bVoltageSupport = 0x07, /* 5/3/1.8V */</span><br><span style="color: hsl(0, 100%, 40%);">-                 .dwProtocols = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+//                        .dwProtocols = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+                  .dwProtocols = 0x01,</span><br><span>                         .dwDefaultClock = LE32(2500),</span><br><span>                        .dwMaximumClock = LE32(20000),</span><br><span style="color: hsl(0, 100%, 40%);">-                  .bNumClockSupported = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+                      .bNumClockSupported = CCID_NUM_CLK_SUPPORTED,</span><br><span>                        .dwDataRate = LE32(9600),</span><br><span>                    .dwMaxDataRate = LE32(921600),</span><br><span>                       .bNumDataRatesSupported = 0,</span><br><span>                         .dwMaxIFSD = LE32(0),</span><br><span>                        .dwSynchProtocols = LE32(0),</span><br><span>                         .dwMechanical = LE32(0),</span><br><span style="color: hsl(0, 100%, 40%);">-                        .dwFeatures = LE32(0x10 | 0x00010000),</span><br><span style="color: hsl(120, 100%, 40%);">+                        .dwFeatures = LE32(0x10 | 0x00010080),</span><br><span style="color: hsl(120, 100%, 40%);">+//                      .dwFeatures = LE32(0x2 | 0x40),</span><br><span>                      .dwMaxCCIDMessageLength = 272,</span><br><span>                       .bClassGetResponse = 0xff,</span><br><span>                   .bClassEnvelope = 0xff,</span><br><span>diff --git a/sysmoOCTSIM/usb_descriptors.h b/sysmoOCTSIM/usb_descriptors.h</span><br><span>new file mode 100644</span><br><span>index 0000000..75b9e01</span><br><span>--- /dev/null</span><br><span>+++ b/sysmoOCTSIM/usb_descriptors.h</span><br><span>@@ -0,0 +1,56 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * usb_descriptors.h</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Created on: Oct 11, 2019</span><br><span style="color: hsl(120, 100%, 40%);">+ *      Author: phi</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%);">+#ifndef USB_DESCRIPTORS_H_</span><br><span style="color: hsl(120, 100%, 40%);">+#define USB_DESCRIPTORS_H_</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CCID_NUM_CLK_SUPPORTED 4</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* aggregate descriptors for the combined CDC-ACM + CCID device that we expose</span><br><span style="color: hsl(120, 100%, 40%);">+ * from sysmoQMOD */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum str_desc_num {</span><br><span style="color: hsl(120, 100%, 40%);">+      STR_DESC_MANUF = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+   STR_DESC_PRODUCT,</span><br><span style="color: hsl(120, 100%, 40%);">+     STR_DESC_CONFIG,</span><br><span style="color: hsl(120, 100%, 40%);">+      STR_DESC_INTF_ACM_COMM,</span><br><span style="color: hsl(120, 100%, 40%);">+       STR_DESC_INTF_ACM_DATA,</span><br><span style="color: hsl(120, 100%, 40%);">+       STR_DESC_INTF_CCID,</span><br><span style="color: hsl(120, 100%, 40%);">+   STR_DESC_SERIAL,</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%);">+/* a struct of structs representing the concatenated collection of USB descriptors */</span><br><span style="color: hsl(120, 100%, 40%);">+struct usb_desc_collection {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct usb_dev_desc dev;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct usb_config_desc cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CDC-ACM: Two interfaces, one with IRQ EP and one with BULK IN + OUT */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct usb_iface_desc iface;</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct usb_cdc_hdr_desc cdc_hdr;</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct usb_cdc_call_mgmt_desc cdc_call_mgmt;</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct usb_cdc_acm_desc cdc_acm;</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct usb_cdc_union_desc cdc_union;</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct usb_ep_desc ep[1];</span><br><span style="color: hsl(120, 100%, 40%);">+             } comm;</span><br><span style="color: hsl(120, 100%, 40%);">+               struct {</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct usb_iface_desc iface;</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct usb_ep_desc ep[2];</span><br><span style="color: hsl(120, 100%, 40%);">+             } data;</span><br><span style="color: hsl(120, 100%, 40%);">+       } cdc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* CCID: One interface with CCID class descriptor and three endpoints */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct usb_iface_desc iface;</span><br><span style="color: hsl(120, 100%, 40%);">+          struct usb_ccid_class_descriptor class;</span><br><span style="color: hsl(120, 100%, 40%);">+               struct usb_ep_desc ep[3];</span><br><span style="color: hsl(120, 100%, 40%);">+     } ccid;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t str[116];</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* USB_DESCRIPTORS_H_ */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16235">change 16235</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/osmo-ccid-firmware/+/16235"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ccid-firmware </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia9d3b099181c24feabdb6a5fddb8db6c44efb72d </div>
<div style="display:none"> Gerrit-Change-Number: 16235 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Hoernchen <ewild@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>