<p>Hoernchen has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16237">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">setparameters/PPS works<br><br>Change-Id: I2e226b0033f8a147fad60a33a63cc45ee9adc756<br>---<br>M ccid_common/ccid_device.c<br>M ccid_common/ccid_device.h<br>M ccid_common/ccid_slot_fsm.c<br>M ccid_common/cuart.h<br>R ccid_common/iso7816_3.c<br>R ccid_common/iso7816_3.h<br>M ccid_common/iso7816_fsm.c<br>M ccid_common/iso7816_fsm.h<br>M sysmoOCTSIM/cuart_driver_asf4_usart_async.c<br>M sysmoOCTSIM/gcc/Makefile<br>M sysmoOCTSIM/ncn8025.c<br>M sysmoOCTSIM/ncn8025.h<br>12 files changed, 370 insertions(+), 29 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/37/16237/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/ccid_common/ccid_device.c b/ccid_common/ccid_device.c</span><br><span>index 8183b16..ba36988 100644</span><br><span>--- a/ccid_common/ccid_device.c</span><br><span>+++ b/ccid_common/ccid_device.c</span><br><span>@@ -24,8 +24,10 @@</span><br><span> static int decode_ccid_pars_t0(struct ccid_pars_decoded *out, const struct ccid_proto_data_t0 *in)</span><br><span> {</span><br><span>    /* input validation: only 0x00 and 0x02 permitted for bmTCCKST0 */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (in->bmTCCKST0 & 0xFD)</span><br><span style="color: hsl(0, 100%, 40%);">-                return -11;</span><br><span style="color: hsl(120, 100%, 40%);">+// if (in->bmTCCKST0 & 0xFD)</span><br><span style="color: hsl(120, 100%, 40%);">+//            return -11;</span><br><span style="color: hsl(120, 100%, 40%);">+// 6.1.7 says: "Note: the CCID ignores this bit", placeholder for GETparameters</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* input validation: only 0x00 to 0x03 permitted for bClockSTop */</span><br><span>   if (in->bClockStop & 0xFC)</span><br><span>            return -14;</span><br><span>@@ -254,7 +256,7 @@</span><br><span>    }</span><br><span>    return msg;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span>                                         enum ccid_error_code err)</span><br><span> {</span><br><span>    return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);</span><br><span>@@ -276,7 +278,7 @@</span><br><span>     }</span><br><span>    return msg;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span>                                         enum ccid_error_code err)</span><br><span> {</span><br><span>    return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);</span><br><span>@@ -465,7 +467,7 @@</span><br><span> </span><br><span>         /* copy default parameters from somewhere */</span><br><span>         /* FIXME: T=1 */</span><br><span style="color: hsl(0, 100%, 40%);">-        cs->ci->slot_ops->set_params(cs, CCID_PROTOCOL_NUM_T0, cs->default_pars);</span><br><span style="color: hsl(120, 100%, 40%);">+ cs->ci->slot_ops->set_params(cs, seq, CCID_PROTOCOL_NUM_T0, cs->default_pars);</span><br><span>   cs->pars = *cs->default_pars;</span><br><span> </span><br><span>      resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span>@@ -502,14 +504,16 @@</span><br><span>               goto out;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ cs->proposed_pars = pars_dec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   /* validate parameters; abort if they are not supported */</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = cs->ci->slot_ops->set_params(cs, spar->bProtocolNum, &pars_dec);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = cs->ci->slot_ops->set_params(cs, seq, spar->bProtocolNum, &pars_dec);</span><br><span>   if (rc < 0) {</span><br><span>             resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_FAILED, -rc);</span><br><span style="color: hsl(0, 100%, 40%);">-    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                cs->pars = pars_dec;</span><br><span style="color: hsl(0, 100%, 40%);">-         resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                goto out;</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* busy, tdpu like callback */</span><br><span style="color: hsl(120, 100%, 40%);">+        return 1;</span><br><span> out:</span><br><span>    return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span>diff --git a/ccid_common/ccid_device.h b/ccid_common/ccid_device.h</span><br><span>index ae3ab5b..8390783 100644</span><br><span>--- a/ccid_common/ccid_device.h</span><br><span>+++ b/ccid_common/ccid_device.h</span><br><span>@@ -53,6 +53,8 @@</span><br><span>    bool cmd_busy;</span><br><span>       /* decided CCID parameters */</span><br><span>        struct ccid_pars_decoded pars;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* proposed CCID parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ccid_pars_decoded proposed_pars;</span><br><span>      /* default parameters; applied on ResetParameters */</span><br><span>         const struct ccid_pars_decoded *default_pars;</span><br><span> };</span><br><span>@@ -80,7 +82,7 @@</span><br><span>                              const struct ccid_pc_to_rdr_xfr_block *xfb);</span><br><span>         void (*set_power)(struct ccid_slot *cs, bool enable);</span><br><span>        void (*set_clock)(struct ccid_slot *cs, enum ccid_clock_command cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-   int (*set_params)(struct ccid_slot *cs, enum ccid_protocol_num proto,</span><br><span style="color: hsl(120, 100%, 40%);">+ int (*set_params)(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,</span><br><span>                     const struct ccid_pars_decoded *pars_dec);</span><br><span>         int (*set_rate_and_clock)(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps);</span><br><span> };</span><br><span>@@ -118,6 +120,10 @@</span><br><span>                   const uint32_t *data_rates, const uint32_t *clock_freqs,</span><br><span>                     const char *name, void *priv);</span><br><span> int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      enum ccid_error_code err);</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           enum ccid_error_code err);</span><br><span> </span><br><span> /* Invalid request received: Please return STALL */</span><br><span> #define CCID_CTRL_RET_INVALID       -1</span><br><span>diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c</span><br><span>index 870cf35..8bdcfd5 100644</span><br><span>--- a/ccid_common/ccid_slot_fsm.c</span><br><span>+++ b/ccid_common/ccid_slot_fsm.c</span><br><span>@@ -13,6 +13,7 @@</span><br><span> #include "ccid_device.h"</span><br><span> #include "cuart.h"</span><br><span> #include "iso7816_fsm.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "iso7816_3.h"</span><br><span> </span><br><span> struct iso_fsm_slot {</span><br><span>   /* CCID slot above us */</span><br><span>@@ -112,6 +113,33 @@</span><br><span>              ccid_slot_send_unbusy(cs, resp);</span><br><span>             msgb_free(tpdu);</span><br><span>             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_DONE_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+          tpdu = data;</span><br><span style="color: hsl(120, 100%, 40%);">+          /* pps was successful, so we know these values are fine */</span><br><span style="color: hsl(120, 100%, 40%);">+            uint16_t F = iso7816_3_fi_table[cs->proposed_pars.fi];</span><br><span style="color: hsl(120, 100%, 40%);">+             uint8_t D = iso7816_3_di_table[cs->proposed_pars.di];</span><br><span style="color: hsl(120, 100%, 40%);">+              uint32_t fmax = iso7816_3_fmax_table[cs->proposed_pars.fi];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK_FREQ, fmax);</span><br><span style="color: hsl(120, 100%, 40%);">+             card_uart_ctrl(ss->cuart, CUART_CTL_FD, F/D);</span><br><span style="color: hsl(120, 100%, 40%);">+              card_uart_ctrl(ss->cuart, CUART_CTL_WTIME, cs->proposed_pars.t0.waiting_integer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             cs->pars = cs->proposed_pars;</span><br><span style="color: hsl(120, 100%, 40%);">+           resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */</span><br><span style="color: hsl(120, 100%, 40%);">+            msgb_free(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_FAILED_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+                tpdu = data;</span><br><span style="color: hsl(120, 100%, 40%);">+          /* failed fi/di */</span><br><span style="color: hsl(120, 100%, 40%);">+            resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_FAILED, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+            ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+              /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */</span><br><span style="color: hsl(120, 100%, 40%);">+            msgb_free(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       default:</span><br><span>             LOGPCS(cs, LOGL_NOTICE, "%s(event=%d, cause=%d, data=%p) unhandled\n",</span><br><span>                     __func__, event, cause, data);</span><br><span>@@ -175,10 +203,36 @@</span><br><span>       }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int iso_fsm_slot_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,</span><br><span style="color: hsl(120, 100%, 40%);">+static int iso_fsm_slot_set_params(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,</span><br><span>                                const struct ccid_pars_decoded *pars_dec)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  /* we always acknowledge all parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *tpdu;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* see 6.1.7 for error offsets */</span><br><span style="color: hsl(120, 100%, 40%);">+     if(proto != CCID_PROTOCOL_NUM_T0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -7;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if(pars_dec->t0.guard_time_etu != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -12;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if(pars_dec->clock_stop != CCID_CLOCK_STOP_NOTALLOWED)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -14;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ss->seq = seq;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Hardware does not support SPU, so no PPS2, and PPS3 is reserved anyway */</span><br><span style="color: hsl(120, 100%, 40%);">+  tpdu = msgb_alloc(6, "PPSRQ");</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_put_u8(tpdu, 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+      msgb_put_u8(tpdu, (1 << 4)); /* only PPS1, T=0 */</span><br><span style="color: hsl(120, 100%, 40%);">+       msgb_put_u8(tpdu, (pars_dec->fi << 4 | pars_dec->di));</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_put_u8(tpdu, 0xff ^ (1 << 4) ^ (pars_dec->fi << 4 | pars_dec->di));</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%);">+        LOGPCS(cs, LOGL_DEBUG, "scheduling PPS transfer: %s\n", msgb_hexdump(tpdu));</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_PPS_CMD, tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* continues in iso_fsm_clot_user_cb once response/error/timeout is received */</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h</span><br><span>index 5e397ab..9c93b7e 100644</span><br><span>--- a/ccid_common/cuart.h</span><br><span>+++ b/ccid_common/cuart.h</span><br><span>@@ -25,8 +25,10 @@</span><br><span>     CUART_CTL_RX,           /* enable/disable receiver */</span><br><span>        CUART_CTL_POWER,        /* enable/disable ICC power */</span><br><span>       CUART_CTL_CLOCK,        /* enable/disable ICC clock */</span><br><span style="color: hsl(120, 100%, 40%);">+        CUART_CTL_CLOCK_FREQ, /* set ICC clock frequency (hz)*/</span><br><span>      CUART_CTL_RST,          /* enable/disable ICC reset */</span><br><span>       CUART_CTL_WTIME,        /* set the waiting time (in etu) */</span><br><span style="color: hsl(120, 100%, 40%);">+   CUART_CTL_FD,</span><br><span> };</span><br><span> </span><br><span> struct card_uart;</span><br><span>@@ -74,6 +76,7 @@</span><br><span>     uint32_t wtime_etu;</span><br><span>  struct osmo_timer_list wtime_tmr;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* driver-specific private data */</span><br><span>   union {</span><br><span>              struct {</span><br><span>@@ -95,6 +98,8 @@</span><br><span>                 struct {</span><br><span>                     struct usart_async_descriptor *usa_pd;</span><br><span>                       uint8_t slot_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* in us, required, no delay breaks _rx_ */</span><br><span style="color: hsl(120, 100%, 40%);">+                   uint32_t extrawait_after_rx;</span><br><span>                 } asf4;</span><br><span>      } u;</span><br><span> };</span><br><span>diff --git a/sysmoOCTSIM/iso7816_3.c b/ccid_common/iso7816_3.c</span><br><span>similarity index 100%</span><br><span>rename from sysmoOCTSIM/iso7816_3.c</span><br><span>rename to ccid_common/iso7816_3.c</span><br><span>diff --git a/sysmoOCTSIM/iso7816_3.h b/ccid_common/iso7816_3.h</span><br><span>similarity index 100%</span><br><span>rename from sysmoOCTSIM/iso7816_3.h</span><br><span>rename to ccid_common/iso7816_3.h</span><br><span>diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c</span><br><span>index beda7ab..c675ece 100644</span><br><span>--- a/ccid_common/iso7816_fsm.c</span><br><span>+++ b/ccid_common/iso7816_fsm.c</span><br><span>@@ -69,6 +69,7 @@</span><br><span>  *  @note defined in ISO/IEC 7816-3:2006(E) section 9</span><br><span>  */</span><br><span> enum pps_state {</span><br><span style="color: hsl(120, 100%, 40%);">+     PPS_S_TX_PPS_REQ,  /*!< tx pps request */</span><br><span>         PPS_S_WAIT_PPSS, /*!< initial byte */</span><br><span>     PPS_S_WAIT_PPS0, /*!< format byte */</span><br><span>      PPS_S_WAIT_PPS1, /*!< first parameter byte */</span><br><span>@@ -221,7 +222,7 @@</span><br><span> </span><br><span>   /* go back to initial state in child FSMs */</span><br><span>         osmo_fsm_inst_state_chg(ip->atr_fi, ATR_S_WAIT_TS, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-    //osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_WAIT_PPSS, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0);</span><br><span>      osmo_fsm_inst_state_chg(ip->tpdu_fi, TPDU_S_INIT, 0, 0);</span><br><span> }</span><br><span> </span><br><span>@@ -311,6 +312,12 @@</span><br><span>          /* pass on to sub-fsm */</span><br><span>             osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data);</span><br><span>                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_XCEIVE_PPS_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+//              osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_REQ, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_fsm_inst_dispatch(ip->pps_fi, event, data);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>      }</span><br><span>@@ -369,6 +376,65 @@</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void iso7816_3_in_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct iso7816_3_priv *tfp = get_iso7816_3_priv(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+//        struct osmo_fsm_inst *parent_fi = fi->proc.parent;</span><br><span style="color: hsl(120, 100%, 40%);">+//       struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case ISO7816_E_XCEIVE_PPS_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+//          card_uart_tx(tfp->uart, msgb_data(data), msgb_length(data), true);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+static void iso7816_3_s_wait_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case ISO7816_E_TX_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Rx of single byte is already enabled by previous card_uart_tx() call */</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_RSP, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+static void iso7816_3_s_ins_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct msgb *ppsrsp;</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case ISO7816_E_RX_SINGLE:</span><br><span style="color: hsl(120, 100%, 40%);">+     case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(120, 100%, 40%);">+             /* simply pass this through to the child FSM for the ATR */</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_fsm_inst_dispatch(ip->pps_fi, event, data);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_DONE_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+  case ISO7816_E_PPS_FAILED_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+                ppsrsp = data;</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               /* notify user about PPS result */</span><br><span style="color: hsl(120, 100%, 40%);">+            ip->user_cb(fi, event, 0, ppsrsp);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_RX_ERR_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+            ppsrsp = data;</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           ip->user_cb(fi, event, 0, ppsrsp);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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> static const struct osmo_fsm_state iso7816_3_states[] = {</span><br><span>  [ISO7816_S_RESET] = {</span><br><span>                .name = "RESET",</span><br><span>@@ -400,11 +466,13 @@</span><br><span>   },</span><br><span>   [ISO7816_S_WAIT_TPDU] = {</span><br><span>            .name = "WAIT_TPDU",</span><br><span style="color: hsl(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_XCEIVE_TPDU_CMD),</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask =        S(ISO7816_E_XCEIVE_TPDU_CMD) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        S(ISO7816_E_XCEIVE_PPS_CMD),</span><br><span>                 .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_WAIT_TPDU) |</span><br><span>                                     S(ISO7816_S_IN_TPDU) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                  S(ISO7816_S_IN_PPS_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+                                      S(ISO7816_S_IN_PPS_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                     S(ISO7816_S_WAIT_PPS_RSP),</span><br><span>           .action = iso7816_3_wait_tpdu_action,</span><br><span>                .onenter = iso7816_3_wait_tpdu_onenter,</span><br><span>      },</span><br><span>@@ -424,26 +492,36 @@</span><br><span>   },</span><br><span>   [ISO7816_S_IN_PPS_REQ] = {</span><br><span>           .name = "IN_PPS_REQ",</span><br><span style="color: hsl(0, 100%, 40%);">-         .in_event_mask =        0, /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_XCEIVE_TPDU_CMD),</span><br><span>                .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_WAIT_TPDU) |</span><br><span>                                     S(ISO7816_S_IN_PPS_REQ) |</span><br><span>                                    S(ISO7816_S_WAIT_PPS_RSP),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = iso7816_3_in_pps_req_action,</span><br><span>       },</span><br><span>   [ISO7816_S_WAIT_PPS_RSP] = {</span><br><span>                 .name = "WAIT_PPS_RESP",</span><br><span style="color: hsl(0, 100%, 40%);">-              .in_event_mask =        0, /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_TX_COMPL) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                       S(ISO7816_E_TX_ERR_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                     S(ISO7816_E_WTIME_EXP),</span><br><span>              .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_WAIT_TPDU) |</span><br><span>                                     S(ISO7816_S_WAIT_PPS_RSP) |</span><br><span>                                  S(ISO7816_S_IN_PPS_RSP),</span><br><span style="color: hsl(120, 100%, 40%);">+              .action = iso7816_3_s_wait_pps_rsp_action,</span><br><span>   },</span><br><span>   [ISO7816_S_IN_PPS_RSP] = {</span><br><span>           .name = "IN_PPS_RESP",</span><br><span style="color: hsl(0, 100%, 40%);">-                .in_event_mask =        0, /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                      S(ISO7816_E_RX_COMPL) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                       S(ISO7816_E_RX_ERR_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                     S(ISO7816_E_PPS_DONE_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                   S(ISO7816_E_PPS_FAILED_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                 S(ISO7816_E_WTIME_EXP),</span><br><span>              .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_WAIT_TPDU) |</span><br><span>                                     S(ISO7816_S_IN_PPS_RSP),</span><br><span style="color: hsl(120, 100%, 40%);">+              .action = iso7816_3_s_ins_pps_rsp_action,</span><br><span>    },</span><br><span> };</span><br><span> static struct osmo_fsm iso7816_3_fsm = {</span><br><span>@@ -796,28 +874,188 @@</span><br><span> /***********************************************************************</span><br><span>  * PPS FSM</span><br><span>  ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+struct pps_fsm_priv {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct msgb* tx_cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct msgb* rx_cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t pps0_recv;</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 pps_s_wait_ppss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct pps_fsm_priv *atp = fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!atp->rx_cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+          atp->rx_cmd = msgb_alloc_c(fi, 6, "ATR"); /* TS + 32 chars */</span><br><span style="color: hsl(120, 100%, 40%);">+    else</span><br><span style="color: hsl(120, 100%, 40%);">+          msgb_reset(atp->rx_cmd);</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 pps_s_tx_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct pps_fsm_priv *atp = fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+       atp->tx_cmd = data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_fsm_inst *parent_fi = fi->proc.parent;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case ISO7816_E_XCEIVE_PPS_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPSS, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           card_uart_tx(ip->uart, msgb_data(data), msgb_length(data), true);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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%);">+static void pps_wait_pX_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct pps_fsm_priv *atp = fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+//     uint32_t guard_time_ms = atr_fi_gt_ms(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t byte;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case ISO7816_E_RX_SINGLE:</span><br><span style="color: hsl(120, 100%, 40%);">+             byte = get_rx_byte_evt(fi->proc.parent, data);</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_put_u8(atp->rx_cmd, byte);</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (fi->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+               case PPS_S_WAIT_PPSS:</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (byte == 0xff)</span><br><span style="color: hsl(120, 100%, 40%);">+                             osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS0, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PPS_S_WAIT_PPS0:</span><br><span style="color: hsl(120, 100%, 40%);">+                 atp->pps0_recv = byte;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if(atp->pps0_recv & (1 << 4)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS1, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                           break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        } else if (atp->pps0_recv & (1 << 5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                           break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        } else if (atp->pps0_recv & (1 << 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);</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%);">+                     osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PPS_S_WAIT_PPS1:</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (atp->pps0_recv & (1 << 5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                           break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        } else if (atp->pps0_recv & (1 << 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);</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%);">+                     osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PPS_S_WAIT_PPS2:</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (atp->pps0_recv & (1 << 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);</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%);">+                     osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PPS_S_WAIT_PPS3:</span><br><span style="color: hsl(120, 100%, 40%);">+                 osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PPS_S_WAIT_PCK:</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* verify checksum if present */</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (fi->state == PPS_S_WAIT_PCK) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         uint8_t *pps_received = msgb_data(atp->rx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                            uint8_t *pps_sent = msgb_data(atp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                              osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_END, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                          /* pps was successful if response equals request</span><br><span style="color: hsl(120, 100%, 40%);">+                               * rx buffer stays with the fsm, tx buffer gets handed back and freed</span><br><span style="color: hsl(120, 100%, 40%);">+                          * by the cb */</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (msgb_length(atp->rx_cmd) == msgb_length(atp->tx_cmd) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                                     !memcmp(pps_received, pps_sent, msgb_length(atp->rx_cmd))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       osmo_fsm_inst_dispatch(fi->proc.parent,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    ISO7816_E_PPS_DONE_IND, atp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      osmo_fsm_inst_dispatch(fi->proc.parent,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    ISO7816_E_PPS_FAILED_IND, atp->tx_cmd);</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%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_ASSERT(0);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(120, 100%, 40%);">+             /* FIXME: timeout handling if no pps supported ? */</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_RX_ERR_IND, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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> </span><br><span> static const struct osmo_fsm_state pps_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     [PPS_S_TX_PPS_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .name = "TX_PPS_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_XCEIVE_PPS_CMD) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_TX_PPS_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 S(PPS_S_WAIT_PPSS),</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = pps_s_tx_pps_req_action,</span><br><span style="color: hsl(120, 100%, 40%);">+            .onenter = pps_s_wait_ppss_onenter,</span><br><span style="color: hsl(120, 100%, 40%);">+   },</span><br><span>   [PPS_S_WAIT_PPSS] = {</span><br><span>                .name = "WAIT_PPSS",</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_PPS0) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PPSS),</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_PPS0] = {</span><br><span>                .name = "WAIT_PPS0",</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_PPS1) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PPS2) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_PPS1] = {</span><br><span>                .name = "WAIT_PPS1",</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_PPS2) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_PPS2] = {</span><br><span>                .name = "WAIT_PPS2",</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_PPS3] = {</span><br><span>                .name = "WAIT_PPS3",</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_PCK] = {</span><br><span>                 .name = "WAIT_PCK",</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask =       S(PPS_S_WAIT_END),</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_WAIT_END] = {</span><br><span>                 .name = "WAIT_END",</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask =        0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask =       S(PPS_S_TX_PPS_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 S(PPS_S_WAIT_PPSS),</span><br><span>  },</span><br><span> };</span><br><span> </span><br><span>@@ -1223,7 +1461,7 @@</span><br><span>         if (!ip->tpdu_fi->priv)</span><br><span>                goto out_tpdu;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+#if 1</span><br><span>       ip->pps_fi = osmo_fsm_inst_alloc_child(&pps_fsm, fi, ISO7816_E_SW_ERR_IND);</span><br><span>   if (!ip->pps_fi)</span><br><span>          goto out_tpdu;</span><br><span>@@ -1237,7 +1475,7 @@</span><br><span> </span><br><span>   return fi;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+#if 1</span><br><span> out_pps:</span><br><span>       osmo_fsm_inst_free(ip->pps_fi);</span><br><span> #endif</span><br><span>diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h</span><br><span>index f2c7483..f512709 100644</span><br><span>--- a/ccid_common/iso7816_fsm.h</span><br><span>+++ b/ccid_common/iso7816_fsm.h</span><br><span>@@ -21,6 +21,9 @@</span><br><span>    ISO7816_E_RESET_ACT_IND,        /*!< Reset activated */</span><br><span>   ISO7816_E_ABORT_REQ,            /*!< Abort request (e.g. from CCID) */</span><br><span>    /* TODO: PPS request */</span><br><span style="color: hsl(120, 100%, 40%);">+       ISO7816_E_XCEIVE_PPS_CMD,</span><br><span style="color: hsl(120, 100%, 40%);">+     ISO7816_E_PPS_DONE_IND,</span><br><span style="color: hsl(120, 100%, 40%);">+       ISO7816_E_PPS_FAILED_IND,</span><br><span>    /* TODO: Clock stop request */</span><br><span>       /* TODO: Rx FIFO overrun */</span><br><span>  /* TODO: Rx buffer overrun */</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 f9856f3..a8f8044 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>@@ -289,6 +289,8 @@</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%);">+       /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/</span><br><span style="color: hsl(120, 100%, 40%);">+  cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);</span><br><span> </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>@@ -338,6 +340,8 @@</span><br><span>         return io_read(&usa_pd->io, data, len);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "ccid_device.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "iso7816_3.h"</span><br><span> static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg)</span><br><span> {</span><br><span>   struct ncn8025_settings settings;</span><br><span>@@ -349,7 +353,7 @@</span><br><span>                      sercom->USART.CTRLB.bit.RXEN = 1;</span><br><span>                         sercom->USART.CTRLB.bit.TXEN = 0;</span><br><span>                 } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        delay_us(100);</span><br><span style="color: hsl(120, 100%, 40%);">+                        delay_us(cuart->u.asf4.extrawait_after_rx);</span><br><span>                       sercom->USART.CTRLB.bit.RXEN = 0;</span><br><span>                         sercom->USART.CTRLB.bit.TXEN = 1;</span><br><span>                 }</span><br><span>@@ -361,22 +365,47 @@</span><br><span>            usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd);</span><br><span>                break;</span><br><span>       case CUART_CTL_POWER:</span><br><span style="color: hsl(0, 100%, 40%);">-           ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(0, 100%, 40%);">-           settings.cmdvcc = arg ? true : false;</span><br><span style="color: hsl(0, 100%, 40%);">-           settings.led = arg ? true : false;</span><br><span style="color: hsl(0, 100%, 40%);">-              settings.vsel = SIM_VOLT_5V0;</span><br><span style="color: hsl(120, 100%, 40%);">+         /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/</span><br><span style="color: hsl(120, 100%, 40%);">+          cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);</span><br><span> </span><br><span>            // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span>             if(arg)</span><br><span>                      slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+             ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+         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>                ncn8025_set(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              break;</span><br><span>       case CUART_CTL_WTIME:</span><br><span>                /* no driver-specific handling of this */</span><br><span>            break;</span><br><span>       case CUART_CTL_CLOCK:</span><br><span style="color: hsl(0, 100%, 40%);">-           /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+           /* no clock stop support */</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case CUART_CTL_CLOCK_FREQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* 2,5/5/10/20 supported by dividers */</span><br><span style="color: hsl(120, 100%, 40%);">+               enum ncn8025_sim_clkdiv clkdiv = SIM_CLKDIV_1;</span><br><span style="color: hsl(120, 100%, 40%);">+                if(arg < 20000000)</span><br><span style="color: hsl(120, 100%, 40%);">+                 clkdiv = SIM_CLKDIV_2;</span><br><span style="color: hsl(120, 100%, 40%);">+                if(arg < 10000000)</span><br><span style="color: hsl(120, 100%, 40%);">+                 clkdiv = SIM_CLKDIV_4;</span><br><span style="color: hsl(120, 100%, 40%);">+                if(arg < 5000000)</span><br><span style="color: hsl(120, 100%, 40%);">+                  clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(120, 100%, 40%);">+                settings.clkdiv = clkdiv;</span><br><span style="color: hsl(120, 100%, 40%);">+             ncn8025_set(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case CUART_CTL_FD:</span><br><span style="color: hsl(120, 100%, 40%);">+            ncn8025_get(cuart->u.asf4.slot_nr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+         uint8_t divider = ncn8025_div_val[settings.clkdiv];</span><br><span style="color: hsl(120, 100%, 40%);">+           uint32_t baudrate = (20e6/divider)/arg;</span><br><span style="color: hsl(120, 100%, 40%);">+               cuart->u.asf4.extrawait_after_rx = 1./baudrate * 1000 * 1000;</span><br><span style="color: hsl(120, 100%, 40%);">+              slot_set_baudrate(cuart->u.asf4.slot_nr, baudrate);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span>       default:</span><br><span>             return -EINVAL;</span><br><span>      }</span><br><span>diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile</span><br><span>index 9873159..41f5d10 100644</span><br><span>--- a/sysmoOCTSIM/gcc/Makefile</span><br><span>+++ b/sysmoOCTSIM/gcc/Makefile</span><br><span>@@ -84,6 +84,7 @@</span><br><span>   ccid_common/ccid_proto.o \</span><br><span>   ccid_common/ccid_device.o \</span><br><span>  ccid_common/iso7816_fsm.o \</span><br><span style="color: hsl(120, 100%, 40%);">+   ccid_common/iso7816_3.o \</span><br><span>    ccid_common/cuart.o \</span><br><span>        ccid_common/ccid_slot_fsm.o \</span><br><span>        cuart_driver_asf4_usart_async.o \</span><br><span>@@ -123,7 +124,6 @@</span><br><span>      hpl/sercom/hpl_sercom.o \</span><br><span>    hpl/usb/hpl_usb.o \</span><br><span>  i2c_bitbang.o \</span><br><span style="color: hsl(0, 100%, 40%);">- iso7816_3.o \</span><br><span>        libosmo_emb.o \</span><br><span>      main.o \</span><br><span>     manual_test.o \</span><br><span>diff --git a/sysmoOCTSIM/ncn8025.c b/sysmoOCTSIM/ncn8025.c</span><br><span>index 540b166..74d3b39 100644</span><br><span>--- a/sysmoOCTSIM/ncn8025.c</span><br><span>+++ b/sysmoOCTSIM/ncn8025.c</span><br><span>@@ -159,7 +159,7 @@</span><br><span>       [SIM_VOLT_1V8] = "1.8",</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const unsigned int div_val[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+const unsigned int ncn8025_div_val[] = {</span><br><span>         [SIM_CLKDIV_1] = 1,</span><br><span>  [SIM_CLKDIV_2] = 2,</span><br><span>  [SIM_CLKDIV_4] = 4,</span><br><span>@@ -168,7 +168,7 @@</span><br><span> </span><br><span> void ncn8025_dump(const struct ncn8025_settings *set)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], div_val[set->clkdiv]);</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], ncn8025_div_val[set->clkdiv]);</span><br><span>     if (set->rstin)</span><br><span>           printf(", RST");</span><br><span>   if (set->cmdvcc)</span><br><span>diff --git a/sysmoOCTSIM/ncn8025.h b/sysmoOCTSIM/ncn8025.h</span><br><span>index 2e774a7..01ddc97 100644</span><br><span>--- a/sysmoOCTSIM/ncn8025.h</span><br><span>+++ b/sysmoOCTSIM/ncn8025.h</span><br><span>@@ -14,6 +14,8 @@</span><br><span>     SIM_CLKDIV_8 = 0,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+extern const unsigned int ncn8025_div_val[];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ncn8025_settings {</span><br><span>     bool rstin;     /* Reset signal (true: asserted low) */</span><br><span>      bool cmdvcc;    /* Command VCC pin. Activation sequence Enable (true: active low) */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16237">change 16237</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/+/16237"/><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: I2e226b0033f8a147fad60a33a63cc45ee9adc756 </div>
<div style="display:none"> Gerrit-Change-Number: 16237 </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>