Harald Welte has submitted this change and it was merged. ( 
https://gerrit.osmocom.org/14055 )

Change subject: ccid_device: Return errors in case of invalid slot numbers
......................................................................

ccid_device: Return errors in case of invalid slot numbers

Change-Id: I4928425cc114c7af0068b13280fe89f428f44aab
---
M ccid/ccid_device.c
1 file changed, 282 insertions(+), 49 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved



diff --git a/ccid/ccid_device.c b/ccid/ccid_device.c
index f10b700..340ff60 100644
--- a/ccid/ccid_device.c
+++ b/ccid/ccid_device.c
@@ -17,6 +17,7 @@
        bool icc_present;
        bool icc_powered;
        bool icc_in_reset;
+       bool cmd_busy;
 };

 struct ccid_ops {
@@ -26,11 +27,16 @@
 struct ccid_instance {
        struct ccid_slot slot[NR_SLOTS];
        struct ccid_ops ops;
+       const char *name;
 };

 #define msgb_ccid_out(x) (union ccid_pc_to_rdr *)msgb_data(x)
 #define msgb_ccid_in(x) (union ccid_rdr_to_pc *)msgb_data(x)

+#define LOGPCI(ci, lvl, fmt, args ...) LOGP(DCCID, lvl, "%s: " fmt, 
(ci)->name, ## args)
+#define LOGPCS(cs, lvl, fmt, args ...) \
+       LOGP(DCCID, lvl, "%s(%u): " fmt, (cc)->ci->name, (cc)->slot_nr, ## args)
+
 static struct ccid_slot *get_ccid_slot(struct ccid_instance *ci, uint8_t 
slot_nr)
 {
        if (slot_nr >= sizeof(ci->slot))
@@ -62,6 +68,14 @@
        (x)->hdr.bError = error;                                \
        } while (0)

+#if 0
+static uint8_t ccid_pc_to_rdr_get_seq(const struct ccid_pc_to_rdr *u)
+{
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       return ch->bSeq;
+}
+#endif
+
 /***********************************************************************
  * Message generation / sending
  ***********************************************************************/
@@ -73,11 +87,13 @@
        return msg;
 }

+/* Send given CCID message */
 static int ccid_send(struct ccid_instance *ci, struct msgb *msg)
 {
        return ci->ops.send_in(ci, msg);
 }

+/* Send given CCID message for given slot; patch bSlot into message */
 static int ccid_slot_send(struct ccid_slot *cs, struct msgb *msg)
 {
        struct ccid_header *ch = (struct ccid_header *) msgb_ccid_in(msg);
@@ -87,80 +103,207 @@
        return ccid_send(cs->ci, msg);
 }

+/* Send given CCID message and mark slot as un-busy */
+static int ccid_slot_send_unbusy(struct ccid_slot *cs, struct msgb *msg)
+{
+       cs->cmd_busy = false;
+       return ccid_slot_send(cs, msg);
+}

 /* Section 6.2.1 */
-static struct msgb *ccid_gen_data_block(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
-                                        enum ccid_error_code err, const 
uint8_t *data,
-                                        uint32_t data_len)
+static struct msgb *ccid_gen_data_block_nr(uint8_t slot_nr, uint8_t 
icc_status, uint8_t seq,
+                                          uint8_t cmd_sts, enum 
ccid_error_code err,
+                                          const uint8_t *data, uint32_t 
data_len)
 {
        struct msgb *msg = ccid_msgb_alloc();
-       struct ccid_rdr_to_pc_data_block *db =
+       struct ccid_rdr_to_pc_data_block *db =
                (struct ccid_rdr_to_pc_data_block *) msgb_put(msg, sizeof(*db) 
+ data_len);
-       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;

-       SET_HDR_IN(db, RDR_to_PC_DataBlock, cs->slot_nr, seq, sts, err);
+       SET_HDR_IN(db, RDR_to_PC_DataBlock, slot_nr, seq, sts, err);
        osmo_store32le(data_len, &db->hdr.hdr.dwLength);
        memcpy(db->abData, data, data_len);
        return msg;
 }
+static struct msgb *ccid_gen_data_block(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
+                                        enum ccid_error_code err, const 
uint8_t *data,
+                                        uint32_t data_len)
+{
+       return ccid_gen_data_block_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err, data, data_len);
+}

 /* Section 6.2.2 */
