blob: dc33114309f22badcd152b09225ca20367514245 [file] [log] [blame]
Harald Weltecab5d152019-05-16 13:31:16 +02001/* Simulated CCID card slot. This is used in absence of a real hardware back-end
2 * in order to test the CCID firmware codebase in a virtual environment */
3
Harald Welte505d4412019-05-16 17:26:09 +02004#include <osmocom/core/msgb.h>
5#include <osmocom/core/timer.h>
Harald Welte29ae5d42019-05-16 17:40:29 +02006#include <osmocom/core/logging.h>
Harald Welte505d4412019-05-16 17:26:09 +02007
Harald Weltecab5d152019-05-16 13:31:16 +02008#include "ccid_device.h"
9
Harald Welte505d4412019-05-16 17:26:09 +020010struct slotsim_slot {
11 struct osmo_timer_list pwron_timer;
12 struct osmo_timer_list xfr_timer;
13 /* bSeq of the operation currently in progress */
14 uint8_t seq;
15};
16
17struct slotsim_instance {
18 struct slotsim_slot slot[NR_SLOTS];
19};
20
21static struct slotsim_instance g_si;
22
23struct slotsim_slot *ccid_slot2slotsim_slot(struct ccid_slot *cs)
24{
25 OSMO_ASSERT(cs->slot_nr < ARRAY_SIZE(g_si.slot));
26 return &g_si.slot[cs->slot_nr];
27}
28
Harald Welte29ae5d42019-05-16 17:40:29 +020029static const uint8_t sysmousim_sjs1_atr[] = {
30 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31,
31 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20,
32 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 };
33
Harald Weltecab5d152019-05-16 13:31:16 +020034static const struct ccid_pars_decoded slotsim_def_pars = {
Harald Welte860d0062019-05-18 11:18:39 +020035 .fi = 372,
36 .di = 1,
Harald Weltecab5d152019-05-16 13:31:16 +020037 .clock_stop = CCID_CLOCK_STOP_NOTALLOWED,
38 .inverse_convention = false,
39 .t0 = {
40 .guard_time_etu = 0,
41 .waiting_integer = 0,
42 },
43 /* FIXME: T=1 */
44};
45
46static void slotsim_pre_proc_cb(struct ccid_slot *cs, struct msgb *msg)
47{
48 /* do nothing; real hardware would update the slot related state here */
49}
50
Harald Welte505d4412019-05-16 17:26:09 +020051static void slotsim_icc_power_on_async(struct ccid_slot *cs, struct msgb *msg,
52 const struct ccid_pc_to_rdr_icc_power_on *ipo)
53{
54 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
55
56 ss->seq = ipo->hdr.bSeq;
Harald Welte29ae5d42019-05-16 17:40:29 +020057 LOGPCS(cs, LOGL_DEBUG, "scheduling pwron_timer\n");
Harald Welte505d4412019-05-16 17:26:09 +020058 osmo_timer_schedule(&ss->pwron_timer, 1, 0);
59 msgb_free(msg);
60 /* continues in timer call-back below */
61}
62static void slotsim_pwron_timer_cb(void *data)
63{
64 struct ccid_slot *cs = data;
65 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
66 struct msgb *resp;
67
Harald Welte29ae5d42019-05-16 17:40:29 +020068 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
69
70 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,
71 sysmousim_sjs1_atr, sizeof(sysmousim_sjs1_atr));
Harald Welte505d4412019-05-16 17:26:09 +020072 ccid_slot_send_unbusy(cs, resp);
73}
74
75static void slotsim_xfr_block_async(struct ccid_slot *cs, struct msgb *msg,
76 const struct ccid_pc_to_rdr_xfr_block *xfb)
77{
78 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
79
80 ss->seq = xfb->hdr.bSeq;
Harald Welte29ae5d42019-05-16 17:40:29 +020081 LOGPCS(cs, LOGL_DEBUG, "scheduling xfr_timer\n");
Harald Welte505d4412019-05-16 17:26:09 +020082 osmo_timer_schedule(&ss->xfr_timer, 0, 50000);
83 msgb_free(msg);
84 /* continues in timer call-back below */
85}
86static void slotsim_xfr_timer_cb(void *data)
87{
88 struct ccid_slot *cs = data;
89 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
90 struct msgb *resp;
91
Harald Welte29ae5d42019-05-16 17:40:29 +020092 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
93
Harald Welte505d4412019-05-16 17:26:09 +020094 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, NULL, 0);
95 ccid_slot_send_unbusy(cs, resp);
96}
97
98
Harald Weltecab5d152019-05-16 13:31:16 +020099static void slotsim_set_power(struct ccid_slot *cs, bool enable)
100{
101 if (enable) {
102 cs->icc_powered = true;
Harald Weltef999b682019-10-01 14:59:27 +0200103 cs->icc_in_reset = false;
Harald Weltecab5d152019-05-16 13:31:16 +0200104 } else {
105 cs->icc_powered = false;
Harald Weltef999b682019-10-01 14:59:27 +0200106 cs->icc_in_reset = true;
Harald Weltecab5d152019-05-16 13:31:16 +0200107 }
108}
109
110static void slotsim_set_clock(struct ccid_slot *cs, enum ccid_clock_command cmd)
111{
112 /* FIXME */
113 switch (cmd) {
114 case CCID_CLOCK_CMD_STOP:
115 break;
116 case CCID_CLOCK_CMD_RESTART:
117 break;
118 default:
119 OSMO_ASSERT(0);
120 }
121}
122
123static int slotsim_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,
124 const struct ccid_pars_decoded *pars_dec)
125{
126 /* we always acknowledge all parameters */
127 return 0;
128}
129
130static int slotsim_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps)
131{
132 /* we always acknowledge all rates/clocks */
133 return 0;
134}
135
Harald Welte505d4412019-05-16 17:26:09 +0200136
Harald Weltecab5d152019-05-16 13:31:16 +0200137static int slotsim_init(struct ccid_slot *cs)
138{
Harald Welte505d4412019-05-16 17:26:09 +0200139 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
Harald Welte29ae5d42019-05-16 17:40:29 +0200140
141 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
142 cs->icc_present = true;
143 cs->icc_powered = true;
Harald Welte505d4412019-05-16 17:26:09 +0200144 osmo_timer_setup(&ss->pwron_timer, slotsim_pwron_timer_cb, cs);
145 osmo_timer_setup(&ss->xfr_timer, slotsim_xfr_timer_cb, cs);
Harald Weltecab5d152019-05-16 13:31:16 +0200146 cs->default_pars = &slotsim_def_pars;
147 return 0;
148}
149
150const struct ccid_slot_ops slotsim_slot_ops = {
151 .init = slotsim_init,
152 .pre_proc_cb = slotsim_pre_proc_cb,
Harald Welte505d4412019-05-16 17:26:09 +0200153 .icc_power_on_async = slotsim_icc_power_on_async,
154 .xfr_block_async = slotsim_xfr_block_async,
Harald Weltecab5d152019-05-16 13:31:16 +0200155 .set_power = slotsim_set_power,
156 .set_clock = slotsim_set_clock,
157 .set_params = slotsim_set_params,
158 .set_rate_and_clock = slotsim_set_rate_and_clock,
159};