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/.
Hoernchen gerrit-no-reply at lists.osmocom.orgHoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16293 ) Change subject: first attempt at rx timeout handling ...................................................................... first attempt at rx timeout handling The general idea is to provide hints to cuart so it can calculate a reasonable timeout value when receiving multiple bytes instead of having per-byte timeouts Change-Id: Ia6ad2d83cea48a8661ed2e4eb50f9bcb85218454 --- M ccid_common/cuart.c M ccid_common/cuart.h M ccid_common/iso7816_fsm.c 3 files changed, 143 insertions(+), 29 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/93/16293/1 diff --git a/ccid_common/cuart.c b/ccid_common/cuart.c index 1ae50c6..1d777f9 100644 --- a/ccid_common/cuart.c +++ b/ccid_common/cuart.c @@ -49,7 +49,12 @@ { int secs, usecs; - usecs = get_etu_in_us(cuart) * cuart->wtime_etu; + if(!cuart->current_wtime_byte) + return; + + /* timemout is wtime * ETU + expected number of bytes * (12ETU+1 slack)ETU */ + usecs = get_etu_in_us(cuart) * cuart->wtime_etu + + get_etu_in_us(cuart) * cuart->current_wtime_byte * (12+1); if (usecs > 1000000) { secs = usecs / 1000000; usecs = usecs % 1000000; @@ -108,6 +113,15 @@ cuart->rx_enabled = arg ? true : false; if (!cuart->rx_enabled) osmo_timer_del(&cuart->wtime_tmr); +// else +// card_uart_wtime_restart(cuart); + break; + case CUART_CTL_RX_TIMER_HINT: + cuart->current_wtime_byte = arg; + if(arg) + card_uart_wtime_restart(cuart); + else + osmo_timer_del(&cuart->wtime_tmr); break; default: break; @@ -158,6 +172,12 @@ if (cuart->rx_after_tx_compl) card_uart_ctrl(cuart, CUART_CTL_RX, true); break; +// case CUART_E_RX_COMPLETE: +// osmo_timer_del(&cuart->wtime_tmr); +// break; +// case CUART_E_RX_SINGLE: +// card_uart_wtime_restart(cuart); +// break; default: break; } diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h index 6a782db..1df0c49 100644 --- a/ccid_common/cuart.h +++ b/ccid_common/cuart.h @@ -23,6 +23,7 @@ enum card_uart_ctl { CUART_CTL_RX, /* enable/disable receiver */ + CUART_CTL_RX_TIMER_HINT, /* tell cuart approximate number of rx bytes */ CUART_CTL_NO_RXTX, /* enable/disable receiver */ CUART_CTL_POWER, /* enable/disable ICC power */ CUART_CTL_CLOCK, /* enable/disable ICC clock */ @@ -78,6 +79,8 @@ uint32_t wtime_etu; struct osmo_timer_list wtime_tmr; + /* expected number of bytes, for timeout */ + uint32_t current_wtime_byte; /* driver-specific private data */ union { diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c index 44c8191..412bea7 100644 --- a/ccid_common/iso7816_fsm.c +++ b/ccid_common/iso7816_fsm.c @@ -68,14 +68,14 @@ * @note defined in ISO/IEC 7816-3:2006(E) section 9 */ enum pps_state { - PPS_S_TX_PPS_REQ, /*!< tx pps request */ - PPS_S_WAIT_PPSS, /*!< initial byte */ + PPS_S_PPS_REQ_INIT, /*!< tx pps request */ + PPS_S_TX_PPS_REQ, + PPS_S_WAIT_PPSX, /*!< initial byte */ PPS_S_WAIT_PPS0, /*!< format byte */ PPS_S_WAIT_PPS1, /*!< first parameter byte */ PPS_S_WAIT_PPS2, /*!< second parameter byte */ PPS_S_WAIT_PPS3, /*!< third parameter byte */ PPS_S_WAIT_PCK, /*!< check byte */ - PPS_S_WAIT_END, /*!< all done */ PPS_S_DONE }; @@ -219,9 +219,11 @@ struct iso7816_3_priv *ip = get_iso7816_3_priv(fi); OSMO_ASSERT(fi->fsm == &iso7816_3_fsm); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 0); + /* go back to initial state in child FSMs */ osmo_fsm_inst_state_chg(ip->atr_fi, ATR_S_WAIT_TS, 0, 0); - osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0); + osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_PPS_REQ_INIT, 0, 0); osmo_fsm_inst_state_chg(ip->tpdu_fi, TPDU_S_INIT, 0, 0); } @@ -235,8 +237,13 @@ case ISO7816_E_RESET_REL_IND: /* TOOD: this should happen before reset is released */ card_uart_ctrl(ip->uart, CUART_CTL_RX, true); - osmo_fsm_inst_state_chg_ms(fi, ISO7816_S_WAIT_ATR, - fi_cycles2ms(fi, 40000), T_WAIT_ATR); + + /* let's be reasonable here: the 40k cycle delay to ATR start is + * ~1.4ms @ 2.5Mhz/6720 baud, 1ETU = 372 cycles -> 40k/372=107/12ETU ~ 9 byte + * default timeout for rx is 9600 ETU, ATR might be missing the TCK + * so it might time out, so just add this delay */ + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 32+9); + osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_ATR, 0, 0); break; case ISO7816_E_POWER_UP_IND: break; @@ -308,6 +315,7 @@ { struct iso7816_3_priv *ip = get_iso7816_3_priv(fi); OSMO_ASSERT(fi->fsm == &iso7816_3_fsm); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 0); card_uart_ctrl(ip->uart, CUART_CTL_NO_RXTX, true); /* reset the TPDU state machine */ osmo_fsm_inst_dispatch(ip->tpdu_fi, ISO7816_E_TPDU_CLEAR_REQ, NULL); @@ -327,7 +335,7 @@ break; case ISO7816_E_XCEIVE_PPS_CMD: osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0); - osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0); + osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_PPS_REQ_INIT, 0, 0); osmo_fsm_inst_dispatch(ip->pps_fi, event, data); break; default: @@ -391,11 +399,13 @@ static void iso7816_3_s_wait_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct iso7816_3_priv *ip = get_iso7816_3_priv(fi); OSMO_ASSERT(fi->fsm == &iso7816_3_fsm); switch (event) { case ISO7816_E_TX_COMPL: /* Rx of single byte is already enabled by previous card_uart_tx() call */ osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_RSP, 0, 0); + osmo_fsm_inst_dispatch(ip->pps_fi, event, data); break; default: OSMO_ASSERT(0); @@ -435,6 +445,7 @@ [ISO7816_S_RESET] = { .name = "RESET", .in_event_mask = S(ISO7816_E_RESET_REL_IND) | + S(ISO7816_E_POWER_UP_IND) | S(ISO7816_E_PPS_FAILED_IND)| S(ISO7816_E_TPDU_FAILED_IND), .out_state_mask = S(ISO7816_S_WAIT_ATR) | @@ -751,6 +762,14 @@ } } +static void atr_done_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) +{ + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); + + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 0); +} + static const struct osmo_fsm_state atr_states[] = { [ATR_S_WAIT_TS] = { .name = "WAIT_TS", @@ -847,7 +866,7 @@ .name = "DONE", .in_event_mask = 0, .out_state_mask = S(ATR_S_WAIT_TS), - //.action = atr_done_action, + .onenter = atr_done_onenter }, }; @@ -868,7 +887,7 @@ uint8_t pps0_recv; }; -static void pps_s_wait_ppss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) +static void pps_s_pps_req_init_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) { struct pps_fsm_priv *atp = fi->priv; @@ -885,7 +904,7 @@ } } -static void pps_s_tx_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +static void pps_s_pps_req_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct pps_fsm_priv *atp = fi->priv; struct osmo_fsm_inst *parent_fi = fi->proc.parent; @@ -896,7 +915,8 @@ switch (event) { case ISO7816_E_XCEIVE_PPS_CMD: - osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPSS, 0, 0); + osmo_fsm_inst_state_chg(fi, PPS_S_TX_PPS_REQ, 0, 0); + card_uart_set_rx_threshold(ip->uart, 1); card_uart_tx(ip->uart, msgb_data(data), msgb_length(data), true); break; default: @@ -904,10 +924,29 @@ } } +static void pps_s_tx_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); + + switch (event) { + case ISO7816_E_TX_COMPL: + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 6); + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPSX, 0, 0); + break; + default: + OSMO_ASSERT(0); + } +} + + + + static void pps_wait_pX_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct pps_fsm_priv *atp = fi->priv; -// uint32_t guard_time_ms = atr_fi_gt_ms(fi); + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); uint8_t byte; switch (event) { @@ -916,7 +955,7 @@ LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte); msgb_put_u8(atp->rx_cmd, byte); switch (fi->state) { - case PPS_S_WAIT_PPSS: + case PPS_S_WAIT_PPSX: if (byte == 0xff) osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS0, 0, 0); break; @@ -960,7 +999,7 @@ uint8_t *pps_received = msgb_data(atp->rx_cmd); uint8_t *pps_sent = msgb_data(atp->tx_cmd); - osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_END, 0, 0); + osmo_fsm_inst_state_chg(fi, PPS_S_DONE, 0, 0); /* pps was successful if response equals request * rx buffer stays with the fsm, tx buffer gets handed back and freed @@ -982,6 +1021,7 @@ } break; case ISO7816_E_WTIME_EXP: + osmo_fsm_inst_state_chg(fi, PPS_S_DONE, 0, 0); /* FIXME: timeout handling if no pps supported ? */ osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_RX_ERR_IND, NULL); break; @@ -991,22 +1031,37 @@ } +static void pps_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) +{ + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); + + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 0); +} + + static const struct osmo_fsm_state pps_states[] = { - [PPS_S_TX_PPS_REQ] = { - .name = "TX_PPS_REQ", + [PPS_S_PPS_REQ_INIT] = { + .name = "INIT", .in_event_mask = S(ISO7816_E_XCEIVE_PPS_CMD) | S(ISO7816_E_WTIME_EXP), - .out_state_mask = S(PPS_S_TX_PPS_REQ) | - S(PPS_S_WAIT_PPSS), - .action = pps_s_tx_pps_req_action, - .onenter = pps_s_wait_ppss_onenter, + .out_state_mask = S(PPS_S_PPS_REQ_INIT) | + S(PPS_S_TX_PPS_REQ), + .action = pps_s_pps_req_init_action, + .onenter = pps_s_pps_req_init_onenter, }, - [PPS_S_WAIT_PPSS] = { + [PPS_S_TX_PPS_REQ] = { + .name = "TX_PPS_REQ", + .in_event_mask = S(ISO7816_E_TX_COMPL), + .out_state_mask = S(PPS_S_WAIT_PPSX), + .action = pps_s_tx_pps_req_action, + }, + [PPS_S_WAIT_PPSX] = { .name = "WAIT_PPSS", .in_event_mask = S(ISO7816_E_RX_SINGLE) | S(ISO7816_E_WTIME_EXP), .out_state_mask = S(PPS_S_WAIT_PPS0) | - S(PPS_S_WAIT_PPSS), + S(PPS_S_WAIT_PPSX), .action = pps_wait_pX_action, }, [PPS_S_WAIT_PPS0] = { @@ -1047,14 +1102,15 @@ .name = "WAIT_PCK", .in_event_mask = S(ISO7816_E_RX_SINGLE) | S(ISO7816_E_WTIME_EXP), - .out_state_mask = S(PPS_S_WAIT_END), + .out_state_mask = S(PPS_S_DONE), .action = pps_wait_pX_action, }, - [PPS_S_WAIT_END] = { - .name = "WAIT_END", + [PPS_S_DONE] = { + .name = "DONE", .in_event_mask = 0, - .out_state_mask = S(PPS_S_TX_PPS_REQ) | - S(PPS_S_WAIT_PPSS), + .out_state_mask = S(PPS_S_PPS_REQ_INIT), + .action = NULL, + .onenter = pps_s_done_onenter, }, }; @@ -1140,9 +1196,14 @@ #include <hal_gpio.h> static void tpdu_s_tx_hdr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); OSMO_ASSERT(fi->fsm == &tpdu_fsm); switch (event) { case ISO7816_E_TX_COMPL: + + card_uart_set_rx_threshold(ip->uart, 1); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1); /* Rx of single byte is already enabled by previous card_uart_tx() call */ osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0); break; @@ -1167,11 +1228,15 @@ LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte); if (byte == 0x60) { /* NULL: wait for another procedure byte */ + 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); } else if ((byte >= 0x60 && byte <= 0x6f) || (byte >= 0x90 && byte <= 0x9f)) { //msgb_apdu_sw(tfp->apdu) = byte << 8; msgb_put(tfp->tpdu, byte); /* receive second SW byte (SW2) */ + 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_SW2, 0, 0); break; } else if (byte == tpduh->ins) { @@ -1187,6 +1252,7 @@ osmo_fsm_inst_state_chg(fi, TPDU_S_TX_REMAINING, 0, 0); } else { card_uart_set_rx_threshold(ip->uart, tpduh->p3); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, tpduh->p3); osmo_fsm_inst_state_chg(fi, TPDU_S_RX_REMAINING, 0, 0); } } else if (byte == (tpduh->ins ^ 0xFF)) { @@ -1197,6 +1263,8 @@ card_uart_tx(ip->uart, msgb_l3(tfp->tpdu), 1, false); osmo_fsm_inst_state_chg(fi, TPDU_S_TX_SINGLE, 0, 0); } else { + 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_RX_SINGLE, 0, 0); } } else @@ -1216,6 +1284,7 @@ switch (event) { case ISO7816_E_TX_COMPL: 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); break; default: @@ -1227,10 +1296,14 @@ 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); + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); switch (event) { case ISO7816_E_TX_COMPL: tfp->tpdu->l3h += 1; + card_uart_set_rx_threshold(ip->uart, 1); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1); if (msgb_l3len(tfp->tpdu)) osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0); else @@ -1261,6 +1334,7 @@ msgb_l2len(tfp->tpdu)); } 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); break; default: @@ -1273,6 +1347,8 @@ { struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi); 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; switch (event) { @@ -1280,6 +1356,10 @@ byte = get_rx_byte_evt(fi->proc.parent, data); LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte); msgb_put_u8(tfp->tpdu, byte); + + card_uart_set_rx_threshold(ip->uart, 1); + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1); + /* 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); @@ -1306,6 +1386,7 @@ //msgb_apdu_sw(tfp->apdu) = byte << 8; msgb_put_u8(tfp->tpdu, byte); 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_SW2, 0, 0); break; default: @@ -1349,7 +1430,7 @@ case ISO7816_E_TX_ERR_IND: /* FIXME: handle this in some different way */ osmo_fsm_inst_state_chg(fi, TPDU_S_DONE, 0, 0); - osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, NULL); + osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_FAILED_IND, NULL); break; case ISO7816_E_TPDU_CLEAR_REQ: osmo_fsm_inst_state_chg(fi, TPDU_S_INIT, 0, 0); @@ -1357,6 +1438,15 @@ } } + +static void tpdu_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) +{ + struct osmo_fsm_inst *parent_fi = fi->proc.parent; + struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi); + + card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 0); +} + static const struct osmo_fsm_state tpdu_states[] = { [TPDU_S_INIT] = { .name = "INIT", @@ -1433,6 +1523,7 @@ .in_event_mask = 0, .out_state_mask = S(TPDU_S_INIT), .action = NULL, + .onenter = tpdu_s_done_onenter, }, }; static struct osmo_fsm tpdu_fsm = { -- To view, visit https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16293 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: Ia6ad2d83cea48a8661ed2e4eb50f9bcb85218454 Gerrit-Change-Number: 16293 Gerrit-PatchSet: 1 Gerrit-Owner: Hoernchen <ewild at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20191127/57f4a9ff/attachment.htm>