-static struct msgb *ccid_gen_slot_status(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
-                                        enum ccid_error_code err)
+static struct msgb *ccid_gen_slot_status_nr(uint8_t slot_nr, uint8_t 
icc_status,
+                                           uint8_t seq, uint8_t cmd_sts,
+                                           enum ccid_error_code err)
 {
        struct msgb *msg = ccid_msgb_alloc();
        struct ccid_rdr_to_pc_slot_status *ss =
                (struct ccid_rdr_to_pc_slot_status *) msgb_put(msg, 
sizeof(*ss));
-       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;

-       SET_HDR_IN(ss, RDR_to_PC_SlotStatus, cs->slot_nr, seq, sts, err);
+       SET_HDR_IN(ss, RDR_to_PC_SlotStatus, slot_nr, seq, sts, err);
        return msg;
 }
+static struct msgb *ccid_gen_slot_status(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
+                                        enum ccid_error_code err)
+{
+       return ccid_gen_slot_status_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err);
+}

 /* Section 6.2.3 */
-/* TODO */
+static struct msgb *ccid_gen_parameters_t0_nr(uint8_t slot_nr, uint8_t 
icc_status,
+                                             uint8_t seq, uint8_t cmd_sts, 
enum ccid_error_code err,
+                                             const struct ccid_proto_data_t0 
*t0)
+{
+       struct msgb *msg = ccid_msgb_alloc();
+       struct ccid_rdr_to_pc_parameters *par =
+               (struct ccid_rdr_to_pc_parameters *) msgb_put(msg, 
sizeof(par->hdr)+sizeof(*t0));
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;
+
+       SET_HDR_IN(par, RDR_to_PC_Parameters, slot_nr, seq, sts, err);
+       if (t0) {
+               osmo_store32le(sizeof(*t0), &par->hdr.hdr.dwLength);
+               par->abProtocolData.t0 = *t0;
+       }
+       return msg;
+}
+static struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
+                                          enum ccid_error_code err,
+                                          const struct ccid_proto_data_t0 *t0)
+{
+       return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err, t0);
+}
+
+static struct msgb *ccid_gen_parameters_t1_nr(uint8_t slot_nr, uint8_t 
icc_status,
+                                             uint8_t seq, uint8_t cmd_sts, 
enum ccid_error_code err,
+                                             const struct ccid_proto_data_t1 
*t1)
+{
+       struct msgb *msg = ccid_msgb_alloc();
+       struct ccid_rdr_to_pc_parameters *par =
+               (struct ccid_rdr_to_pc_parameters *) msgb_put(msg, 
sizeof(par->hdr)+sizeof(*t1));
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;
+
+       SET_HDR_IN(par, RDR_to_PC_Parameters, slot_nr, seq, sts, err);
+       if (t1) {
+               osmo_store32le(sizeof(*t1), &par->hdr.hdr.dwLength);
+               par->abProtocolData.t1 = *t1;
+       }
+       return msg;
+}
+static struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
+                                          enum ccid_error_code err,
+                                          const struct ccid_proto_data_t1 *t1)
+{
+       return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err, t1);
+}
+

 /* Section 6.2.4 */
-static struct msgb *ccid_gen_escape(struct ccid_slot *cs, uint8_t seq, uint8_t 
cmd_sts,
-                                   enum ccid_error_code err, const uint8_t 
*data,
-                                   uint32_t data_len)
+static struct msgb *ccid_gen_escape_nr(uint8_t slot_nr, uint8_t icc_status, 
uint8_t seq, uint8_t cmd_sts,
+                                       enum ccid_error_code err, const uint8_t 
*data, uint32_t data_len)
 {
        struct msgb *msg = ccid_msgb_alloc();
        struct ccid_rdr_to_pc_escape *esc =
                (struct ccid_rdr_to_pc_escape *) msgb_put(msg, sizeof(*esc) + 
data_len);
-       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;

-       SET_HDR_IN(esc, RDR_to_PC_Escape, cs->slot_nr, seq, sts, err);
+       SET_HDR_IN(esc, RDR_to_PC_Escape, slot_nr, seq, sts, err);
        osmo_store32le(data_len, &esc->hdr.hdr.dwLength);
        memcpy(esc->abData, data, data_len);
        return msg;
 }
