Kévin Redon has uploaded this change for review. ( https://gerrit.osmocom.org/10217
Change subject: cardem: use TC_ETU to trigger ATR sending ...................................................................... cardem: use TC_ETU to trigger ATR sending this changes how ATR is handled. the ATR is also printed when set (as important debug information). Change-Id: I69df797e2feadffa9f5f977cb71b69386cee7cd0 --- M firmware/libcommon/source/card_emu.c 1 file changed, 75 insertions(+), 22 deletions(-) git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/17/10217/1 diff --git a/firmware/libcommon/source/card_emu.c b/firmware/libcommon/source/card_emu.c index 25ec36a..aa06707 100644 --- a/firmware/libcommon/source/card_emu.c +++ b/firmware/libcommon/source/card_emu.c @@ -296,32 +296,39 @@ card_emu_uart_enable(ch->uart_chan, 0); break; case ISO_S_WAIT_ATR: - set_pts_state(ch, PTS_S_WAIT_REQ_PTSS); /* Reset to initial Fi / Di ratio */ ch->fi = 1; ch->di = 1; emu_update_fidi(ch); + /* the ATR should only be sent 400 to 40k clock cycles after the RESET. + * we use the tc_etu mechanism to wait this time. + * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU. + */ + tc_etu_set_wtime(ch->tc_chan, 2); + /* ensure the TC_ETU timer is enabled */ + tc_etu_enable(ch->tc_chan); + break; + case ISO_S_IN_ATR: /* initialize to default WI, this will be overwritten if we - * receive TC2, and it will be programmed into hardware after + * send TC2, and it will be programmed into hardware after * ATR is finished */ ch->wi = ISO7816_3_DEFAULT_WI; /* update waiting time to initial waiting time */ ch->waiting_time = ISO7816_3_INIT_WTIME; + /* set initial waiting time */ tc_etu_set_wtime(ch->tc_chan, ch->waiting_time); /* Set ATR sub-state to initial state */ ch->atr.idx = 0; - //set_atr_state(ch, ATR_S_WAIT_TS); - /* Notice that we are just coming out of reset */ - //ch->sh.flags |= SIMTRACE_FLAG_ATR; + /* enable USART transmission to reader */ card_emu_uart_enable(ch->uart_chan, ENABLE_TX); - break; + /* sent first ATR byte TS */ + card_emu_tx_byte(ch); break; case ISO_S_WAIT_TPDU: /* enable the receiver, disable transmitter */ set_tpdu_state(ch, TPDU_S_WAIT_CLA); card_emu_uart_enable(ch->uart_chan, ENABLE_RX); break; - case ISO_S_IN_ATR: case ISO_S_IN_PTS: case ISO_S_IN_TPDU: /* do nothing */ @@ -329,6 +336,47 @@ } } +/********************************************************************** + * ATR handling + **********************************************************************/ + +/*! Transmit ATR data to reader + * @param[in] ch card interface connected to reader + * @return numbers of bytes transmitted + */ +static int tx_byte_atr(struct card_handle *ch) +{ + if (NULL == ch) { + TRACE_ERROR("ATR TX: no card handle provided\n\r"); + return 0; + } + if (ISO_S_IN_ATR != ch->state) { + TRACE_ERROR("%u: ATR TX: no in ATR state\n\r", ch->num); + return 0; + } + + /* Transmit ATR */ + if (ch->atr.idx < ch->atr.len) { + uint8_t byte = ch->atr.atr[ch->atr.idx++]; + card_emu_uart_tx(ch->uart_chan, byte); + TRACE_DEBUG("%u: ATR TX: %02x\n\r", ch->num, byte); + return 1; + } else { /* The ATR has been completely transmitted */ + /* TODO update WI using optional TC2 and then update WT */ + //ch->wi = ISO7816_3_DEFAULT_WI; + /* update waiting time */ + //ch->waiting_time = ISO7816_3_INIT_WTIME; + //tc_etu_set_wtime(ch->tc_chan, ch->waiting_time); + /* reset PTS to initial state */ + set_pts_state(ch, PTS_S_WAIT_REQ_PTSS); + /* go to next state */ + card_set_state(ch, ISO_S_WAIT_TPDU); + return 0; + } + + /* return number of bytes transmitted */ + return 1; +} /********************************************************************** * PTS / PPS handling @@ -793,17 +841,7 @@ switch (ch->state) { case ISO_S_IN_ATR: - if (ch->atr.idx < ch->atr.len) { - uint8_t byte; - byte = ch->atr.atr[ch->atr.idx++]; - rc = 1; - - card_emu_uart_tx(ch->uart_chan, byte); - - /* detect end of ATR */ - if (ch->atr.idx >= ch->atr.len) - card_set_state(ch, ISO_S_WAIT_TPDU); - } + rc = tx_byte_atr(ch); break; case ISO_S_IN_PTS: rc = tx_byte_pts(ch); @@ -898,9 +936,8 @@ if (ch->vcc_active && ch->clocked) { /* enable the TC/ETU counter once reset has been released */ tc_etu_enable(ch->tc_chan); + /* prepare to send the ATR */ card_set_state(ch, ISO_S_WAIT_ATR); - /* FIXME: wait 400 to 40k clock cycles before sending ATR */ - card_set_state(ch, ISO_S_IN_ATR); } } else if (active && !ch->in_reset) { TRACE_INFO("%u: RST asserted\r\n", ch->num); @@ -921,7 +958,15 @@ ch->atr.len = len; ch->atr.idx = 0; - /* FIXME: race condition with trasmitting ATR to reader? */ +#if TRACE_LEVEL >= TRACE_LEVEL_INFO + uint8_t i; + TRACE_INFO("%u: ATR set: ", ch->num); + for (i = 0; i < ch->atr.len; i++) { + TRACE_INFO_WP("%02x ", atr[i]); + } + TRACE_INFO_WP("\n\r"); +#endif + /* FIXME: race condition with transmitting ATR to reader? */ return 0; } @@ -952,7 +997,15 @@ void tc_etu_wtime_expired(void *handle) { struct card_handle *ch = handle; - TRACE_ERROR("%u: wtime_exp\r\n", ch->num); + switch (ch->state) { + case ISO_S_WAIT_ATR: + /* ISO 7816-3 6.2.1 time tc has passed, we can now send the ATR */ + card_set_state(ch, ISO_S_IN_ATR); + break; + default: + TRACE_ERROR("%u: wtime_exp\r\n", ch->num); + break; + } } /* shortest ATR found in smartcard_list.txt */ -- To view, visit https://gerrit.osmocom.org/10217 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: simtrace2 Gerrit-Branch: master Gerrit-MessageType: newchange Gerrit-Change-Id: I69df797e2feadffa9f5f977cb71b69386cee7cd0 Gerrit-Change-Number: 10217 Gerrit-PatchSet: 1 Gerrit-Owner: Kévin Redon <kre...@sysmocom.de>