Change in osmo-ccid-firmware[master]: ccid: Implement encode/decode of ProtocolParameters

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

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


Harald Welte has uploaded this change for review. ( https://gerrit.osmocom.org/14057


Change subject: ccid: Implement encode/decode of ProtocolParameters
......................................................................

ccid: Implement encode/decode of ProtocolParameters

Change-Id: Id6c436916a54b98a11809a58e9154e3e9b627885
---
M ccid/ccid_device.c
M ccid/ccid_proto.h
2 files changed, 175 insertions(+), 20 deletions(-)



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

diff --git a/ccid/ccid_device.c b/ccid/ccid_device.c
index 340ff60..02d1599 100644
--- a/ccid/ccid_device.c
+++ b/ccid/ccid_device.c
@@ -11,6 +11,28 @@
 
 #define NR_SLOTS	8
 
+struct ccid_pars_decoded {
+	/* global for T0/T1 */
+	uint8_t fi;
+	uint8_t di;
+	enum ccid_clock_stop clock_stop;
+	bool inverse_convention;
+
+	struct {
+		uint8_t guard_time_etu;
+		uint8_t waiting_integer;
+	} t0;
+
+	struct {
+		enum ccid_t1_csum_type csum_type;
+		uint8_t guard_time_t1;
+		uint8_t bwi;
+		uint8_t cwi;
+		uint8_t ifsc;
+		uint8_t nad;
+	} t1;
+};
+
 struct ccid_slot {
 	struct ccid_instance *ci;
 	uint8_t slot_nr;
@@ -18,8 +40,100 @@
 	bool icc_powered;
 	bool icc_in_reset;
 	bool cmd_busy;
+	struct ccid_pars_decoded pars;
 };
 
+/* decode on-the-wire T0 parameters into their parsed form */
+static int decode_ccid_pars_t0(struct ccid_pars_decoded *out, const struct ccid_proto_data_t0 *in)
+{
+	/* input validation: only 0x00 and 0x02 permitted for bmTCCKST0 */
+	if (in->bmTCCKST0 & 0xFD)
+		return -11;
+	/* input validation: only 0x00 to 0x03 permitted for bClockSTop */
+	if (in->bClockStop & 0xFC)
+		return -14;
+
+	out->fi = in->bmFindexDindex >> 4;
+	out->di = in->bmFindexDindex & 0xF;
+	if (in->bmTCCKST0 & 2)
+		out->inverse_convention = true;
+	else
+		out->inverse_convention = false;
+	if (in->bGuardTimeT0 == 0xff)
+		out->t0.guard_time_etu = 0;
+	else
+		out->t0.guard_time_etu = in->bGuardTimeT0;
+	out->t0.waiting_integer = in->bWaitingIntegerT0;
+	out->clock_stop = in->bClockStop & 0x03;
+
+	return 0;
+}
+
+/* encode T0 parameters from parsed form into on-the-wire encoding */
+static void encode_ccid_pars_t0(struct ccid_proto_data_t0 *out, const struct ccid_pars_decoded *in)
+{
+	out->bmFindexDindex = ((in->fi << 4) & 0xF0) | (in->di & 0x0F);
+	if (in->inverse_convention)
+		out->bmTCCKST0 = 0x02;
+	else
+		out->bmTCCKST0 = 0x00;
+	out->bGuardTimeT0 = in->t0.guard_time_etu;
+	out->bWaitingIntegerT0 = in->t0.waiting_integer;
+	out->bClockStop = in->clock_stop & 0x03;
+}
+
+/* decode on-the-wire T1 parameters into their parsed form */
+static int decode_ccid_pars_t1(struct ccid_pars_decoded *out, const struct ccid_proto_data_t1 *in)
+{
+	/* input validation: only some values permitted for bmTCCKST0 */
+	if (in->bmTCCKST1 & 0xE8)
+		return -11;
+	/* input validation: only 0x00 to 0x9F permitted for bmWaitingIntegersT1 */
+	if (in->bWaitingIntegersT1 > 0x9F)
+		return -13;
+	/* input validation: only 0x00 to 0x03 permitted for bClockSTop */
+	if (in->bClockStop & 0xFC)
+		return -14;
+	/* input validation: only 0x00 to 0xFE permitted for bIFSC */
+	if (in->bIFSC > 0xFE)
+		return -15;
+
+	out->fi = in->bmFindexDindex >> 4;
+	out->di = in->bmFindexDindex & 0xF;
+	if (in->bmTCCKST1 & 1)
+		out->t1.csum_type = CCID_CSUM_TYPE_CRC;
+	else
+		out->t1.csum_type = CCID_CSUM_TYPE_LRC;
+	if (in->bmTCCKST1 & 2)
+		out->inverse_convention = true;
+	else
+		out->inverse_convention = false;
+	out->t1.guard_time_t1 = in->bGuardTimeT1;
+	out->t1.bwi = in->bWaitingIntegersT1 >> 4;
+	out->t1.cwi = in->bWaitingIntegersT1 & 0xF;
+	out->clock_stop = in->bClockStop & 0x03;
+	out->t1.ifsc = in->bIFSC;
+	out->t1.nad = in->bNadValue;
+
+	return 0;
+}
+
+/* encode T1 parameters from parsed form into on-the-wire encoding */
+static void encode_ccid_pars_t1(struct ccid_proto_data_t1 *out, const struct ccid_pars_decoded *in)
+{
+	out->bmFindexDindex = ((in->fi << 4) & 0xF0) | (in->di & 0x0F);
+	out->bmTCCKST1 = 0x10;
+	if (in->t1.csum_type == CCID_CSUM_TYPE_CRC)
+		out->bmTCCKST1 |= 0x01;
+	if (in->inverse_convention)
+		out->bmTCCKST1 |= 0x02;
+	out->bGuardTimeT1 = in->t1.guard_time_t1;
+	out->bWaitingIntegersT1 = ((in->t1.bwi << 4) & 0xF0) | (in->t1.cwi & 0x0F);
+	out->bClockStop = in->clock_stop & 0x03;
+	out->bIFSC = in->t1.ifsc;
+	out->bNadValue = in->t1.nad;
+}
+
 struct ccid_ops {
 	int (*send_in)(struct ccid_instance *ci, struct msgb *msg);
 };
@@ -154,48 +268,46 @@
 /* Section 6.2.3 */
 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)
