<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/14055">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ccid_device: Return errors in case of invalid slot numbers<br><br>Change-Id: I4928425cc114c7af0068b13280fe89f428f44aab<br>---<br>M ccid/ccid_device.c<br>1 file changed, 282 insertions(+), 49 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/ccid/ccid_device.c b/ccid/ccid_device.c</span><br><span>index f10b700..340ff60 100644</span><br><span>--- a/ccid/ccid_device.c</span><br><span>+++ b/ccid/ccid_device.c</span><br><span>@@ -17,6 +17,7 @@</span><br><span>  bool icc_present;</span><br><span>    bool icc_powered;</span><br><span>    bool icc_in_reset;</span><br><span style="color: hsl(120, 100%, 40%);">+    bool cmd_busy;</span><br><span> };</span><br><span> </span><br><span> struct ccid_ops {</span><br><span>@@ -26,11 +27,16 @@</span><br><span> struct ccid_instance {</span><br><span>        struct ccid_slot slot[NR_SLOTS];</span><br><span>     struct ccid_ops ops;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *name;</span><br><span> };</span><br><span> </span><br><span> #define msgb_ccid_out(x) (union ccid_pc_to_rdr *)msgb_data(x)</span><br><span> #define msgb_ccid_in(x) (union ccid_rdr_to_pc *)msgb_data(x)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define LOGPCI(ci, lvl, fmt, args ...) LOGP(DCCID, lvl, "%s: " fmt, (ci)->name, ## args)</span><br><span style="color: hsl(120, 100%, 40%);">+#define LOGPCS(cs, lvl, fmt, args ...) \</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DCCID, lvl, "%s(%u): " fmt, (cc)->ci->name, (cc)->slot_nr, ## args)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ccid_slot *get_ccid_slot(struct ccid_instance *ci, uint8_t slot_nr)</span><br><span> {</span><br><span>      if (slot_nr >= sizeof(ci->slot))</span><br><span>@@ -62,6 +68,14 @@</span><br><span>  (x)->hdr.bError = error;                             \</span><br><span>    } while (0)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t ccid_pc_to_rdr_get_seq(const struct ccid_pc_to_rdr *u)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        return ch->bSeq;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /***********************************************************************</span><br><span>  * Message generation / sending</span><br><span>  ***********************************************************************/</span><br><span>@@ -73,11 +87,13 @@</span><br><span>   return msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Send given CCID message */</span><br><span> static int ccid_send(struct ccid_instance *ci, struct msgb *msg)</span><br><span> {</span><br><span>         return ci->ops.send_in(ci, msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Send given CCID message for given slot; patch bSlot into message */</span><br><span> static int ccid_slot_send(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>       struct ccid_header *ch = (struct ccid_header *) msgb_ccid_in(msg);</span><br><span>@@ -87,80 +103,207 @@</span><br><span>   return ccid_send(cs->ci, msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Send given CCID message and mark slot as un-busy */</span><br><span style="color: hsl(120, 100%, 40%);">+static int ccid_slot_send_unbusy(struct ccid_slot *cs, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       cs->cmd_busy = false;</span><br><span style="color: hsl(120, 100%, 40%);">+      return ccid_slot_send(cs, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Section 6.2.1 */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_data_block(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                         enum ccid_error_code err, const uint8_t *data,</span><br><span style="color: hsl(0, 100%, 40%);">-                                  uint32_t data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_data_block_nr(uint8_t slot_nr, uint8_t icc_status, uint8_t seq,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        uint8_t cmd_sts, enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    const uint8_t *data, uint32_t data_len)</span><br><span> {</span><br><span>      struct msgb *msg = ccid_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ccid_rdr_to_pc_data_block *db = </span><br><span style="color: hsl(120, 100%, 40%);">+       struct ccid_rdr_to_pc_data_block *db =</span><br><span>               (struct ccid_rdr_to_pc_data_block *) msgb_put(msg, sizeof(*db) + data_len);</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    SET_HDR_IN(db, RDR_to_PC_DataBlock, cs->slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+   SET_HDR_IN(db, RDR_to_PC_DataBlock, slot_nr, seq, sts, err);</span><br><span>         osmo_store32le(data_len, &db->hdr.hdr.dwLength);</span><br><span>      memcpy(db->abData, data, data_len);</span><br><span>       return msg;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_data_block(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, const uint8_t *data,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        uint32_t data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return ccid_gen_data_block_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, data, data_len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Section 6.2.2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_slot_status(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                  enum ccid_error_code err)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_slot_status_nr(uint8_t slot_nr, uint8_t icc_status,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      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>   struct msgb *msg = ccid_msgb_alloc();</span><br><span>        struct ccid_rdr_to_pc_slot_status *ss =</span><br><span>              (struct ccid_rdr_to_pc_slot_status *) msgb_put(msg, sizeof(*ss));</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    SET_HDR_IN(ss, RDR_to_PC_SlotStatus, cs->slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_HDR_IN(ss, RDR_to_PC_SlotStatus, slot_nr, seq, sts, err);</span><br><span>        return msg;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_slot_status(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%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ccid_gen_slot_status_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Section 6.2.3 */</span><br><span style="color: hsl(0, 100%, 40%);">-/* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_parameters_t0_nr(uint8_t slot_nr, uint8_t icc_status,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          uint8_t seq, uint8_t cmd_sts, enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       const struct ccid_proto_data_t0 *t0)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = ccid_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ccid_rdr_to_pc_parameters *par =</span><br><span style="color: hsl(120, 100%, 40%);">+               (struct ccid_rdr_to_pc_parameters *) msgb_put(msg, sizeof(par->hdr)+sizeof(*t0));</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_HDR_IN(par, RDR_to_PC_Parameters, slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (t0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_store32le(sizeof(*t0), &par->hdr.hdr.dwLength);</span><br><span style="color: hsl(120, 100%, 40%);">+           par->abProtocolData.t0 = *t0;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 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%);">+                                           enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     const struct ccid_proto_data_t0 *t0)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, t0);</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 struct msgb *ccid_gen_parameters_t1_nr(uint8_t slot_nr, uint8_t icc_status,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       uint8_t seq, uint8_t cmd_sts, enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       const struct ccid_proto_data_t1 *t1)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = ccid_msgb_alloc();</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ccid_rdr_to_pc_parameters *par =</span><br><span style="color: hsl(120, 100%, 40%);">+               (struct ccid_rdr_to_pc_parameters *) msgb_put(msg, sizeof(par->hdr)+sizeof(*t1));</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    SET_HDR_IN(par, RDR_to_PC_Parameters, slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (t1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_store32le(sizeof(*t1), &par->hdr.hdr.dwLength);</span><br><span style="color: hsl(120, 100%, 40%);">+           par->abProtocolData.t1 = *t1;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 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%);">+                                           enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     const struct ccid_proto_data_t1 *t1)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, t1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> /* Section 6.2.4 */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_escape(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 enum ccid_error_code err, const uint8_t *data,</span><br><span style="color: hsl(0, 100%, 40%);">-                                  uint32_t data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_escape_nr(uint8_t slot_nr, uint8_t icc_status, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     enum ccid_error_code err, const uint8_t *data, uint32_t data_len)</span><br><span> {</span><br><span>       struct msgb *msg = ccid_msgb_alloc();</span><br><span>        struct ccid_rdr_to_pc_escape *esc =</span><br><span>          (struct ccid_rdr_to_pc_escape *) msgb_put(msg, sizeof(*esc) + data_len);</span><br><span style="color: hsl(0, 100%, 40%);">-        uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    SET_HDR_IN(esc, RDR_to_PC_Escape, cs->slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+     SET_HDR_IN(esc, RDR_to_PC_Escape, slot_nr, seq, sts, err);</span><br><span>   osmo_store32le(data_len, &esc->hdr.hdr.dwLength);</span><br><span>     memcpy(esc->abData, data, data_len);</span><br><span>      return msg;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_escape(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, const uint8_t *data,</span><br><span style="color: hsl(120, 100%, 40%);">+                                uint32_t data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return ccid_gen_escape_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, data, data_len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Section 6.2.5 */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *ccid_gen_clock_and_rate(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,</span><br><span style="color: hsl(0, 100%, 40%);">-                                      enum ccid_error_code err, uint32_t clock_khz, uint32_t rate_bps)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_clock_and_rate_nr(uint8_t slot_nr, uint8_t icc_status, uint8_t seq,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                uint8_t cmd_sts, enum ccid_error_code err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                            uint32_t clock_khz, uint32_t rate_bps)</span><br><span> {</span><br><span>  struct msgb *msg = ccid_msgb_alloc();</span><br><span>        struct ccid_rdr_to_pc_data_rate_and_clock *drc =</span><br><span>             (struct ccid_rdr_to_pc_data_rate_and_clock *) msgb_put(msg, sizeof(*drc));</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    SET_HDR_IN(drc, RDR_to_PC_DataRateAndClockFrequency, cs->slot_nr, seq, sts, err);</span><br><span style="color: hsl(120, 100%, 40%);">+  SET_HDR_IN(drc, RDR_to_PC_DataRateAndClockFrequency, slot_nr, seq, sts, err);</span><br><span>        osmo_store32le(8, &drc->hdr.hdr.dwLength); /* Message-specific data length (wtf?) */</span><br><span>  osmo_store32le(clock_khz, &drc->dwClockFrequency); /* kHz */</span><br><span>  osmo_store32le(rate_bps, &drc->dwDataRate); /* bps */</span><br><span>         return msg;</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 style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *gen_err_resp(struct ccid_instance *ci, enum ccid_msg_type msg_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                             enum ccid_error_code err_code)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *ccid_gen_clock_and_rate(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, uint32_t clock_khz,</span><br><span style="color: hsl(120, 100%, 40%);">+                                         uint32_t rate_bps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     struct c</span><br><span style="color: hsl(120, 100%, 40%);">+      return ccid_gen_clock_and_rate_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        clock_khz, rate_bps);</span><br><span> }</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%);">+/*! generate an error response for given input message_type/slot_nr/seq</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] msg_type CCID Message Type against which response is to be created</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] slot_nr CCID Slot Number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] icc_status ICC Status of the slot</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] seq CCID Sequence number</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] err_code CCID Error Code to send</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns dynamically-allocated message buffer containing error response */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *gen_err_resp(enum ccid_msg_type msg_type, uint8_t slot_nr, uint8_t icc_status,</span><br><span style="color: hsl(120, 100%, 40%);">+                              uint8_t seq, enum ccid_error_code err_code)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *resp = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case PC_to_RDR_IccPowerOn:</span><br><span style="color: hsl(120, 100%, 40%);">+    case PC_to_RDR_XfrBlock:</span><br><span style="color: hsl(120, 100%, 40%);">+      case PC_to_RDR_Secure:</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Return RDR_to_PC_DataBlock */</span><br><span style="color: hsl(120, 100%, 40%);">+              resp = ccid_gen_data_block_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                               err_code, NULL, 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%);">+      case PC_to_RDR_IccPowerOff:</span><br><span style="color: hsl(120, 100%, 40%);">+   case PC_to_RDR_GetSlotStatus:</span><br><span style="color: hsl(120, 100%, 40%);">+ case PC_to_RDR_IccClock:</span><br><span style="color: hsl(120, 100%, 40%);">+      case PC_to_RDR_T0APDU:</span><br><span style="color: hsl(120, 100%, 40%);">+        case PC_to_RDR_Mechanical:</span><br><span style="color: hsl(120, 100%, 40%);">+    case PC_to_RDR_Abort:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Return RDR_to_PC_SlotStatus */</span><br><span style="color: hsl(120, 100%, 40%);">+             resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              err_code);</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%);">+      case PC_to_RDR_GetParameters:</span><br><span style="color: hsl(120, 100%, 40%);">+ case PC_to_RDR_ResetParameters:</span><br><span style="color: hsl(120, 100%, 40%);">+       case PC_to_RDR_SetParameters:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Return RDR_to_PC_Parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+             resp = ccid_gen_parameters_t0_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             err_code, NULL); /* FIXME: parameters? */</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%);">+      case PC_to_RDR_Escape:</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Return RDR_to_PC_Escape */</span><br><span style="color: hsl(120, 100%, 40%);">+         resp = ccid_gen_escape_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     err_code, NULL, 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%);">+      case PC_to_RDR_SetDataRateAndClockFrequency:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Return RDR_to_PC_SlotStatus */</span><br><span style="color: hsl(120, 100%, 40%);">+             resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              err_code);</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%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* generate general error */</span><br><span style="color: hsl(120, 100%, 40%);">+          resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, CCID_CMD_STATUS_FAILED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              CCID_ERR_CMD_NOT_SUPPORTED);</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%);">+     return resp;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /***********************************************************************</span><br><span>  * Message reception / parsing</span><br><span>@@ -170,11 +313,13 @@</span><br><span> static int ccid_handle_get_slot_status(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>     const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->get_slot_status.hdr.bSeq;</span><br><span>        struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -182,123 +327,195 @@</span><br><span> static int ccid_handle_icc_power_on(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>   const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->icc_power_on.hdr.bSeq;</span><br><span>   struct msgb *resp;</span><br><span> </span><br><span>       /* TODO: send actual ATR; handle error cases */</span><br><span>      /* TODO: handle this asynchronously */</span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_data_block(cs, u->icc_power_on.hdr.bSeq, CCID_CMD_STATUS_OK, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.2 */</span><br><span> static int ccid_handle_icc_power_off(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>         const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->icc_power_off.hdr.bSeq;</span><br><span>  struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.4 */</span><br><span> static int ccid_handle_xfr_block(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>     const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->xfr_block.hdr.bSeq;</span><br><span>      struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_data_block(cs, u->icc_power_on.hdr.bSeq, CCID_CMD_STATUS_OK, 0, NULL, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-    return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.5 */</span><br><span> static int ccid_handle_get_parameters(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->get_parameters.hdr.bSeq;</span><br><span>         struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.6 */</span><br><span> static int ccid_handle_reset_parameters(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>      const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->reset_parameters.hdr.bSeq;</span><br><span>       struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.7 */</span><br><span> static int ccid_handle_set_parameters(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->set_parameters.hdr.bSeq;</span><br><span>         struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.8 */</span><br><span> static int ccid_handle_escape(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->escape.hdr.bSeq;</span><br><span>         struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  resp = ccid_gen_escape(cs, seq, CCID_CMD_STATUS_FAILED, CCID_ERR_CMD_NOT_SUPPORTED, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.9 */</span><br><span> static int ccid_handle_icc_clock(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>     const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->icc_clock.hdr.bSeq;</span><br><span>      struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FIXME: Actually Stop/Start the clock */</span><br><span style="color: hsl(120, 100%, 40%);">+    resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.10 */</span><br><span> static int ccid_handle_t0apdu(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>       const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->t0apdu.hdr.bSeq;</span><br><span>         struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   //resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, CCID_ERR_CMD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+     return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.11 */</span><br><span> static int ccid_handle_secure(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>       const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->secure.hdr.bSeq;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, CCID_ERR_CMD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+     return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.12 */</span><br><span> static int ccid_handle_mechanical(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>   const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->mechanical.hdr.bSeq;</span><br><span>     struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, CCID_ERR_CMD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+     return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.13 */</span><br><span> static int ccid_handle_abort(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->abort.hdr.bSeq;</span><br><span>  struct msgb *resp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return ccid_send(cs->ci, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Check if the currently in-progress message is Abortable */</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (0/* FIXME */) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case PC_to_RDR_IccPowerOn:</span><br><span style="color: hsl(120, 100%, 40%);">+    case PC_to_RDR_XfrBlock:</span><br><span style="color: hsl(120, 100%, 40%);">+      case PC_to_RDR_Escape:</span><br><span style="color: hsl(120, 100%, 40%);">+        case PC_to_RDR_Secure:</span><br><span style="color: hsl(120, 100%, 40%);">+        case PC_to_RDR_Mechanical:</span><br><span style="color: hsl(120, 100%, 40%);">+    //case PC_to_RDR_Abort: /* seriously? WTF! */</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%);">+              /* CCID spec lists CMD_NOT_ABORTED, but gives no numberic value ?!? */</span><br><span style="color: hsl(120, 100%, 40%);">+                resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, CCID_ERR_CMD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+             return ccid_slot_send_unbusy(cs, resp);</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%);">+   /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span> /* Section 6.1.14 */</span><br><span> static int ccid_handle_set_rate_and_clock(struct ccid_slot *cs, struct msgb *msg)</span><br><span> {</span><br><span>   const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t seq = u->set_rate_and_clock.hdr.bSeq;</span><br><span>     struct msgb *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME */</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = ccid_gen_clock_and_rate(cs, seq, CCID_CMD_STATUS_OK, 0, 9600, 2500000);</span><br><span style="color: hsl(120, 100%, 40%);">+        return ccid_slot_send_unbusy(cs, resp);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* handle data arriving from the host on the OUT endpoint */</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Handle data arriving from the host on the OUT endpoint.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] cs CCID Instance on which to operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] msgb received message buffer containing one CCID OUT EP message from the host</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 on success; negative on error */</span><br><span> int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg)</span><br><span> {</span><br><span>        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);</span><br><span>  const struct ccid_header *ch = (const struct ccid_header *) u;</span><br><span>       unsigned int len = msgb_length(msg);</span><br><span>         struct ccid_slot *cs;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *resp;</span><br><span>   int rc;</span><br><span> </span><br><span>  if (len < sizeof(*ch)) {</span><br><span>@@ -306,12 +523,26 @@</span><br><span>          return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check for invalid slot number */</span><br><span>  cs = get_ccid_slot(ci, ch->bSlot);</span><br><span>        if (!cs) {</span><br><span style="color: hsl(0, 100%, 40%);">-              /* FIXME */</span><br><span style="color: hsl(0, 100%, 40%);">-             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            resp = gen_err_resp(ch->bMessageType, ch->bSlot, CCID_ICC_STATUS_NO_ICC, ch->bSeq, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+               return ccid_send(ci, resp);</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if slot is already busy; Reject any additional commands meanwhile */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cs->cmd_busy) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* FIXME: ABORT logic as per section 5.3.1 of CCID Spec v1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+               resp = gen_err_resp(ch->bMessageType, ch->bSlot, get_icc_status(cs), ch->bSeq,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       CCID_ERR_CMD_SLOT_BUSY);</span><br><span style="color: hsl(120, 100%, 40%);">+              return ccid_send(ci, resp);</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%);">+   /* we're now processing a command for the slot; mark slot as busy */</span><br><span style="color: hsl(120, 100%, 40%);">+      cs->cmd_busy = true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* TODO: enqueue into the per-slot specific input queue */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         switch (ch->bMessageType) {</span><br><span>       case PC_to_RDR_GetSlotStatus:</span><br><span>                if (len != sizeof(u->get_slot_status))</span><br><span>@@ -384,8 +615,10 @@</span><br><span>             rc = ccid_handle_set_rate_and_clock(cs, msg);</span><br><span>                break;</span><br><span>       default:</span><br><span style="color: hsl(0, 100%, 40%);">-                /* FIXME */</span><br><span style="color: hsl(0, 100%, 40%);">-             break;</span><br><span style="color: hsl(120, 100%, 40%);">+                /* generic response with bERror = 0 (command not supported) */</span><br><span style="color: hsl(120, 100%, 40%);">+                resp = gen_err_resp(ch->bMessageType, ch->bSlot, CCID_ICC_STATUS_NO_ICC, ch->bSeq,</span><br><span style="color: hsl(120, 100%, 40%);">+                               CCID_ERR_CMD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+              return ccid_slot_send_unbusy(cs, resp);</span><br><span>      }</span><br><span>    return 0;</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/14055">change 14055</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/14055"/><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-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I4928425cc114c7af0068b13280fe89f428f44aab </div>
<div style="display:none"> Gerrit-Change-Number: 14055 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>