laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/15697


Change subject: iso7816_fsm: Implement single-byte RX/TX
......................................................................

iso7816_fsm: Implement single-byte RX/TX

Change-Id: I31fb127e1cb2fda0856658a6511089c3d9e31c2a
---
M ccid/iso7816_fsm.c
1 file changed, 52 insertions(+), 17 deletions(-)



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

diff --git a/ccid/iso7816_fsm.c b/ccid/iso7816_fsm.c
index f20cbcd..e173030 100644
--- a/ccid/iso7816_fsm.c
+++ b/ccid/iso7816_fsm.c
@@ -779,8 +779,22 @@
  * TPDU FSM
  ***********************************************************************/

+/* In this FSM weu use the msgb for the TPDU as follows:
+ *  - 5-byte TPDU header is at msg->data
+ *  - COMMAND TPDU:
+ *    - command bytes are provided after the header at msg->l2h
+ *    - in case of incremental transmission, l3h points to next 
to-be-transmitted byte
+ *  - RESPONSE TPDU:
+ *    - any response bytes are stored after the header at msg->l2h
+ */
+
+static inline struct osim_apdu_cmd_hdr *msgb_tpdu_hdr(struct msgb *msg) {
+       return (struct osim_apdu_cmd_hdr *) msgb_data(msg);
+}
+
 struct tpdu_fsm_priv {
        struct msgb *tpdu;
+       bool is_command; /* is this a command TPDU (true) or a response (false) 
*/
 };

 /* type-safe method to obtain iso7816_3_priv from fi */
@@ -805,8 +819,14 @@
                tfp->tpdu = (struct msgb *)data;
                OSMO_ASSERT(msgb_length(tfp->tpdu) >= sizeof(*tpduh));
                tfp->tpdu->l2h = msgb_data(tfp->tpdu) + sizeof(*tpduh);
