Hoernchen has uploaded this change for review.
ccid: properly emit wait time ext messages
The CCID message that tells the host that the card
asked for a wait time extension was missing.
This is a bit weird, because it breaks the 1:1
relationship between messages and responses that
usually exists, nor does it consume a bSeq,
so we just count and emit WT msgs as appropriate.
Closes: OS#6458
Change-Id: Ib69483d453a0e5ebb1bc1885a8f78790a0f10d70
---
M ccid_common/ccid_device.h
M ccid_common/ccid_slot_fsm.c
M ccid_common/iso7816_fsm.c
M ccid_common/iso7816_fsm.h
4 files changed, 46 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/06/42306/1
diff --git a/ccid_common/ccid_device.h b/ccid_common/ccid_device.h
index 97d6212..ee2b5e2 100644
--- a/ccid_common/ccid_device.h
+++ b/ccid_common/ccid_device.h
@@ -78,6 +78,8 @@
const struct ccid_pars_decoded *default_pars;
volatile uint32_t event;
volatile void* event_data;
+ /* count of pending Wait Time Extension notifications to send to host */
+ volatile uint32_t wtime_ext;
};
/* CCID operations provided by USB transport layer */
diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c
index c34ad72..307c50f 100644
--- a/ccid_common/ccid_slot_fsm.c
+++ b/ccid_common/ccid_slot_fsm.c
@@ -102,6 +102,7 @@
card_uart_ctrl(ss->cuart, CUART_CTL_POWER_5V0, false);
cs->icc_powered = false;
cs->cmd_busy = false;
+ cs->wtime_ext = 0;
}
}
@@ -175,6 +176,10 @@
case ISO7816_E_HW_ERR_IND:
card_uart_ctrl(ss->cuart, CUART_CTL_NO_RXTX, true);
break;
+ case ISO7816_E_WTIME_EXT_IND:
+ /* card sent NULL byte (0x60); notify host via intermediate TimeExtension response */
+ cs->wtime_ext++;
+ break;
case ISO7816_E_ATR_ERR_IND:
case ISO7816_E_TPDU_FAILED_IND:
case ISO7816_E_PPS_FAILED_IND:
@@ -206,6 +211,27 @@
volatile uint32_t event = cs->event;
volatile void * volatile data = cs->event_data;
+ /* send pending Wait Time Extension notifications to host.
+ * wtime_ext is incremented from ISR context (UART RX -> FSM -> user_cb),
+ * so we must atomically read-and-clear to avoid losing increments. */
+ if (cs->wtime_ext) {
+ uint32_t wt_pending;
+#ifdef OCTSIMFWBUILD
+ CRITICAL_SECTION_ENTER();
+#endif
+ wt_pending = cs->wtime_ext;
+ cs->wtime_ext = 0;
+#ifdef OCTSIMFWBUILD
+ CRITICAL_SECTION_LEAVE();
+#endif
+ for (uint32_t i = 0; i < wt_pending; i++) {
+ LOGPCS(cs, LOGL_DEBUG, "Sending Wait Time Extension to host\n");
+ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_TIME_EXT, 1, NULL, 0);
+ /* this does neither consume the bSeq nor unbusy the slot! */
+ ccid_slot_send(cs, resp);
+ }
+ }
+
if (!event)
return 0;
// if(event && !data)
@@ -224,6 +250,7 @@
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, 0, 0);
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case ISO7816_E_ATR_DONE_IND:
tpdu = data;
@@ -239,6 +266,7 @@
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_data(tpdu), msgb_length(tpdu));
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case ISO7816_E_ATR_ERR_IND:
tpdu = data;
@@ -252,6 +280,7 @@
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, msgb_data(tpdu), msgb_length(tpdu));
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
break;
case ISO7816_E_TPDU_DONE_IND:
@@ -261,6 +290,7 @@
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_l4(tpdu), msgb_l4len(tpdu));
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case ISO7816_E_TPDU_FAILED_IND:
tpdu = data;
@@ -275,6 +305,7 @@
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, msgb_l2(tpdu), 0);
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case ISO7816_E_PPS_DONE_IND:
tpdu = data;
@@ -310,6 +341,7 @@
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case ISO7816_E_PPS_UNSUPPORTED_IND:
/* unsupported means no response, failed means request/response mismatch
@@ -331,6 +363,7 @@
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
+ cs->wtime_ext = 0;
break;
case 0:
break;
diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c
index a035148..c59bc7d 100644
--- a/ccid_common/iso7816_fsm.c
+++ b/ccid_common/iso7816_fsm.c
@@ -228,6 +228,7 @@
{ ISO7816_E_ATR_DONE_IND, "ATR_DONE_IND" },
{ ISO7816_E_ATR_ERR_IND, "ATR_ERR_IND" },
{ ISO7816_E_TPDU_DONE_IND, "TPDU_DONE_IND" },
+ { ISO7816_E_WTIME_EXT_IND, "WTIME_EXT_IND" },
{ ISO7816_E_XCEIVE_TPDU_CMD, "XCEIVE_TPDU_CMD" },
/* allstate events */
{ ISO7816_E_WTIME_EXP, "WAIT_TIME_EXP" },
@@ -432,6 +433,10 @@
/* hand finished TPDU to user */
ip->user_cb(fi, event, 0, apdu);
break;
+ case ISO7816_E_WTIME_EXT_IND:
+ /* notify user of wait time extension; TPDU still in progress! */
+ ip->user_cb(fi, event, 0, NULL);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -588,7 +593,8 @@
S(ISO7816_E_TX_COMPL) |
S(ISO7816_E_RX_ERR_IND) |
S(ISO7816_E_TX_ERR_IND) |
- S(ISO7816_E_TPDU_DONE_IND),
+ S(ISO7816_E_TPDU_DONE_IND) |
+ S(ISO7816_E_WTIME_EXT_IND),
.out_state_mask = S(ISO7816_S_RESET) |
S(ISO7816_S_WAIT_TPDU) |
S(ISO7816_S_IN_TPDU),
@@ -1319,6 +1325,7 @@
LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
if (byte == 0x60) {
/* NULL: wait for another procedure byte */
+ osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_WTIME_EXT_IND, NULL);
card_uart_set_rx_threshold(ip->uart, 1);
card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1);
osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
@@ -1490,6 +1497,7 @@
LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
if (byte == 0x60) {
/* NULL: wait for actual SW1 */
+ osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_WTIME_EXT_IND, NULL);
card_uart_set_rx_threshold(ip->uart, 1);
card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1);
osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h
index fb37396..542880a 100644
--- a/ccid_common/iso7816_fsm.h
+++ b/ccid_common/iso7816_fsm.h
@@ -47,6 +47,8 @@
/* TODO: Rx FIFO overrun */
/* TODO: Rx buffer overrun */
+ ISO7816_E_WTIME_EXT_IND, /*!< Wait Time Extension (NULL byte 0x60) from card */
+
/* internal events between FSMs in this file */
ISO7816_E_ATR_DONE_IND, /*!< ATR Done indication from ATR child FSM */
ISO7816_E_ATR_ERR_IND, /*!< ATR Error indication from ATR child FSM */
To view, visit change 42306. To unsubscribe, or for help writing mail filters, visit settings.