+static struct msgb *ccid_gen_escape(struct ccid_slot *cs, uint8_t seq, uint8_t 
cmd_sts,
+                                   enum ccid_error_code err, const uint8_t 
*data,
+                                   uint32_t data_len)
+{
+       return ccid_gen_escape_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err, data, data_len);
+}

 /* Section 6.2.5 */
-static struct msgb *ccid_gen_clock_and_rate(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
-                                           enum ccid_error_code err, uint32_t 
clock_khz, uint32_t rate_bps)
+static struct msgb *ccid_gen_clock_and_rate_nr(uint8_t slot_nr, uint8_t 
icc_status, uint8_t seq,
+                                               uint8_t cmd_sts, enum 
ccid_error_code err,
+                                               uint32_t clock_khz, uint32_t 
rate_bps)
 {
        struct msgb *msg = ccid_msgb_alloc();
        struct ccid_rdr_to_pc_data_rate_and_clock *drc =
                (struct ccid_rdr_to_pc_data_rate_and_clock *) msgb_put(msg, 
sizeof(*drc));
-       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | get_icc_status(cs);
+       uint8_t sts = (cmd_sts & CCID_CMD_STATUS_MASK) | icc_status;

-       SET_HDR_IN(drc, RDR_to_PC_DataRateAndClockFrequency, cs->slot_nr, seq, 
sts, err);
+       SET_HDR_IN(drc, RDR_to_PC_DataRateAndClockFrequency, slot_nr, seq, sts, 
err);
        osmo_store32le(8, &drc->hdr.hdr.dwLength); /* Message-specific data 
length (wtf?) */
        osmo_store32le(clock_khz, &drc->dwClockFrequency); /* kHz */
        osmo_store32le(rate_bps, &drc->dwDataRate); /* bps */
        return msg;
 }
-
-
-
-#if 0
-static struct msgb *gen_err_resp(struct ccid_instance *ci, enum ccid_msg_type 
msg_type,
-                                enum ccid_error_code err_code)
+static struct msgb *ccid_gen_clock_and_rate(struct ccid_slot *cs, uint8_t seq, 
uint8_t cmd_sts,
+                                           enum ccid_error_code err, uint32_t 
clock_khz,
+                                           uint32_t rate_bps)
 {
-       struct c
+       return ccid_gen_clock_and_rate_nr(cs->slot_nr, get_icc_status(cs), seq, 
cmd_sts, err,
+                                         clock_khz, rate_bps);
 }
-#endif
+
+/*! generate an error response for given input message_type/slot_nr/seq
+ *  \param[in] msg_type CCID Message Type against which response is to be 
created
+ *  \param[in] slot_nr CCID Slot Number
+ *  \param[in] icc_status ICC Status of the slot
+ *  \param[in] seq CCID Sequence number
+ *  \param[in] err_code CCID Error Code to send
+ *  \returns dynamically-allocated message buffer containing error response */
+static struct msgb *gen_err_resp(enum ccid_msg_type msg_type, uint8_t slot_nr, 
uint8_t icc_status,
+                                uint8_t seq, enum ccid_error_code err_code)
+{
+       struct msgb *resp = NULL;
+
+       switch (msg_type) {
+       case PC_to_RDR_IccPowerOn:
+       case PC_to_RDR_XfrBlock:
+       case PC_to_RDR_Secure:
+               /* Return RDR_to_PC_DataBlock */
+               resp = ccid_gen_data_block_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                               err_code, NULL, 0);
+               break;
+
+       case PC_to_RDR_IccPowerOff:
+       case PC_to_RDR_GetSlotStatus:
+       case PC_to_RDR_IccClock:
+       case PC_to_RDR_T0APDU:
+       case PC_to_RDR_Mechanical:
+       case PC_to_RDR_Abort:
+               /* Return RDR_to_PC_SlotStatus */
+               resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                               err_code);
+               break;
+
+       case PC_to_RDR_GetParameters:
+       case PC_to_RDR_ResetParameters:
+       case PC_to_RDR_SetParameters:
+               /* Return RDR_to_PC_Parameters */
+               resp = ccid_gen_parameters_t0_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                                err_code, NULL); /* FIXME: 
parameters? */
+               break;
+
+       case PC_to_RDR_Escape:
+               /* Return RDR_to_PC_Escape */
+               resp = ccid_gen_escape_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                         err_code, NULL, 0);
+               break;
+
+       case PC_to_RDR_SetDataRateAndClockFrequency:
+               /* Return RDR_to_PC_SlotStatus */
+               resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                               err_code);
+               break;
+
+       default:
+               /* generate general error */
+               resp = ccid_gen_slot_status_nr(slot_nr, icc_status, seq, 
CCID_CMD_STATUS_FAILED,
+                                               CCID_ERR_CMD_NOT_SUPPORTED);
+               break;
+       }
+       return resp;
+}

 /***********************************************************************
  * Message reception / parsing
@@ -170,11 +313,13 @@
 static int ccid_handle_get_slot_status(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->get_slot_status.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);

-       return ccid_send(cs->ci, resp);
+       return ccid_slot_send_unbusy(cs, resp);
 }


@@ -182,123 +327,195 @@
 static int ccid_handle_icc_power_on(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->icc_power_on.hdr.bSeq;
        struct msgb *resp;

        /* TODO: send actual ATR; handle error cases */
        /* TODO: handle this asynchronously */