+					      const struct ccid_pars_decoded *dec_par)
 {
 	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));
+		(struct ccid_rdr_to_pc_parameters *) msgb_put(msg, sizeof(par->hdr)+sizeof(par->abProtocolData.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;
+	if (dec_par) {
+		osmo_store32le(sizeof(par->abProtocolData.t0), &par->hdr.hdr.dwLength);
+		encode_ccid_pars_t0(&par->abProtocolData.t0, dec_par);
 	}
 	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)
+					   enum ccid_error_code err)
 {
-	return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, t0);
+	return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);
 }
 
 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)
+					      const struct ccid_pars_decoded *dec_par)
 {
 	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));
+		(struct ccid_rdr_to_pc_parameters *) msgb_put(msg, sizeof(par->hdr)+sizeof(par->abProtocolData.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;
+	if (dec_par) {
+		osmo_store32le(sizeof(par->abProtocolData.t1), &par->hdr.hdr.dwLength);
+		encode_ccid_pars_t1(&par->abProtocolData.t1, dec_par);
 	}
 	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)
+					   enum ccid_error_code err)
 {
-	return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, t1);
+	return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);
 }
 
 
@@ -372,7 +484,8 @@
 	uint8_t seq = u->get_parameters.hdr.bSeq;
 	struct msgb *resp;
 
-	/* FIXME */
+	/* FIXME: T=1 */
+	resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);
 	return ccid_slot_send_unbusy(cs, resp);
 }
 
