<p>Hoernchen has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/21071">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">7816 fsm: move to static msgb<br><br>Error handling was difficult due to the need to pass msgb pointers<br>attached to the sub fsms back to the cb that is polled from the main<br>loop to be able free them, while ensuring they never get lost, because<br>memory leakage is deadly.<br><br>This is now fixed by using static pseudo-msgbs for the fsms that are<br>never deallocated. This only adds one tpdu tx copy, the ccid response<br>msgbs were already being copied anyway, so memory usage has not changed<br>except for the "unused slots" case that is not really important since<br>the octsim was designed around concurrent slot operation anway.<br><br>All of this allows convenient error handling in the allstate function<br>instead of having to spread it all over the sub fsms - in practice<br>handling errors mostly consists of card deactivation + returning a<br>proper failure message that matches the ccid command anyway.<br><br>Change-Id: I65e77c376aca9ed50e234a0b58a7450a8bbd4fe0<br>---<br>M ccid_common/ccid_slot_fsm.c<br>M ccid_common/iso7816_fsm.c<br>M ccid_common/iso7816_fsm.h<br>3 files changed, 216 insertions(+), 151 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/71/21071/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 043fa8f..5fc74e0 100644</span><br><span>--- a/ccid_common/ccid_slot_fsm.c</span><br><span>+++ b/ccid_common/ccid_slot_fsm.c</span><br><span>@@ -159,6 +159,7 @@</span><br><span>    case ISO7816_E_TPDU_FAILED_IND:</span><br><span>      case ISO7816_E_PPS_DONE_IND:</span><br><span>         case ISO7816_E_PPS_FAILED_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_UNSUPPORTED_IND:</span><br><span>  case ISO7816_E_WTIME_EXP:</span><br><span>            cs->event_data = data;</span><br><span> #ifdef OCTSIMFWBUILD</span><br><span>@@ -173,6 +174,7 @@</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* do not free msgbs passed from the fsms, they are statically allocated! */</span><br><span> static int iso_handle_fsm_events(struct ccid_slot *cs, bool enable){</span><br><span>     struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);</span><br><span>        struct msgb *tpdu, *resp;</span><br><span>@@ -207,7 +209,6 @@</span><br><span>              resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,</span><br><span>                                       msgb_data(tpdu), msgb_length(tpdu));</span><br><span>              ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-                /* Don't free "TPDU" here, as the ATR should survive */</span><br><span>                cs->event = 0;</span><br><span>            break;</span><br><span>       case ISO7816_E_ATR_ERR_IND:</span><br><span>@@ -217,7 +218,6 @@</span><br><span>            resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE,</span><br><span>                                           msgb_data(tpdu), msgb_length(tpdu));</span><br><span>              ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-                /* Don't free "TPDU" here, as the ATR should survive */</span><br><span>                cs->event = 0;</span><br><span>            break;</span><br><span>               break;</span><br><span>@@ -227,7 +227,6 @@</span><br><span>                         msgb_hexdump(tpdu));</span><br><span>                 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_l4(tpdu), msgb_l4len(tpdu));</span><br><span>          ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-                msgb_free(tpdu);</span><br><span>             cs->event = 0;</span><br><span>            break;</span><br><span>       case ISO7816_E_TPDU_FAILED_IND:</span><br><span>@@ -237,7 +236,6 @@</span><br><span>                /* FIXME: other error causes than card removal?*/</span><br><span>            resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, msgb_l2(tpdu), 0);</span><br><span>             ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-                msgb_free(tpdu);</span><br><span>             cs->event = 0;</span><br><span>            break;</span><br><span>       case ISO7816_E_PPS_DONE_IND:</span><br><span>@@ -264,17 +262,34 @@</span><br><span> </span><br><span>             ccid_slot_send_unbusy(cs, resp);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */</span><br><span style="color: hsl(0, 100%, 40%);">-              msgb_free(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+              cs->event = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_UNSUPPORTED_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+           tpdu = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* perform deactivation */</span><br><span style="color: hsl(120, 100%, 40%);">+            card_uart_ctrl(ss->cuart, CUART_CTL_RST, true);</span><br><span style="color: hsl(120, 100%, 40%);">+            card_uart_ctrl(ss->cuart, CUART_CTL_POWER_5V0, false);</span><br><span style="color: hsl(120, 100%, 40%);">+             cs->icc_powered = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* failed comand */</span><br><span style="color: hsl(120, 100%, 40%);">+           resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_FAILED, 0);</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>           cs->event = 0;</span><br><span>            break;</span><br><span>       case ISO7816_E_PPS_FAILED_IND:</span><br><span>               tpdu = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* perform deactivation */</span><br><span style="color: hsl(120, 100%, 40%);">+            card_uart_ctrl(ss->cuart, CUART_CTL_RST, true);</span><br><span style="color: hsl(120, 100%, 40%);">+            card_uart_ctrl(ss->cuart, CUART_CTL_POWER_5V0, false);</span><br><span style="color: hsl(120, 100%, 40%);">+             cs->icc_powered = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                /* failed fi/di */</span><br><span>           resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_FAILED, 10);</span><br><span>           ccid_slot_send_unbusy(cs, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-                /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */</span><br><span style="color: hsl(0, 100%, 40%);">-              msgb_free(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>           cs->event = 0;</span><br><span>            break;</span><br><span>       case 0:</span><br><span>@@ -310,6 +325,7 @@</span><br><span> </span><br><span>    LOGPCS(cs, LOGL_DEBUG, "scheduling TPDU transfer: %s\n", msgb_hexdump(msg));</span><br><span>       osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_TPDU_CMD, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_free(msg);</span><br><span>      /* continues in iso_fsm_clot_user_cb once response/error/timeout is received */</span><br><span>      return 1;</span><br><span> }</span><br><span>@@ -348,7 +364,7 @@</span><br><span>                                 const struct ccid_pars_decoded *pars_dec)</span><br><span> {</span><br><span>       struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);</span><br><span style="color: hsl(0, 100%, 40%);">-   struct msgb *tpdu;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t PPS1 = (pars_dec->fi << 4 | pars_dec->di);</span><br><span> </span><br><span>   /* see 6.1.7 for error offsets */</span><br><span>    if(proto != CCID_PROTOCOL_NUM_T0)</span><br><span>@@ -370,17 +386,10 @@</span><br><span>        -> we can't really do 4 stop bits?!</span><br><span>       */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Hardware does not support SPU, so no PPS2, and PPS3 is reserved anyway */</span><br><span style="color: hsl(0, 100%, 40%);">-    tpdu = msgb_alloc(6, "PPSRQ");</span><br><span style="color: hsl(0, 100%, 40%);">-        OSMO_ASSERT(tpdu);</span><br><span style="color: hsl(0, 100%, 40%);">-      msgb_put_u8(tpdu, 0xff);</span><br><span style="color: hsl(0, 100%, 40%);">-        msgb_put_u8(tpdu, (1 << 4)); /* only PPS1, T=0 */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_put_u8(tpdu, (pars_dec->fi << 4 | pars_dec->di));</span><br><span style="color: hsl(0, 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%);">+    LOGPCS(cs, LOGL_DEBUG, "scheduling PPS transfer, PPS1: %2x\n", PPS1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     LOGPCS(cs, LOGL_DEBUG, "scheduling PPS transfer: %s\n", msgb_hexdump(tpdu));</span><br><span style="color: hsl(0, 100%, 40%);">-  osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_PPS_CMD, tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* pass PPS1 instead of msgb */</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_PPS_CMD, PPS1);</span><br><span>   /* continues in iso_fsm_clot_user_cb once response/error/timeout is received */</span><br><span>      return 0;</span><br><span> }</span><br><span>diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c</span><br><span>index bf19539..66250d5 100644</span><br><span>--- a/ccid_common/iso7816_fsm.c</span><br><span>+++ b/ccid_common/iso7816_fsm.c</span><br><span>@@ -33,6 +33,47 @@</span><br><span> #include "cuart.h"</span><br><span> #include "iso7816_fsm.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* unionize to ensure at least properly aligned msgb struct */</span><br><span style="color: hsl(120, 100%, 40%);">+#define DECLARE_STATIC_MSGB(name, size) \</span><br><span style="color: hsl(120, 100%, 40%);">+     struct msgb* name; \</span><br><span style="color: hsl(120, 100%, 40%);">+  union { \</span><br><span style="color: hsl(120, 100%, 40%);">+     struct msgb name ## dummy; \</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char name ## _msgbuf[sizeof(struct msgb) + size]; \</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 INIT_STATIC_MSGB(name) { \</span><br><span style="color: hsl(120, 100%, 40%);">+      name = (struct msgb*)name ## _msgbuf; \</span><br><span style="color: hsl(120, 100%, 40%);">+       memset(name, 0x00, sizeof(name ## _msgbuf)); \</span><br><span style="color: hsl(120, 100%, 40%);">+        name->data_len = sizeof(name ## _msgbuf) - sizeof(struct msgb); \</span><br><span style="color: hsl(120, 100%, 40%);">+  name->len = 0; \</span><br><span style="color: hsl(120, 100%, 40%);">+   name->data = name->_data; \</span><br><span style="color: hsl(120, 100%, 40%);">+     name->head = name->_data; \</span><br><span style="color: hsl(120, 100%, 40%);">+     name->tail = name->_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%);">+#define COPY_TO_STATIC_MSGB(src, dst) { \</span><br><span style="color: hsl(120, 100%, 40%);">+     struct msgb *new_msg = dst; \</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = src; \</span><br><span style="color: hsl(120, 100%, 40%);">+      \</span><br><span style="color: hsl(120, 100%, 40%);">+    /* copy data */ \</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(new_msg->_data, msg->_data, new_msg->data_len); \</span><br><span style="color: hsl(120, 100%, 40%);">+      \</span><br><span style="color: hsl(120, 100%, 40%);">+    /* copy header */ \</span><br><span style="color: hsl(120, 100%, 40%);">+   new_msg->len = msg->len; \</span><br><span style="color: hsl(120, 100%, 40%);">+      new_msg->data += msg->data - msg->_data; \</span><br><span style="color: hsl(120, 100%, 40%);">+   new_msg->head += msg->head - msg->_data; \</span><br><span style="color: hsl(120, 100%, 40%);">+   new_msg->tail += msg->tail - msg->_data; \</span><br><span style="color: hsl(120, 100%, 40%);">+    \</span><br><span style="color: hsl(120, 100%, 40%);">+    if (msg->l1h) \</span><br><span style="color: hsl(120, 100%, 40%);">+            new_msg->l1h = new_msg->_data + (msg->l1h - msg->_data); \</span><br><span style="color: hsl(120, 100%, 40%);">+        if (msg->l2h) \</span><br><span style="color: hsl(120, 100%, 40%);">+            new_msg->l2h = new_msg->_data + (msg->l2h - msg->_data); \</span><br><span style="color: hsl(120, 100%, 40%);">+        if (msg->l3h) \</span><br><span style="color: hsl(120, 100%, 40%);">+            new_msg->l3h = new_msg->_data + (msg->l3h - msg->_data); \</span><br><span style="color: hsl(120, 100%, 40%);">+        if (msg->l4h) \</span><br><span style="color: hsl(120, 100%, 40%);">+            new_msg->l4h = new_msg->_data + (msg->l4h - msg->_data); \</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Section 8.2: the Answer-to-Reset (... a string of at most 32 bytes) */</span><br><span> #define MAX_ATR_SIZE 32</span><br><span> </span><br><span>@@ -132,12 +173,25 @@</span><br><span>      uint8_t hist_len;       /*!< store the number of expected historical bytes */</span><br><span>     uint8_t y;              /*!< last mask of the upcoming TA, TB, TC, TD interface bytes */</span><br><span>  uint8_t i;              /*!< interface byte subgroup number */</span><br><span style="color: hsl(0, 100%, 40%);">-       struct msgb *atr;       /*!< ATR data */</span><br><span style="color: hsl(120, 100%, 40%);">+   DECLARE_STATIC_MSGB(atr, 33) /*!< ATR data */</span><br><span>     uint8_t computed_checksum;</span><br><span>   uint16_t protocol_support;</span><br><span> };</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%);">+   DECLARE_STATIC_MSGB(tx_cmd, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+       DECLARE_STATIC_MSGB(rx_cmd, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t pps0_recv; /*!< contains flags so we know how many pps bytes follow */</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 tpdu_fsm_priv {</span><br><span style="color: hsl(120, 100%, 40%);">+       DECLARE_STATIC_MSGB(tpdu, 300);</span><br><span style="color: hsl(120, 100%, 40%);">+       bool is_command; /* is this a command TPDU (true) or a response (false) */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct atr_fsm_priv *get_atr_fsm_priv(struct osmo_fsm_inst *fi);</span><br><span style="color: hsl(120, 100%, 40%);">+static struct pps_fsm_priv *get_pps_fsm_priv(struct osmo_fsm_inst *fi);</span><br><span style="color: hsl(120, 100%, 40%);">+static struct tpdu_fsm_priv *get_tpdu_fsm_priv(struct osmo_fsm_inst *fi);</span><br><span> </span><br><span> /***********************************************************************</span><br><span>  * ISO7816-3 Main FSM</span><br><span>@@ -257,6 +311,7 @@</span><br><span>               break;</span><br><span>       case ISO7816_E_POWER_UP_IND:</span><br><span>                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_UNSUPPORTED_IND:</span><br><span>  case ISO7816_E_PPS_FAILED_IND:</span><br><span>               msg = data;</span><br><span>          /* notify user about PPS result */</span><br><span>@@ -285,10 +340,6 @@</span><br><span>            osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_ATR, 0, 0);</span><br><span>                 osmo_fsm_inst_dispatch(ip->atr_fi, event, data);</span><br><span>          break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(0, 100%, 40%);">-               ip->user_cb(fi, event, 0, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-             osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-             break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>      }</span><br><span>@@ -297,26 +348,18 @@</span><br><span> static void iso7816_3_in_atr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>  struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-     struct msgb *atr;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct msgb *atr = data;</span><br><span>     OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);</span><br><span> </span><br><span>   switch (event) {</span><br><span>     case ISO7816_E_RX_SINGLE:</span><br><span>    case ISO7816_E_RX_ERR_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-      case ISO7816_E_WTIME_EXP:</span><br><span>            /* simply pass this through to the child FSM for the ATR */</span><br><span>          osmo_fsm_inst_dispatch(ip->atr_fi, event, data);</span><br><span>          break;</span><br><span>       case ISO7816_E_ATR_DONE_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-            atr = data;</span><br><span>          /* FIXME: verify ATR result: success / failure */</span><br><span>            osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-         /* notify user about ATR */</span><br><span style="color: hsl(0, 100%, 40%);">-             ip->user_cb(fi, event, 0, atr);</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case ISO7816_E_ATR_ERR_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-             atr = data;</span><br><span style="color: hsl(0, 100%, 40%);">-             osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span>          ip->user_cb(fi, event, 0, atr);</span><br><span>           break;</span><br><span>       default:</span><br><span>@@ -368,7 +411,7 @@</span><br><span>       case ISO7816_E_RX_ERR_IND:</span><br><span>   case ISO7816_E_TX_COMPL:</span><br><span>     case ISO7816_E_TX_ERR_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-              /* simply pass this through to the child FSM for the ATR */</span><br><span style="color: hsl(120, 100%, 40%);">+           /* simply pass this through to the child FSM for the TPDU */</span><br><span>                 osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data);</span><br><span>                 break;</span><br><span>       case ISO7816_E_TPDU_DONE_IND:</span><br><span>@@ -377,10 +420,6 @@</span><br><span>                 /* hand finished TPDU to user */</span><br><span>             ip->user_cb(fi, event, 0, apdu);</span><br><span>          break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(0, 100%, 40%);">-               /* FIXME: power off? */</span><br><span style="color: hsl(0, 100%, 40%);">-         osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-             break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>      }</span><br><span>@@ -391,6 +430,8 @@</span><br><span>      OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);</span><br><span>       struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);</span><br><span>  struct atr_fsm_priv *atp = get_atr_fsm_priv(ip->atr_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct pps_fsm_priv *ppp = get_pps_fsm_priv(ip->pps_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct tpdu_fsm_priv *tpdup = get_tpdu_fsm_priv(ip->tpdu_fi);</span><br><span> </span><br><span>         switch (event) {</span><br><span>     case ISO7816_E_HW_ERR_IND:</span><br><span>@@ -398,6 +439,13 @@</span><br><span>            /* FIXME: power off? */</span><br><span>              if(fi->state == ISO7816_S_WAIT_ATR || fi->state == ISO7816_S_IN_ATR)</span><br><span>                   ip->user_cb(fi, ISO7816_E_ATR_ERR_IND, 0, atp->atr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if(fi->state == ISO7816_S_WAIT_PPS_RSP || fi->state == ISO7816_S_IN_PPS_RSP)</span><br><span style="color: hsl(120, 100%, 40%);">+                    ip->user_cb(fi, ISO7816_E_PPS_FAILED_IND, 0, ppp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if(fi->state == ISO7816_S_WAIT_TPDU || fi->state == ISO7816_S_IN_TPDU)</span><br><span style="color: hsl(120, 100%, 40%);">+                  ip->user_cb(fi, ISO7816_E_TPDU_FAILED_IND, 0, tpdup->tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span>          break;</span><br><span>       case ISO7816_E_POWER_DN_IND:</span><br><span>@@ -407,6 +455,24 @@</span><br><span>  case ISO7816_E_ABORT_REQ:</span><br><span>            /* FIXME */</span><br><span>          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(120, 100%, 40%);">+             if(fi->state == ISO7816_S_WAIT_ATR || fi->state == ISO7816_S_IN_ATR) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* atr timeout instead of tck might be fine */</span><br><span style="color: hsl(120, 100%, 40%);">+                        osmo_fsm_inst_dispatch(ip->atr_fi, event, data);</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%);">+             if(fi->state == ISO7816_S_WAIT_PPS_RSP || fi->state == ISO7816_S_IN_PPS_RSP)</span><br><span style="color: hsl(120, 100%, 40%);">+                    ip->user_cb(fi, ISO7816_E_PPS_FAILED_IND, 0, ppp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if(fi->state == ISO7816_S_WAIT_TPDU || fi->state == ISO7816_S_IN_TPDU)</span><br><span style="color: hsl(120, 100%, 40%);">+                  ip->user_cb(fi, ISO7816_E_TPDU_FAILED_IND, 0, tpdup->tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_ATR_ERR_IND:</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, atp->atr);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>              break;</span><br><span>@@ -434,25 +500,28 @@</span><br><span> static void iso7816_3_s_ins_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>      struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-     struct msgb *ppsrsp;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct msgb *ppsrsp = data;</span><br><span>  OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);</span><br><span> </span><br><span>   switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* --v-- events from outside --v-- */</span><br><span>        case ISO7816_E_RX_SINGLE:</span><br><span style="color: hsl(0, 100%, 40%);">-       case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(0, 100%, 40%);">-               /* simply pass this through to the child FSM for the ATR */</span><br><span style="color: hsl(120, 100%, 40%);">+           /* simply pass this through to the child FSM for the PPS */</span><br><span>          osmo_fsm_inst_dispatch(ip->pps_fi, event, data);</span><br><span>          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* --v-- events from childf fsm --v-- */</span><br><span>     case ISO7816_E_PPS_DONE_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-    case ISO7816_E_PPS_FAILED_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-          ppsrsp = data;</span><br><span>               osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);</span><br><span>              /* notify user about PPS result */</span><br><span>           ip->user_cb(fi, event, 0, ppsrsp);</span><br><span>                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ISO7816_E_PPS_UNSUPPORTED_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+   case ISO7816_E_PPS_FAILED_IND:</span><br><span>       case ISO7816_E_RX_ERR_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-              ppsrsp = data;</span><br><span style="color: hsl(120, 100%, 40%);">+                /* error cases lead to slot reset */</span><br><span>                 osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           /* notify user about PPS result */</span><br><span>           ip->user_cb(fi, event, 0, ppsrsp);</span><br><span>                break;</span><br><span>       default:</span><br><span>@@ -466,6 +535,7 @@</span><br><span>               .in_event_mask =        S(ISO7816_E_RESET_REL_IND) |</span><br><span>                                                         S(ISO7816_E_POWER_UP_IND) |</span><br><span>                                                  S(ISO7816_E_PPS_FAILED_IND)|</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(ISO7816_E_PPS_UNSUPPORTED_IND)|</span><br><span>                                                    S(ISO7816_E_TPDU_FAILED_IND),</span><br><span>                .out_state_mask =       S(ISO7816_S_WAIT_ATR) |</span><br><span>                                      S(ISO7816_S_RESET),</span><br><span>@@ -474,8 +544,7 @@</span><br><span>    },</span><br><span>   [ISO7816_S_WAIT_ATR] = {</span><br><span>             .name = "WAIT_ATR",</span><br><span style="color: hsl(0, 100%, 40%);">-           .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_IN_ATR),</span><br><span>                 .action = iso7816_3_wait_atr_action,</span><br><span>@@ -484,9 +553,7 @@</span><br><span>           .name = "IN_ATR",</span><br><span>          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span>                                     S(ISO7816_E_RX_ERR_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                       S(ISO7816_E_ATR_DONE_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                     S(ISO7816_E_ATR_ERR_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                      S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+                                       S(ISO7816_E_ATR_DONE_IND),</span><br><span>           .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_IN_ATR) |</span><br><span>                                        S(ISO7816_S_WAIT_TPDU),</span><br><span>@@ -510,8 +577,7 @@</span><br><span>                                        S(ISO7816_E_TX_COMPL) |</span><br><span>                                      S(ISO7816_E_RX_ERR_IND) |</span><br><span>                                    S(ISO7816_E_TX_ERR_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                       S(ISO7816_E_TPDU_DONE_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                    S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+                                       S(ISO7816_E_TPDU_DONE_IND),</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>@@ -521,7 +587,6 @@</span><br><span>          .name = "WAIT_PPS_RESP",</span><br><span>           .in_event_mask =        S(ISO7816_E_TX_COMPL) |</span><br><span>                                      S(ISO7816_E_TX_ERR_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                       S(ISO7816_E_WTIME_EXP) |</span><br><span>                                     S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(ISO7816_S_RESET) |</span><br><span>                                         S(ISO7816_S_WAIT_TPDU) |</span><br><span>@@ -536,7 +601,7 @@</span><br><span>                                       S(ISO7816_E_RX_ERR_IND) |</span><br><span>                                    S(ISO7816_E_PPS_DONE_IND) |</span><br><span>                                  S(ISO7816_E_PPS_FAILED_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                   S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+                                       S(ISO7816_E_PPS_UNSUPPORTED_IND),</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>@@ -554,7 +619,9 @@</span><br><span>                               S(ISO7816_E_POWER_DN_IND) |</span><br><span>                          S(ISO7816_E_RESET_ACT_IND) |</span><br><span>                                 S(ISO7816_E_HW_ERR_IND) |</span><br><span style="color: hsl(0, 100%, 40%);">-                               S(ISO7816_E_ABORT_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+                               S(ISO7816_E_ABORT_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                              S(ISO7816_E_WTIME_EXP) |</span><br><span style="color: hsl(120, 100%, 40%);">+                              S(ISO7816_E_ATR_ERR_IND),</span><br><span> };</span><br><span> </span><br><span> /***********************************************************************</span><br><span>@@ -617,10 +684,12 @@</span><br><span>      atp->hist_len = 0;</span><br><span>        atp->y = 0;</span><br><span>       atp->i = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!atp->atr)</span><br><span style="color: hsl(0, 100%, 40%);">-               atp->atr = msgb_alloc_c(fi, 33, "ATR"); /* TS + 32 chars */</span><br><span style="color: hsl(0, 100%, 40%);">-        else</span><br><span style="color: hsl(0, 100%, 40%);">-            msgb_reset(atp->atr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* might be used by cb later, but this is fine - error means broken, no one cares about a half-received atr</span><br><span style="color: hsl(120, 100%, 40%);">+    * in the error repsonse anyway, next state after atr is wait tpdu, not reset, unless error, so we should</span><br><span style="color: hsl(120, 100%, 40%);">+      * not end up here during normal operation.</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_reset(atp->atr);</span><br><span>     atp->computed_checksum = 0;</span><br><span>       atp->protocol_support = 0;</span><br><span> }</span><br><span>@@ -764,16 +833,16 @@</span><br><span>           break;</span><br><span>       case ISO7816_E_WTIME_EXP:</span><br><span>            switch (fi->state) {</span><br><span style="color: hsl(0, 100%, 40%);">-         case ATR_S_WAIT_HIST:</span><br><span style="color: hsl(0, 100%, 40%);">-           case ATR_S_WAIT_TCK:</span><br><span style="color: hsl(0, 100%, 40%);">-                    /* Some cards have an ATR with long indication of historical bytes */</span><br><span style="color: hsl(0, 100%, 40%);">-                   /* FIXME: should we check the checksum? */</span><br><span style="color: hsl(0, 100%, 40%);">-                      osmo_fsm_inst_state_chg(fi, ATR_S_DONE, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-                  osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_DONE_IND, atp->atr);</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-          default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_ERR_IND, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case ATR_S_WAIT_HIST:</span><br><span style="color: hsl(120, 100%, 40%);">+                 case ATR_S_WAIT_TCK:</span><br><span style="color: hsl(120, 100%, 40%);">+                          /* Some cards have an ATR with long indication of historical bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+                         /* FIXME: should we check the checksum? */</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 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_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_ERR_IND, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span>               }</span><br><span>            break;</span><br><span>       default:</span><br><span>@@ -900,43 +969,41 @@</span><br><span> /***********************************************************************</span><br><span>  * PPS FSM</span><br><span>  ***********************************************************************/</span><br><span style="color: hsl(0, 100%, 40%);">-struct pps_fsm_priv {</span><br><span style="color: hsl(0, 100%, 40%);">-    struct msgb* tx_cmd;</span><br><span style="color: hsl(0, 100%, 40%);">-    struct msgb* rx_cmd;</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t pps0_recv;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void pps_s_pps_req_init_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)</span><br><span style="color: hsl(120, 100%, 40%);">+/* type-safe method to obtain pps_fsm_priv from fi */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct pps_fsm_priv *get_pps_fsm_priv(struct osmo_fsm_inst *fi)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        struct pps_fsm_priv *atp = fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!atp->rx_cmd)</span><br><span style="color: hsl(0, 100%, 40%);">-            atp->rx_cmd = msgb_alloc_c(fi, 6, "PPSRSP"); /* at most 6 */</span><br><span style="color: hsl(0, 100%, 40%);">-       else</span><br><span style="color: hsl(0, 100%, 40%);">-            msgb_reset(atp->rx_cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     /* notify in case card got pulled out */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (atp->tx_cmd && old_state != PPS_S_DONE){</span><br><span style="color: hsl(0, 100%, 40%);">-         osmo_fsm_inst_dispatch(fi->proc.parent,</span><br><span style="color: hsl(0, 100%, 40%);">-                              ISO7816_E_PPS_FAILED_IND, atp->tx_cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-              atp->tx_cmd = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(fi->fsm == &pps_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+      return (struct pps_fsm_priv *) fi->priv;</span><br><span> }</span><br><span> </span><br><span> static void pps_s_pps_req_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        struct pps_fsm_priv *atp = fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct pps_fsm_priv *atp = get_pps_fsm_priv(fi);</span><br><span>     struct osmo_fsm_inst *parent_fi = fi->proc.parent;</span><br><span>        struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb* pps_to_transmit = atp->tx_cmd;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* keep the buffer to compare it with the received response */</span><br><span style="color: hsl(0, 100%, 40%);">-  atp->tx_cmd = data;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* data passed is PPS1, not msgb ptr! */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t PPS1 = (uint8_t)data;</span><br><span> </span><br><span>    switch (event) {</span><br><span>     case ISO7816_E_XCEIVE_PPS_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              /* buf might be required for cb until we end up here */</span><br><span style="color: hsl(120, 100%, 40%);">+               msgb_reset(atp->rx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_reset(atp->tx_cmd);</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%);">+          msgb_put_u8(pps_to_transmit, 0xff);</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_put_u8(pps_to_transmit, (1 << 4)); /* only PPS1, T=0 */</span><br><span style="color: hsl(120, 100%, 40%);">+            msgb_put_u8(pps_to_transmit, PPS1);</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_put_u8(pps_to_transmit, 0xff ^ (1 << 4) ^ PPS1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                osmo_fsm_inst_state_chg(fi, PPS_S_TX_PPS_REQ, 0, 0);</span><br><span>                 card_uart_set_rx_threshold(ip->uart, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-             card_uart_tx(ip->uart, msgb_data(data), msgb_length(data), true);</span><br><span style="color: hsl(120, 100%, 40%);">+          card_uart_tx(ip->uart, msgb_data(pps_to_transmit), msgb_length(pps_to_transmit), true);</span><br><span>           break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>@@ -958,9 +1025,6 @@</span><br><span>       }</span><br><span> }</span><br><span> </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> static void pps_wait_pX_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>      struct pps_fsm_priv *atp = fi->priv;</span><br><span>@@ -1020,30 +1084,19 @@</span><br><span> </span><br><span>                                osmo_fsm_inst_state_chg(fi, PPS_S_DONE, 0, 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                              /* pps was successful if response equals request</span><br><span style="color: hsl(0, 100%, 40%);">-                                 * rx buffer stays with the fsm, tx buffer gets handed back and freed</span><br><span style="color: hsl(0, 100%, 40%);">-                            * by the cb */</span><br><span style="color: hsl(120, 100%, 40%);">+                               /* pps was successful if response equals request */</span><br><span>                          if (msgb_length(atp->rx_cmd) == msgb_length(atp->tx_cmd) &&</span><br><span>                                    !memcmp(pps_received, pps_sent, msgb_length(atp->rx_cmd))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                 osmo_fsm_inst_dispatch(fi->proc.parent,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                      ISO7816_E_PPS_DONE_IND, atp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                                      osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_PPS_DONE_IND, atp->tx_cmd);</span><br><span>                          } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                        osmo_fsm_inst_dispatch(fi->proc.parent,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                      ISO7816_E_PPS_FAILED_IND, atp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                                    osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_PPS_FAILED_IND, atp->tx_cmd);</span><br><span>                                }</span><br><span style="color: hsl(0, 100%, 40%);">-                               /* ownership transfer */</span><br><span style="color: hsl(0, 100%, 40%);">-                                atp->tx_cmd = 0;</span><br><span>                  }</span><br><span>                    break;</span><br><span>               default:</span><br><span>                     OSMO_ASSERT(0);</span><br><span>              }</span><br><span>            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case ISO7816_E_WTIME_EXP:</span><br><span style="color: hsl(0, 100%, 40%);">-               osmo_fsm_inst_state_chg(fi, PPS_S_DONE, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-          /* FIXME: timeout handling if no pps supported ? */</span><br><span style="color: hsl(0, 100%, 40%);">-             osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_RX_ERR_IND, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>      }</span><br><span>@@ -1062,12 +1115,10 @@</span><br><span> static const struct osmo_fsm_state pps_states[] = {</span><br><span>   [PPS_S_PPS_REQ_INIT] = {</span><br><span>             .name = "INIT",</span><br><span style="color: hsl(0, 100%, 40%);">-               .in_event_mask =        S(ISO7816_E_XCEIVE_PPS_CMD) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                   S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_XCEIVE_PPS_CMD),</span><br><span>                 .out_state_mask =       S(PPS_S_PPS_REQ_INIT) |</span><br><span>                                                      S(PPS_S_TX_PPS_REQ),</span><br><span>                 .action = pps_s_pps_req_init_action,</span><br><span style="color: hsl(0, 100%, 40%);">-            .onenter = pps_s_pps_req_init_onenter,</span><br><span>       },</span><br><span>   [PPS_S_TX_PPS_REQ] = {</span><br><span>               .name = "TX_PPS_REQ",</span><br><span>@@ -1077,51 +1128,57 @@</span><br><span>    },</span><br><span>   [PPS_S_WAIT_PPSX] = {</span><br><span>                .name = "WAIT_PPSS",</span><br><span style="color: hsl(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(PPS_S_WAIT_PPS0) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                    S(PPS_S_WAIT_PPSX),</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   S(PPS_S_WAIT_PPSX) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .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(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(PPS_S_WAIT_PPS1) |</span><br><span>                                                         S(PPS_S_WAIT_PPS2) |</span><br><span>                                                         S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                    S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    S(PPS_S_WAIT_PCK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .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(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(PPS_S_WAIT_PPS2) |</span><br><span>                                                         S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                    S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    S(PPS_S_WAIT_PCK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .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(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =        S(ISO7816_E_RX_SINGLE),</span><br><span>              .out_state_mask =       S(PPS_S_WAIT_PPS3) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                    S(PPS_S_WAIT_PCK),</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    S(PPS_S_WAIT_PCK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .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(0, 100%, 40%);">-          .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(0, 100%, 40%);">-         .out_state_mask =       S(PPS_S_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%);">+               .out_state_mask =       S(PPS_S_WAIT_PCK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .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(0, 100%, 40%);">-           .in_event_mask =        S(ISO7816_E_RX_SINGLE) |</span><br><span style="color: hsl(0, 100%, 40%);">-                                                        S(ISO7816_E_WTIME_EXP),</span><br><span style="color: hsl(0, 100%, 40%);">-         .out_state_mask =       S(PPS_S_DONE),</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%);">+               .out_state_mask =       S(PPS_S_DONE) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_PPS_REQ_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       S(PPS_S_DONE),</span><br><span>               .action = pps_wait_pX_action,</span><br><span>        },</span><br><span>   [PPS_S_DONE] = {</span><br><span>@@ -1158,11 +1215,6 @@</span><br><span>    return (struct osim_apdu_cmd_hdr *) msgb_data(msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct tpdu_fsm_priv {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct msgb *tpdu;</span><br><span style="color: hsl(0, 100%, 40%);">-      bool is_command; /* is this a command TPDU (true) or a response (false) */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* type-safe method to obtain iso7816_3_priv from fi */</span><br><span> static struct tpdu_fsm_priv *get_tpdu_fsm_priv(struct osmo_fsm_inst *fi)</span><br><span> {</span><br><span>@@ -1171,17 +1223,6 @@</span><br><span>    return (struct tpdu_fsm_priv *) fi->priv;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void tpdu_s_init_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* notify in case card got pulled out */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (tfp->tpdu && old_state != TPDU_S_DONE){</span><br><span style="color: hsl(0, 100%, 40%);">-          osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_FAILED_IND, tfp->tpdu);</span><br><span style="color: hsl(0, 100%, 40%);">-            tfp->tpdu = 0;</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> static void tpdu_s_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>      struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);</span><br><span>@@ -1191,8 +1232,12 @@</span><br><span> </span><br><span>      switch (event) {</span><br><span>     case ISO7816_E_XCEIVE_TPDU_CMD:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* buf might be required for cb until we end up here */</span><br><span style="color: hsl(120, 100%, 40%);">+               msgb_reset(tfp->tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+             COPY_TO_STATIC_MSGB(data, tfp->tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>           /* start transmission of a TPDU by sending the 5-byte header */</span><br><span style="color: hsl(0, 100%, 40%);">-         tfp->tpdu = (struct msgb *)data;</span><br><span>          OSMO_ASSERT(msgb_length(tfp->tpdu) >= sizeof(*tpduh));</span><br><span>                 /* l2h = after the 5byte header */</span><br><span>           tfp->tpdu->l2h = msgb_data(tfp->tpdu) + sizeof(*tpduh);</span><br><span>@@ -1455,8 +1500,6 @@</span><br><span>             /* Notify parent FSM */</span><br><span>              osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, tfp->tpdu);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          /* ownership transfer */</span><br><span style="color: hsl(0, 100%, 40%);">-                tfp->tpdu = 0;</span><br><span>            break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>@@ -1497,7 +1540,6 @@</span><br><span>              .out_state_mask = S(TPDU_S_INIT) |</span><br><span>                             S(TPDU_S_TX_HDR),</span><br><span>          .action = tpdu_s_init_action,</span><br><span style="color: hsl(0, 100%, 40%);">-           .onenter = tpdu_s_init_onenter,</span><br><span>      },</span><br><span>   [TPDU_S_TX_HDR] = {</span><br><span>          .name = "TX_HDR",</span><br><span>@@ -1590,6 +1632,10 @@</span><br><span> {</span><br><span>    struct iso7816_3_priv *ip;</span><br><span>   struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct atr_fsm_priv *atp;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct pps_fsm_priv *ppsp;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct tpdu_fsm_priv *tpdup;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span>   fi = osmo_fsm_inst_alloc(&iso7816_3_fsm, ctx, NULL, log_level, id);</span><br><span>      ip = talloc_zero(fi, struct iso7816_3_priv);</span><br><span>@@ -1611,6 +1657,9 @@</span><br><span>         if (!ip->atr_fi->priv)</span><br><span>                 goto out_atr;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     atp = get_atr_fsm_priv(ip->atr_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+        INIT_STATIC_MSGB(atp->atr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     ip->tpdu_fi = osmo_fsm_inst_alloc_child(&tpdu_fsm, fi, ISO7816_E_SW_ERR_IND);</span><br><span>         if (!ip->tpdu_fi)</span><br><span>                 goto out_atr;</span><br><span>@@ -1618,14 +1667,20 @@</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 1</span><br><span style="color: hsl(120, 100%, 40%);">+       tpdup = get_tpdu_fsm_priv(ip->tpdu_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+    INIT_STATIC_MSGB(tpdup->tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</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>       ip->pps_fi->priv = talloc_zero(ip->pps_fi, struct pps_fsm_priv);</span><br><span>    if (!ip->pps_fi->priv)</span><br><span>                 goto out_pps;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ppsp = get_pps_fsm_priv(ip->pps_fi);</span><br><span style="color: hsl(120, 100%, 40%);">+       INIT_STATIC_MSGB(ppsp->rx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+    INIT_STATIC_MSGB(ppsp->tx_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span>     /* This ensures the 'onenter' function of the initial state is called */</span><br><span>     osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);</span><br><span>diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h</span><br><span>index c0ef620..fcba87b 100644</span><br><span>--- a/ccid_common/iso7816_fsm.h</span><br><span>+++ b/ccid_common/iso7816_fsm.h</span><br><span>@@ -42,6 +42,7 @@</span><br><span>     ISO7816_E_XCEIVE_PPS_CMD,</span><br><span>    ISO7816_E_PPS_DONE_IND,</span><br><span>      ISO7816_E_PPS_FAILED_IND,</span><br><span style="color: hsl(120, 100%, 40%);">+     ISO7816_E_PPS_UNSUPPORTED_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></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/21071">change 21071</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/+/21071"/><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: I65e77c376aca9ed50e234a0b58a7450a8bbd4fe0 </div>
<div style="display:none"> Gerrit-Change-Number: 21071 </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>