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/+/16237 ) Change subject: setparameters/PPS works ...................................................................... setparameters/PPS works Change-Id: I2e226b0033f8a147fad60a33a63cc45ee9adc756 --- M ccid_common/ccid_device.c M ccid_common/ccid_device.h M ccid_common/ccid_slot_fsm.c M ccid_common/cuart.h R ccid_common/iso7816_3.c R ccid_common/iso7816_3.h M ccid_common/iso7816_fsm.c M ccid_common/iso7816_fsm.h M sysmoOCTSIM/cuart_driver_asf4_usart_async.c M sysmoOCTSIM/gcc/Makefile M sysmoOCTSIM/ncn8025.c M sysmoOCTSIM/ncn8025.h 12 files changed, 370 insertions(+), 29 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/37/16237/1 diff --git a/ccid_common/ccid_device.c b/ccid_common/ccid_device.c index 8183b16..ba36988 100644 --- a/ccid_common/ccid_device.c +++ b/ccid_common/ccid_device.c @@ -24,8 +24,10 @@ 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; +// if (in->bmTCCKST0 & 0xFD) +// return -11; +// 6.1.7 says: "Note: the CCID ignores this bit", placeholder for GETparameters + /* input validation: only 0x00 to 0x03 permitted for bClockSTop */ if (in->bClockStop & 0xFC) return -14; @@ -254,7 +256,7 @@ } return msg; } -static struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, +struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, enum ccid_error_code err) { return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars); @@ -276,7 +278,7 @@ } return msg; } -static struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, +struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, enum ccid_error_code err) { return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars); @@ -465,7 +467,7 @@ /* copy default parameters from somewhere */ /* FIXME: T=1 */ - cs->ci->slot_ops->set_params(cs, CCID_PROTOCOL_NUM_T0, cs->default_pars); + cs->ci->slot_ops->set_params(cs, seq, CCID_PROTOCOL_NUM_T0, cs->default_pars); cs->pars = *cs->default_pars; resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0); @@ -502,14 +504,16 @@ goto out; } + cs->proposed_pars = pars_dec; + /* validate parameters; abort if they are not supported */ - rc = cs->ci->slot_ops->set_params(cs, spar->bProtocolNum, &pars_dec); + rc = cs->ci->slot_ops->set_params(cs, seq, spar->bProtocolNum, &pars_dec); if (rc < 0) { resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_FAILED, -rc); - } else { - cs->pars = pars_dec; - resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0); + goto out; } + /* busy, tdpu like callback */ + return 1; out: return ccid_slot_send_unbusy(cs, resp); } diff --git a/ccid_common/ccid_device.h b/ccid_common/ccid_device.h index ae3ab5b..8390783 100644 --- a/ccid_common/ccid_device.h +++ b/ccid_common/ccid_device.h @@ -53,6 +53,8 @@ bool cmd_busy; /* decided CCID parameters */ struct ccid_pars_decoded pars; + /* proposed CCID parameters */ + struct ccid_pars_decoded proposed_pars; /* default parameters; applied on ResetParameters */ const struct ccid_pars_decoded *default_pars; }; @@ -80,7 +82,7 @@ const struct ccid_pc_to_rdr_xfr_block *xfb); void (*set_power)(struct ccid_slot *cs, bool enable); void (*set_clock)(struct ccid_slot *cs, enum ccid_clock_command cmd); - int (*set_params)(struct ccid_slot *cs, enum ccid_protocol_num proto, + int (*set_params)(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto, const struct ccid_pars_decoded *pars_dec); int (*set_rate_and_clock)(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps); }; @@ -118,6 +120,10 @@ const uint32_t *data_rates, const uint32_t *clock_freqs, const char *name, void *priv); int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg); +struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, + enum ccid_error_code err); +struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts, + enum ccid_error_code err); /* Invalid request received: Please return STALL */ #define CCID_CTRL_RET_INVALID -1 diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c index 870cf35..8bdcfd5 100644 --- a/ccid_common/ccid_slot_fsm.c +++ b/ccid_common/ccid_slot_fsm.c @@ -13,6 +13,7 @@ #include "ccid_device.h" #include "cuart.h" #include "iso7816_fsm.h" +#include "iso7816_3.h" struct iso_fsm_slot { /* CCID slot above us */ @@ -112,6 +113,33 @@ ccid_slot_send_unbusy(cs, resp); msgb_free(tpdu); break; + case ISO7816_E_PPS_DONE_IND: + tpdu = data; + /* pps was successful, so we know these values are fine */ + uint16_t F = iso7816_3_fi_table[cs->proposed_pars.fi]; + uint8_t D = iso7816_3_di_table[cs->proposed_pars.di]; + uint32_t fmax = iso7816_3_fmax_table[cs->proposed_pars.fi]; + + card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK_FREQ, fmax); + card_uart_ctrl(ss->cuart, CUART_CTL_FD, F/D); + card_uart_ctrl(ss->cuart, CUART_CTL_WTIME, cs->proposed_pars.t0.waiting_integer); + + cs->pars = cs->proposed_pars; + resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_OK, 0); + + ccid_slot_send_unbusy(cs, resp); + + /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */ + msgb_free(tpdu); + break; + case ISO7816_E_PPS_FAILED_IND: + tpdu = data; + /* failed fi/di */ + resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_FAILED, 10); + ccid_slot_send_unbusy(cs, resp); + /* this frees the pps req from the host, pps resp buffer stays with the pps fsm */ + msgb_free(tpdu); + break; default: LOGPCS(cs, LOGL_NOTICE, "%s(event=%d, cause=%d, data=%p) unhandled\n", __func__, event, cause, data); @@ -175,10 +203,36 @@ } } -static int iso_fsm_slot_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto, +static int iso_fsm_slot_set_params(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto, const struct ccid_pars_decoded *pars_dec) { - /* we always acknowledge all parameters */ + struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs); + struct msgb *tpdu; + + /* see 6.1.7 for error offsets */ + if(proto != CCID_PROTOCOL_NUM_T0) + return -7; + + if(pars_dec->t0.guard_time_etu != 0) + return -12; + + if(pars_dec->clock_stop != CCID_CLOCK_STOP_NOTALLOWED) + return -14; + + ss->seq = seq; + + /* Hardware does not support SPU, so no PPS2, and PPS3 is reserved anyway */ + tpdu = msgb_alloc(6, "PPSRQ"); + OSMO_ASSERT(tpdu); + msgb_put_u8(tpdu, 0xff); + msgb_put_u8(tpdu, (1 << 4)); /* only PPS1, T=0 */ + msgb_put_u8(tpdu, (pars_dec->fi << 4 | pars_dec->di)); + msgb_put_u8(tpdu, 0xff ^ (1 << 4) ^ (pars_dec->fi << 4 | pars_dec->di)); + + + LOGPCS(cs, LOGL_DEBUG, "scheduling PPS transfer: %s\n", msgb_hexdump(tpdu)); + osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_PPS_CMD, tpdu); + /* continues in iso_fsm_clot_user_cb once response/error/timeout is received */ return 0; } diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h index 5e397ab..9c93b7e 100644 --- a/ccid_common/cuart.h +++ b/ccid_common/cuart.h @@ -25,8 +25,10 @@ CUART_CTL_RX, /* enable/disable receiver */ CUART_CTL_POWER, /* enable/disable ICC power */ CUART_CTL_CLOCK, /* enable/disable ICC clock */ + CUART_CTL_CLOCK_FREQ, /* set ICC clock frequency (hz)*/ CUART_CTL_RST, /* enable/disable ICC reset */ CUART_CTL_WTIME, /* set the waiting time (in etu) */ + CUART_CTL_FD, }; struct card_uart; @@ -74,6 +76,7 @@ uint32_t wtime_etu; struct osmo_timer_list wtime_tmr; + /* driver-specific private data */ union { struct { @@ -95,6 +98,8 @@ struct { struct usart_async_descriptor *usa_pd; uint8_t slot_nr; + /* in us, required, no delay breaks _rx_ */ + uint32_t extrawait_after_rx; } asf4; } u; }; diff --git a/sysmoOCTSIM/iso7816_3.c b/ccid_common/iso7816_3.c similarity index 100% rename from sysmoOCTSIM/iso7816_3.c rename to ccid_common/iso7816_3.c diff --git a/sysmoOCTSIM/iso7816_3.h b/ccid_common/iso7816_3.h similarity index 100% rename from sysmoOCTSIM/iso7816_3.h rename to ccid_common/iso7816_3.h diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c index beda7ab..c675ece 100644 --- a/ccid_common/iso7816_fsm.c +++ b/ccid_common/iso7816_fsm.c @@ -69,6 +69,7 @@ * @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_WAIT_PPS0, /*!< format byte */ PPS_S_WAIT_PPS1, /*!< first parameter byte */ @@ -221,7 +222,7 @@ /* 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_WAIT_PPSS, 0, 0); + osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0); osmo_fsm_inst_state_chg(ip->tpdu_fi, TPDU_S_INIT, 0, 0); } @@ -311,6 +312,12 @@ /* pass on to sub-fsm */ osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data); break; + case ISO7816_E_XCEIVE_PPS_CMD: +// osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_REQ, 0, 0); + 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_dispatch(ip->pps_fi, event, data); + break; default: OSMO_ASSERT(0); } @@ -369,6 +376,65 @@ } } +static void iso7816_3_in_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct iso7816_3_priv *tfp = get_iso7816_3_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_XCEIVE_PPS_CMD: + osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0); +// card_uart_tx(tfp->uart, msgb_data(data), msgb_length(data), true); + break; + default: + OSMO_ASSERT(0); + } +} + + +static void iso7816_3_s_wait_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + 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); + break; + default: + OSMO_ASSERT(0); + } +} + +static void iso7816_3_s_ins_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct iso7816_3_priv *ip = get_iso7816_3_priv(fi); + struct msgb *ppsrsp; + OSMO_ASSERT(fi->fsm == &iso7816_3_fsm); + + switch (event) { + case ISO7816_E_RX_SINGLE: + case ISO7816_E_WTIME_EXP: + /* simply pass this through to the child FSM for the ATR */ + osmo_fsm_inst_dispatch(ip->pps_fi, event, data); + break; + case ISO7816_E_PPS_DONE_IND: + case ISO7816_E_PPS_FAILED_IND: + ppsrsp = data; + osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0); + /* notify user about PPS result */ + ip->user_cb(fi, event, 0, ppsrsp); + break; + case ISO7816_E_RX_ERR_IND: + ppsrsp = data; + osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0); + ip->user_cb(fi, event, 0, ppsrsp); + break; + default: + OSMO_ASSERT(0); + } +} + static const struct osmo_fsm_state iso7816_3_states[] = { [ISO7816_S_RESET] = { .name = "RESET", @@ -400,11 +466,13 @@ }, [ISO7816_S_WAIT_TPDU] = { .name = "WAIT_TPDU", - .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD), + .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD) | + S(ISO7816_E_XCEIVE_PPS_CMD), .out_state_mask = S(ISO7816_S_RESET) | S(ISO7816_S_WAIT_TPDU) | S(ISO7816_S_IN_TPDU) | - S(ISO7816_S_IN_PPS_REQ), + S(ISO7816_S_IN_PPS_REQ) | + S(ISO7816_S_WAIT_PPS_RSP), .action = iso7816_3_wait_tpdu_action, .onenter = iso7816_3_wait_tpdu_onenter, }, @@ -424,26 +492,36 @@ }, [ISO7816_S_IN_PPS_REQ] = { .name = "IN_PPS_REQ", - .in_event_mask = 0, /* FIXME */ + .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD), .out_state_mask = S(ISO7816_S_RESET) | S(ISO7816_S_WAIT_TPDU) | S(ISO7816_S_IN_PPS_REQ) | S(ISO7816_S_WAIT_PPS_RSP), + .action = iso7816_3_in_pps_req_action, }, [ISO7816_S_WAIT_PPS_RSP] = { .name = "WAIT_PPS_RESP", - .in_event_mask = 0, /* FIXME */ + .in_event_mask = S(ISO7816_E_TX_COMPL) | + S(ISO7816_E_TX_ERR_IND) | + S(ISO7816_E_WTIME_EXP), .out_state_mask = S(ISO7816_S_RESET) | S(ISO7816_S_WAIT_TPDU) | S(ISO7816_S_WAIT_PPS_RSP) | S(ISO7816_S_IN_PPS_RSP), + .action = iso7816_3_s_wait_pps_rsp_action, }, [ISO7816_S_IN_PPS_RSP] = { .name = "IN_PPS_RESP", - .in_event_mask = 0, /* FIXME */ + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_RX_COMPL) | + S(ISO7816_E_RX_ERR_IND) | + S(ISO7816_E_PPS_DONE_IND) | + S(ISO7816_E_PPS_FAILED_IND) | + S(ISO7816_E_WTIME_EXP), .out_state_mask = S(ISO7816_S_RESET) | S(ISO7816_S_WAIT_TPDU) | S(ISO7816_S_IN_PPS_RSP), + .action = iso7816_3_s_ins_pps_rsp_action, }, }; static struct osmo_fsm iso7816_3_fsm = { @@ -796,28 +874,188 @@ /*********************************************************************** * PPS FSM ***********************************************************************/ +struct pps_fsm_priv { + struct msgb* tx_cmd; + struct msgb* rx_cmd; + uint8_t pps0_recv; +}; + +static void pps_s_wait_ppss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) +{ + struct pps_fsm_priv *atp = fi->priv; + + if (!atp->rx_cmd) + atp->rx_cmd = msgb_alloc_c(fi, 6, "ATR"); /* TS + 32 chars */ + else + msgb_reset(atp->rx_cmd); +} + +static void pps_s_tx_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct pps_fsm_priv *atp = fi->priv; + atp->tx_cmd = 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_XCEIVE_PPS_CMD: + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPSS, 0, 0); + card_uart_tx(ip->uart, msgb_data(data), msgb_length(data), true); + 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); + uint8_t byte; + + switch (event) { + case ISO7816_E_RX_SINGLE: + byte = get_rx_byte_evt(fi->proc.parent, data); + LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte); + msgb_put_u8(atp->rx_cmd, byte); + switch (fi->state) { + case PPS_S_WAIT_PPSS: + if (byte == 0xff) + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS0, 0, 0); + break; + case PPS_S_WAIT_PPS0: + atp->pps0_recv = byte; + if(atp->pps0_recv & (1 << 4)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS1, 0, 0); + break; + } else if (atp->pps0_recv & (1 << 5)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0); + break; + } else if (atp->pps0_recv & (1 << 6)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0); + break; + } + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0); + break; + case PPS_S_WAIT_PPS1: + if (atp->pps0_recv & (1 << 5)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0); + break; + } else if (atp->pps0_recv & (1 << 6)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0); + break; + } + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0); + break; + case PPS_S_WAIT_PPS2: + if (atp->pps0_recv & (1 << 6)) { + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0); + break; + } + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0); + break; + case PPS_S_WAIT_PPS3: + osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0); + break; + case PPS_S_WAIT_PCK: + /* verify checksum if present */ + if (fi->state == PPS_S_WAIT_PCK) { + 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); + + /* pps was successful if response equals request + * rx buffer stays with the fsm, tx buffer gets handed back and freed + * by the cb */ + if (msgb_length(atp->rx_cmd) == msgb_length(atp->tx_cmd) && + !memcmp(pps_received, pps_sent, msgb_length(atp->rx_cmd))) { + osmo_fsm_inst_dispatch(fi->proc.parent, + ISO7816_E_PPS_DONE_IND, atp->tx_cmd); + } else { + osmo_fsm_inst_dispatch(fi->proc.parent, + ISO7816_E_PPS_FAILED_IND, atp->tx_cmd); + } + } + break; + default: + OSMO_ASSERT(0); + } + break; + case ISO7816_E_WTIME_EXP: + /* FIXME: timeout handling if no pps supported ? */ + osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_RX_ERR_IND, NULL); + break; + default: + OSMO_ASSERT(0); + } +} + static const struct osmo_fsm_state pps_states[] = { + [PPS_S_TX_PPS_REQ] = { + .name = "TX_PPS_REQ", + .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, + }, [PPS_S_WAIT_PPSS] = { .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), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_PPS0] = { .name = "WAIT_PPS0", + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_WTIME_EXP), + .out_state_mask = S(PPS_S_WAIT_PPS1) | + S(PPS_S_WAIT_PPS2) | + S(PPS_S_WAIT_PPS3) | + S(PPS_S_WAIT_PCK), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_PPS1] = { .name = "WAIT_PPS1", + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_WTIME_EXP), + .out_state_mask = S(PPS_S_WAIT_PPS2) | + S(PPS_S_WAIT_PPS3) | + S(PPS_S_WAIT_PCK), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_PPS2] = { .name = "WAIT_PPS2", + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_WTIME_EXP), + .out_state_mask = S(PPS_S_WAIT_PPS3) | + S(PPS_S_WAIT_PCK), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_PPS3] = { .name = "WAIT_PPS3", + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_WTIME_EXP), + .out_state_mask = S(PPS_S_WAIT_PCK), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_PCK] = { .name = "WAIT_PCK", + .in_event_mask = S(ISO7816_E_RX_SINGLE) | + S(ISO7816_E_WTIME_EXP), + .out_state_mask = S(PPS_S_WAIT_END), + .action = pps_wait_pX_action, }, [PPS_S_WAIT_END] = { .name = "WAIT_END", + .in_event_mask = 0, + .out_state_mask = S(PPS_S_TX_PPS_REQ) | + S(PPS_S_WAIT_PPSS), }, }; @@ -1223,7 +1461,7 @@ if (!ip->tpdu_fi->priv) goto out_tpdu; -#if 0 +#if 1 ip->pps_fi = osmo_fsm_inst_alloc_child(&pps_fsm, fi, ISO7816_E_SW_ERR_IND); if (!ip->pps_fi) goto out_tpdu; @@ -1237,7 +1475,7 @@ return fi; -#if 0 +#if 1 out_pps: osmo_fsm_inst_free(ip->pps_fi); #endif diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h index f2c7483..f512709 100644 --- a/ccid_common/iso7816_fsm.h +++ b/ccid_common/iso7816_fsm.h @@ -21,6 +21,9 @@ ISO7816_E_RESET_ACT_IND, /*!< Reset activated */ ISO7816_E_ABORT_REQ, /*!< Abort request (e.g. from CCID) */ /* TODO: PPS request */ + ISO7816_E_XCEIVE_PPS_CMD, + ISO7816_E_PPS_DONE_IND, + ISO7816_E_PPS_FAILED_IND, /* TODO: Clock stop request */ /* TODO: Rx FIFO overrun */ /* TODO: Rx buffer overrun */ diff --git a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c index f9856f3..a8f8044 100644 --- a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c +++ b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c @@ -289,6 +289,8 @@ cuart->u.asf4.usa_pd = usa_pd; cuart->u.asf4.slot_nr = slot_nr; + /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/ + cuart->u.asf4.extrawait_after_rx = 1./(20./8/372); usart_async_register_callback(usa_pd, USART_ASYNC_RXC_CB, SIM_rx_cb[slot_nr]); usart_async_register_callback(usa_pd, USART_ASYNC_TXC_CB, SIM_tx_cb[slot_nr]); @@ -338,6 +340,8 @@ return io_read(&usa_pd->io, data, len); } +#include "ccid_device.h" +#include "iso7816_3.h" static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg) { struct ncn8025_settings settings; @@ -349,7 +353,7 @@ sercom->USART.CTRLB.bit.RXEN = 1; sercom->USART.CTRLB.bit.TXEN = 0; } else { - delay_us(100); + delay_us(cuart->u.asf4.extrawait_after_rx); sercom->USART.CTRLB.bit.RXEN = 0; sercom->USART.CTRLB.bit.TXEN = 1; } @@ -361,22 +365,47 @@ usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd); break; case CUART_CTL_POWER: - ncn8025_get(cuart->u.asf4.slot_nr, &settings); - settings.cmdvcc = arg ? true : false; - settings.led = arg ? true : false; - settings.vsel = SIM_VOLT_5V0; + /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/ + cuart->u.asf4.extrawait_after_rx = 1./(20./8/372); // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1) if(arg) slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD); + ncn8025_get(cuart->u.asf4.slot_nr, &settings); + settings.cmdvcc = arg ? true : false; + settings.led = arg ? true : false; + settings.vsel = SIM_VOLT_5V0; ncn8025_set(cuart->u.asf4.slot_nr, &settings); + break; case CUART_CTL_WTIME: /* no driver-specific handling of this */ break; case CUART_CTL_CLOCK: - /* FIXME */ + /* no clock stop support */ + break; + case CUART_CTL_CLOCK_FREQ: + ncn8025_get(cuart->u.asf4.slot_nr, &settings); + + /* 2,5/5/10/20 supported by dividers */ + enum ncn8025_sim_clkdiv clkdiv = SIM_CLKDIV_1; + if(arg < 20000000) + clkdiv = SIM_CLKDIV_2; + if(arg < 10000000) + clkdiv = SIM_CLKDIV_4; + if(arg < 5000000) + clkdiv = SIM_CLKDIV_8; + settings.clkdiv = clkdiv; + ncn8025_set(cuart->u.asf4.slot_nr, &settings); + break; + case CUART_CTL_FD: + ncn8025_get(cuart->u.asf4.slot_nr, &settings); + uint8_t divider = ncn8025_div_val[settings.clkdiv]; + uint32_t baudrate = (20e6/divider)/arg; + cuart->u.asf4.extrawait_after_rx = 1./baudrate * 1000 * 1000; + slot_set_baudrate(cuart->u.asf4.slot_nr, baudrate); + break; default: return -EINVAL; } diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile index 9873159..41f5d10 100644 --- a/sysmoOCTSIM/gcc/Makefile +++ b/sysmoOCTSIM/gcc/Makefile @@ -84,6 +84,7 @@ ccid_common/ccid_proto.o \ ccid_common/ccid_device.o \ ccid_common/iso7816_fsm.o \ + ccid_common/iso7816_3.o \ ccid_common/cuart.o \ ccid_common/ccid_slot_fsm.o \ cuart_driver_asf4_usart_async.o \ @@ -123,7 +124,6 @@ hpl/sercom/hpl_sercom.o \ hpl/usb/hpl_usb.o \ i2c_bitbang.o \ - iso7816_3.o \ libosmo_emb.o \ main.o \ manual_test.o \ diff --git a/sysmoOCTSIM/ncn8025.c b/sysmoOCTSIM/ncn8025.c index 540b166..74d3b39 100644 --- a/sysmoOCTSIM/ncn8025.c +++ b/sysmoOCTSIM/ncn8025.c @@ -159,7 +159,7 @@ [SIM_VOLT_1V8] = "1.8", }; -static const unsigned int div_val[] = { +const unsigned int ncn8025_div_val[] = { [SIM_CLKDIV_1] = 1, [SIM_CLKDIV_2] = 2, [SIM_CLKDIV_4] = 4, @@ -168,7 +168,7 @@ void ncn8025_dump(const struct ncn8025_settings *set) { - printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], div_val[set->clkdiv]); + printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], ncn8025_div_val[set->clkdiv]); if (set->rstin) printf(", RST"); if (set->cmdvcc) diff --git a/sysmoOCTSIM/ncn8025.h b/sysmoOCTSIM/ncn8025.h index 2e774a7..01ddc97 100644 --- a/sysmoOCTSIM/ncn8025.h +++ b/sysmoOCTSIM/ncn8025.h @@ -14,6 +14,8 @@ SIM_CLKDIV_8 = 0, }; +extern const unsigned int ncn8025_div_val[]; + struct ncn8025_settings { bool rstin; /* Reset signal (true: asserted low) */ bool cmdvcc; /* Command VCC pin. Activation sequence Enable (true: active low) */ -- To view, visit https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16237 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: I2e226b0033f8a147fad60a33a63cc45ee9adc756 Gerrit-Change-Number: 16237 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/20191126/43f15728/attachment.htm>