Change in osmo-ccid-firmware[master]: ccid_device: Return errors in case of invalid slot numbers

Harald Welte gerrit-no-reply at lists.osmocom.org
Wed May 15 17:56:22 UTC 2019


Harald Welte has uploaded this change for review. ( 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(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/55/14055/1

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: newchange
Gerrit-Change-Id: I4928425cc114c7af0068b13280fe89f428f44aab
Gerrit-Change-Number: 14055
Gerrit-PatchSet: 1
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190515/ac77b1a3/attachment.html>


More information about the gerrit-log mailing list