@@ -384,7 +497,9 @@
 	uint8_t seq = u->reset_parameters.hdr.bSeq;
 	struct msgb *resp;
 
-	/* FIXME */
+	/* FIXME: copy default parameters from somewhere */
+	/* FIXME: T=1 */
+	resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);
 	return ccid_slot_send_unbusy(cs, resp);
 }
 
@@ -392,11 +507,34 @@
 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_pc_to_rdr_set_parameters *spar = &u->set_parameters;
 	const struct ccid_header *ch = (const struct ccid_header *) u;
 	uint8_t seq = u->set_parameters.hdr.bSeq;
+	struct ccid_pars_decoded pars_dec;
 	struct msgb *resp;
+	int rc;
 
-	/* FIXME */
+	switch (spar->bProtocolNum) {
+	case CCID_PROTOCOL_NUM_T0:
+		rc = decode_ccid_pars_t0(&pars_dec, &spar->abProtocolData.t0);
+		if (rc < 0)
+			resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_FAILED, -rc);
+		/* FIXME: validate parameters; abort if they are not supported */
+		cs->pars = pars_dec;
+		resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);
+		break;
+	case CCID_PROTOCOL_NUM_T1:
+		rc = decode_ccid_pars_t1(&pars_dec, &spar->abProtocolData.t1);
+		if (rc < 0)
+			resp = ccid_gen_parameters_t1(cs, seq, CCID_CMD_STATUS_FAILED, -rc);
+		/* FIXME: validate parameters; abort if they are not supported */
+		cs->pars = pars_dec;
+		resp = ccid_gen_parameters_t1(cs, seq, CCID_CMD_STATUS_OK, 0);
+		break;
+	default:
+		resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_FAILED, 0);
+		break;
+	}
 	return ccid_slot_send_unbusy(cs, resp);
 }
 
diff --git a/ccid/ccid_proto.h b/ccid/ccid_proto.h
index fa0ead1..92878dc 100644
--- a/ccid/ccid_proto.h
+++ b/ccid/ccid_proto.h
@@ -132,6 +132,23 @@
 /* Response: RDR_to_PC_Parameters */
 
 /* Section 6.1.7 */
+enum ccid_protocol_num {
+	CCID_PROTOCOL_NUM_T0	= 0x00,
+	CCID_PROTOCOL_NUM_T1	= 0x01,
+	CCID_PROTOCOL_NUM_2WIRE	= 0x80,
+	CCID_PROTOCOL_NUM_3WIRE	= 0x81,
+	CCID_PROTOCOL_NUM_I2C	= 0x82,
+};
+enum ccid_clock_stop {
+	CCID_CLOCK_STOP_NOTALLOWED	= 0x00,
+	CCID_CLOCK_STOP_LOW		= 0x01,
+	CCID_CLOCK_STOP_HIGH		= 0x02,
+	CCID_CLOCK_STOP_EITHER		= 0x03,
+};
+enum ccid_t1_csum_type {
+	CCID_CSUM_TYPE_LRC	= 0,
+	CCID_CSUM_TYPE_CRC	= 1,
+};
 struct ccid_proto_data_t0 {
 	uint8_t bmFindexDindex;
 	uint8_t bmTCCKST0;
@@ -145,7 +162,7 @@
 	uint8_t bGuardTimeT1;
 	uint8_t bWaitingIntegersT1;
 	uint8_t bClockStop;
-	uint8_t bFSC;
+	uint8_t bIFSC;
 	uint8_t bNadValue;
 } __attribute__ ((packed));
 struct ccid_pc_to_rdr_set_parameters {

-- 
To view, visit https://gerrit.osmocom.org/14057
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: Id6c436916a54b98a11809a58e9154e3e9b627885
Gerrit-Change-Number: 14057
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/1300f00e/attachment.htm>


More information about the gerrit-log mailing list