-               tpduh = msgb_data(tfp->tpdu);
-               LOGPFSML(fi, LOGL_DEBUG, "Transmitting TPDU header %s via 
UART\n",
+               if (msgb_l2len(tfp->tpdu)) {
+                       tfp->is_command = true;
+                       tfp->tpdu->l3h = tfp->tpdu->l2h; /* next tx byte == 
first byte of body */
+               } else
+                       tfp->is_command = false;
+               tpduh = msgb_tpdu_hdr(tfp->tpdu);
+               LOGPFSML(fi, LOGL_DEBUG, "Transmitting %s TPDU header %s via 
UART\n",
+                        tfp->is_command ? "COMMAND" : "RESPONSE",
                         osmo_hexdump_nospc((uint8_t *) tpduh, sizeof(*tpduh)));
                osmo_fsm_inst_state_chg(fi, TPDU_S_TX_HDR, 0, 0);
                card_uart_tx(ip->uart, (uint8_t *) tpduh, sizeof(*tpduh));
@@ -834,7 +854,7 @@
 static void tpdu_s_procedure_action(struct osmo_fsm_inst *fi, uint32_t event, 
void *data)
 {
        struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
-       struct osim_apdu_cmd_hdr *tpduh = msgb_data(tfp->tpdu);
+       struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
        struct osmo_fsm_inst *parent_fi = fi->proc.parent;
        struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
        uint8_t byte;
@@ -853,7 +873,7 @@
                        osmo_fsm_inst_state_chg(fi, TPDU_S_SW2, 0, 0);
                        break;
                } else if (byte == tpduh->ins) {
-                       if (msgb_l2len(tfp->tpdu)) {
+                       if (tfp->is_command) {
                                /* transmit all remaining bytes */
                                card_uart_tx(ip->uart, msgb_l2(tfp->tpdu), 
msgb_l2len(tfp->tpdu));
                                osmo_fsm_inst_state_chg(fi, 
TPDU_S_TX_REMAINING, 0, 0);
@@ -862,10 +882,15 @@
                                osmo_fsm_inst_state_chg(fi, 
TPDU_S_RX_REMAINING, 0, 0);
                        }
                } else if (byte == (tpduh->ins ^ 0xFF)) {
-                       osmo_panic("unsupported single-byte T=0 case");
-                       /* FIXME: transmit single byte then wait for proc */
-                       //osmo_fsm_inst_state_chg(fi, TPDU_S_xX_SINGLE, 0, 0);
-                       //osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
+                       /* transmit/recieve single byte then wait for proc */
+                       if (tfp->is_command) {
+                               /* transmit *next*, not first byte */
+                               OSMO_ASSERT(msgb_l3len(tfp->tpdu) >= 0);
+                               card_uart_tx(ip->uart, msgb_l3(tfp->tpdu), 1);
+                               osmo_fsm_inst_state_chg(fi, TPDU_S_TX_SINGLE, 
0, 0);
+                       } else {
+                               osmo_fsm_inst_state_chg(fi, TPDU_S_RX_SINGLE, 
0, 0);
+                       }
                } else
                        OSMO_ASSERT(0);
                break;
@@ -893,10 +918,15 @@
 /* UART is transmitting single byte of data; we wait for ISO7816_E_TX_COMPL */
 static void tpdu_s_tx_single_action(struct osmo_fsm_inst *fi, uint32_t event, 
void *data)
 {
+       struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
+
        switch (event) {
        case ISO7816_E_TX_COMPL:
-               /* TODO: increase pointer/counter? */
-               osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
+               tfp->tpdu->l3h += 1;
+               if (msgb_l3len(tfp->tpdu))
+                       osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
+               else
+                       osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
                break;
        default:
                OSMO_ASSERT(0);
@@ -907,7 +937,7 @@
 static void tpdu_s_rx_remaining_action(struct osmo_fsm_inst *fi, uint32_t 
event, void *data)
 {
        struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
-       struct osim_apdu_cmd_hdr *tpduh = msgb_data(tfp->tpdu);
+       struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
        struct osmo_fsm_inst *parent_fi = fi->proc.parent;
        struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
        int rc;
@@ -916,8 +946,12 @@
        case ISO7816_E_RX_COMPL:
                /* retrieve pending byte(s) */
                rc = card_uart_rx(ip->uart, msgb_l2(tfp->tpdu), tpduh->p3);
-               if (rc != tpduh->p3)
-                       LOGPFSML(fi, LOGL_ERROR, "expected %u bytes; read 
%d\n", tpduh->p3, rc);
+               OSMO_ASSERT(rc > 0);
+               msgb_put(tfp->tpdu, rc);
+               if (msgb_l2len(tfp->tpdu) != tpduh->p3) {
+                       LOGPFSML(fi, LOGL_ERROR, "expected %u bytes; read 
%d\n", tpduh->p3,
+                                msgb_l2len(tfp->tpdu));
+               }
                card_uart_set_rx_threshold(ip->uart, 1);
                osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
                break;
@@ -930,17 +964,18 @@
 static void tpdu_s_rx_single_action(struct osmo_fsm_inst *fi, uint32_t event, 
void *data)
 {
        struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
+       struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
        uint8_t byte;

        switch (event) {
        case ISO7816_E_RX_SINGLE:
                byte = get_rx_byte_evt(fi->proc.parent, data);
                LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
-               /* TODO: record byte */
-               /* FIXME: determine if number of expected bytes received */
-               if (0) {
+               msgb_put_u8(tfp->tpdu, byte);
+               /* determine if number of expected bytes received */
+               if (msgb_l2len(tfp->tpdu) == tpduh->p3)
                        osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
-               } else
+               else
                        osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
                break;
        default:

--
To view, visit https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/15697
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ccid-firmware
Gerrit-Branch: master
Gerrit-Change-Id: I31fb127e1cb2fda0856658a6511089c3d9e31c2a
Gerrit-Change-Number: 15697
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <lafo...@osmocom.org>
Gerrit-MessageType: newchange

Reply via email to