Harald Welte has submitted this change and it was merged. ( 
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(-)

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



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: merged
Gerrit-Change-Id: Id6c436916a54b98a11809a58e9154e3e9b627885
Gerrit-Change-Number: 14057
Gerrit-PatchSet: 1
Gerrit-Owner: Harald Welte <[email protected]>
Gerrit-Reviewer: Harald Welte <[email protected]>
Gerrit-Reviewer: Jenkins Builder (1000002)

Reply via email to