osmo-ccid-firmware/ccid_host/ccid_slot_sim.c

177 lines
4.9 KiB
C

/* 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 */
/* (C) 2019-2020 by Harald Welte <laforge@gnumonks.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <osmocom/core/msgb.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/logging.h>
#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 uint8_t sysmousim_sjs1_atr[] = {
0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31,
0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20,
0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 };
static const struct ccid_pars_decoded slotsim_def_pars = {
.fi = 372,
.di = 1,
.clock_stop = CCID_CLOCK_STOP_NOTALLOWED,
.inverse_convention = false,
.t0 = {
.guard_time_etu = 0,
.waiting_integer = 0,
},
/* FIXME: T=1 */
};
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;
LOGPCS(cs, LOGL_DEBUG, "scheduling pwron_timer\n");
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;
LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,
sysmousim_sjs1_atr, sizeof(sysmousim_sjs1_atr));
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;
LOGPCS(cs, LOGL_DEBUG, "scheduling xfr_timer\n");
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;
LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
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) {
cs->icc_powered = true;
cs->icc_in_reset = false;
} else {
cs->icc_powered = false;
cs->icc_in_reset = true;
}
}
static void slotsim_set_clock(struct ccid_slot *cs, enum ccid_clock_command cmd)
{
/* FIXME */
switch (cmd) {
case CCID_CLOCK_CMD_STOP:
break;
case CCID_CLOCK_CMD_RESTART:
break;
default:
OSMO_ASSERT(0);
}
}
static int slotsim_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,
const struct ccid_pars_decoded *pars_dec)
{
/* we always acknowledge all parameters */
return 0;
}
static int slotsim_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps)
{
/* we always acknowledge all rates/clocks */
return 0;
}
static int slotsim_init(struct ccid_slot *cs)
{
struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
cs->icc_present = true;
cs->icc_powered = true;
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;
}
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,
.set_rate_and_clock = slotsim_set_rate_and_clock,
};