diff --git a/ccid/ccid_device.c b/ccid/ccid_device.c index ff523d3..9dafebc 100644 --- a/ccid/ccid_device.c +++ b/ccid/ccid_device.c @@ -403,14 +403,10 @@ static int ccid_handle_icc_power_on(struct ccid_slot *cs, struct msgb *msg) { const union ccid_pc_to_rdr *u = msgb_ccid_out(msg); const struct ccid_header *ch = (const struct ccid_header *) u; - uint8_t seq = u->icc_power_on.hdr.bSeq; - struct msgb *resp; - /* TODO: send actual ATR; handle error cases */ - /* TODO: handle this asynchronously */ - resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0); - - return ccid_slot_send_unbusy(cs, resp); + /* handle this asynchronously */ + cs->ci->slot_ops->icc_power_on_async(cs, msg, &u->icc_power_on); + return 1; } /* Section 6.1.2 */ @@ -431,12 +427,10 @@ static int ccid_handle_xfr_block(struct ccid_slot *cs, struct msgb *msg) { const union ccid_pc_to_rdr *u = msgb_ccid_out(msg); const struct ccid_header *ch = (const struct ccid_header *) u; - uint8_t seq = u->xfr_block.hdr.bSeq; - struct msgb *resp; - /* FIXME: handle this asynchronously */ - resp = ccid_gen_data_block(cs, seq, CCID_CMD_STATUS_OK, 0, NULL, 0); - return ccid_slot_send_unbusy(cs, resp); + /* handle this asynchronously */ + cs->ci->slot_ops->xfr_block_async(cs, msg, &u->xfr_block); + return 1; } /* Section 6.1.5 */ diff --git a/ccid/ccid_device.h b/ccid/ccid_device.h index 5b3a5bc..7eba842 100644 --- a/ccid/ccid_device.h +++ b/ccid/ccid_device.h @@ -78,6 +78,10 @@ struct ccid_slot_ops { * update the (power/clock/...) status from the hardware */ void (*pre_proc_cb)(struct ccid_slot *cs, struct msgb *msg); + void (*icc_power_on_async)(struct ccid_slot *cs, struct msgb *msg, + const struct ccid_pc_to_rdr_icc_power_on *ipo); + void (*xfr_block_async)(struct ccid_slot *cs, struct msgb *msg, + 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, diff --git a/ccid/ccid_slot_sim.c b/ccid/ccid_slot_sim.c index d7a5952..57fe3cf 100644 --- a/ccid/ccid_slot_sim.c +++ b/ccid/ccid_slot_sim.c @@ -1,8 +1,30 @@ /* Simulated CCID card slot. This is used in absence of a real hardware back-end * in order to test the CCID firmware codebase in a virtual environment */ +#include +#include + #include "ccid_device.h" +struct slotsim_slot { + struct osmo_timer_list pwron_timer; + struct osmo_timer_list xfr_timer; + /* bSeq of the operation currently in progress */ + uint8_t seq; +}; + +struct slotsim_instance { + struct slotsim_slot slot[NR_SLOTS]; +}; + +static struct slotsim_instance g_si; + +struct slotsim_slot *ccid_slot2slotsim_slot(struct ccid_slot *cs) +{ + OSMO_ASSERT(cs->slot_nr < ARRAY_SIZE(g_si.slot)); + return &g_si.slot[cs->slot_nr]; +} + static const struct ccid_pars_decoded slotsim_def_pars = { .fi = 0, .di = 0, @@ -20,6 +42,47 @@ static void slotsim_pre_proc_cb(struct ccid_slot *cs, struct msgb *msg) /* do nothing; real hardware would update the slot related state here */ } +static void slotsim_icc_power_on_async(struct ccid_slot *cs, struct msgb *msg, + const struct ccid_pc_to_rdr_icc_power_on *ipo) +{ + struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs); + + ss->seq = ipo->hdr.bSeq; + osmo_timer_schedule(&ss->pwron_timer, 1, 0); + msgb_free(msg); + /* continues in timer call-back below */ +} +static void slotsim_pwron_timer_cb(void *data) +{ + struct ccid_slot *cs = data; + struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs); + struct msgb *resp; + + resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, NULL, 0); + ccid_slot_send_unbusy(cs, resp); +} + +static void slotsim_xfr_block_async(struct ccid_slot *cs, struct msgb *msg, + const struct ccid_pc_to_rdr_xfr_block *xfb) +{ + struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs); + + ss->seq = xfb->hdr.bSeq; + osmo_timer_schedule(&ss->xfr_timer, 0, 50000); + msgb_free(msg); + /* continues in timer call-back below */ +} +static void slotsim_xfr_timer_cb(void *data) +{ + struct ccid_slot *cs = data; + struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs); + struct msgb *resp; + + resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, NULL, 0); + ccid_slot_send_unbusy(cs, resp); +} + + static void slotsim_set_power(struct ccid_slot *cs, bool enable) { if (enable) { @@ -56,8 +119,12 @@ static int slotsim_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_hz, ui return 0; } + static int slotsim_init(struct ccid_slot *cs) { + struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs); + osmo_timer_setup(&ss->pwron_timer, slotsim_pwron_timer_cb, cs); + osmo_timer_setup(&ss->xfr_timer, slotsim_xfr_timer_cb, cs); cs->default_pars = &slotsim_def_pars; return 0; } @@ -65,6 +132,8 @@ static int slotsim_init(struct ccid_slot *cs) const struct ccid_slot_ops slotsim_slot_ops = { .init = slotsim_init, .pre_proc_cb = slotsim_pre_proc_cb, + .icc_power_on_async = slotsim_icc_power_on_async, + .xfr_block_async = slotsim_xfr_block_async, .set_power = slotsim_set_power, .set_clock = slotsim_set_clock, .set_params = slotsim_set_params,