-       resp = ccid_gen_data_block(cs, u->icc_power_on.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0, NULL, 0);
+       resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0);

-       return ccid_send(cs->ci, resp);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.2 */
 static int ccid_handle_icc_power_off(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->icc_power_off.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
-       return ccid_send(cs->ci, resp);
+       /* FIXME */
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.4 */
 static int ccid_handle_xfr_block(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->xfr_block.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_data_block(cs, u->icc_power_on.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0, NULL, 0);
-       return ccid_send(cs->ci, resp);
+       /* FIXME */
+       resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.5 */
 static int ccid_handle_get_parameters(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->get_parameters.hdr.bSeq;
        struct msgb *resp;
+
+       /* FIXME */
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.6 */
 static int ccid_handle_reset_parameters(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->reset_parameters.hdr.bSeq;
        struct msgb *resp;
+
+       /* FIXME */
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.7 */
 static int ccid_handle_set_parameters(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->set_parameters.hdr.bSeq;
        struct msgb *resp;
+
+       /* FIXME */
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.8 */
 static int ccid_handle_escape(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->escape.hdr.bSeq;
        struct msgb *resp;
+
+       resp = ccid_gen_escape(cs, seq, CCID_CMD_STATUS_FAILED, 
CCID_ERR_CMD_NOT_SUPPORTED, NULL, 0);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.9 */
 static int ccid_handle_icc_clock(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->icc_clock.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
-       return ccid_send(cs->ci, resp);
+       /* FIXME: Actually Stop/Start the clock */
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.10 */
 static int ccid_handle_t0apdu(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->t0apdu.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
-       return ccid_send(cs->ci, resp);
+       /* FIXME */
+       //resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, 
CCID_ERR_CMD_NOT_SUPPORTED);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.11 */
 static int ccid_handle_secure(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->secure.hdr.bSeq;
+       struct msgb *resp;
+
+       /* FIXME */
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, 
CCID_ERR_CMD_NOT_SUPPORTED);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.12 */
 static int ccid_handle_mechanical(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->mechanical.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
-       return ccid_send(cs->ci, resp);
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, 
CCID_ERR_CMD_NOT_SUPPORTED);
+       return ccid_slot_send_unbusy(cs, resp);
 }
 
 /* Section 6.1.13 */
 static int ccid_handle_abort(struct ccid_slot *cs, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->abort.hdr.bSeq;
        struct msgb *resp;

-       resp = ccid_gen_slot_status(cs, u->get_slot_status.hdr.bSeq, 
CCID_CMD_STATUS_OK, 0);
-       return ccid_send(cs->ci, resp);
+       /* Check if the currently in-progress message is Abortable */
+       switch (0/* FIXME */) {
+       case PC_to_RDR_IccPowerOn:
+       case PC_to_RDR_XfrBlock:
+       case PC_to_RDR_Escape:
+       case PC_to_RDR_Secure:
+       case PC_to_RDR_Mechanical:
+       //case PC_to_RDR_Abort: /* seriously? WTF! */
+               break;
+       default:
+               /* CCID spec lists CMD_NOT_ABORTED, but gives no numberic value 
?!? */
+               resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_FAILED, 
CCID_ERR_CMD_NOT_SUPPORTED);
+               return ccid_slot_send_unbusy(cs, resp);
+       }
+
+       /* FIXME */
+       resp = ccid_gen_slot_status(cs, seq, CCID_CMD_STATUS_OK, 0);
+       return ccid_slot_send_unbusy(cs, resp);
 }

 /* Section 6.1.14 */
 static int ccid_handle_set_rate_and_clock(struct ccid_slot *cs, struct msgb 
*msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
+       const struct ccid_header *ch = (const struct ccid_header *) u;
+       uint8_t seq = u->set_rate_and_clock.hdr.bSeq;
        struct msgb *resp;
+
+       /* FIXME */
+       resp = ccid_gen_clock_and_rate(cs, seq, CCID_CMD_STATUS_OK, 0, 9600, 
2500000);
+       return ccid_slot_send_unbusy(cs, resp);
 }

-/* handle data arriving from the host on the OUT endpoint */
+/*! Handle data arriving from the host on the OUT endpoint.
+ *  \param[in] cs CCID Instance on which to operate
+ *  \param[in] msgb received message buffer containing one CCID OUT EP message 
from the host
+ *  \returns 0 on success; negative on error */
 int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg)
 {
        const union ccid_pc_to_rdr *u = msgb_ccid_out(msg);
        const struct ccid_header *ch = (const struct ccid_header *) u;
        unsigned int len = msgb_length(msg);
        struct ccid_slot *cs;
+       struct msgb *resp;
        int rc;

        if (len < sizeof(*ch)) {
@@ -306,12 +523,26 @@
                return -1;
        }

+       /* Check for invalid slot number */
        cs = get_ccid_slot(ci, ch->bSlot);
        if (!cs) {
-               /* FIXME */
-               return -1;
+               resp = gen_err_resp(ch->bMessageType, ch->bSlot, 
CCID_ICC_STATUS_NO_ICC, ch->bSeq, 5);
+               return ccid_send(ci, resp);
        }

+       /* Check if slot is already busy; Reject any additional commands 
meanwhile */
+       if (cs->cmd_busy) {
+               /* FIXME: ABORT logic as per section 5.3.1 of CCID Spec v1.1 */
+               resp = gen_err_resp(ch->bMessageType, ch->bSlot, 
get_icc_status(cs), ch->bSeq,
+                                       CCID_ERR_CMD_SLOT_BUSY);
+               return ccid_send(ci, resp);
+       }
+
+       /* we're now processing a command for the slot; mark slot as busy */
+       cs->cmd_busy = true;
+
+       /* TODO: enqueue into the per-slot specific input queue */
+
        switch (ch->bMessageType) {
        case PC_to_RDR_GetSlotStatus:
                if (len != sizeof(u->get_slot_status))
@@ -384,8 +615,10 @@
                rc = ccid_handle_set_rate_and_clock(cs, msg);
                break;
        default:
-               /* FIXME */
-               break;
+               /* generic response with bERror = 0 (command not supported) */
+               resp = gen_err_resp(ch->bMessageType, ch->bSlot, 
CCID_ICC_STATUS_NO_ICC, ch->bSeq,
+                                   CCID_ERR_CMD_NOT_SUPPORTED);
+               return ccid_slot_send_unbusy(cs, resp);
        }
        return 0;


--
To view, visit https://gerrit.osmocom.org/14055
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ccid-firmware
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I4928425cc114c7af0068b13280fe89f428f44aab
Gerrit-Change-Number: 14055
Gerrit-PatchSet: 1
Gerrit-Owner: Harald Welte <[email protected]>
Gerrit-Reviewer: Harald Welte <[email protected]>
Gerrit-Reviewer: Jenkins Builder (1000002)

Reply via email to