blob: c873c7370b250e518ca46dc72b9eec641e3892fb [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 Weltea67be5f2020-09-03 10:04:36 +02004/* (C) 2019-2020 by Harald Welte <laforge@gnumonks.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19 */
20
Harald Welte505d4412019-05-16 17:26:09 +020021#include <osmocom/core/msgb.h>
22#include <osmocom/core/timer.h>
Harald Welte29ae5d42019-05-16 17:40:29 +020023#include <osmocom/core/logging.h>
Harald Welte505d4412019-05-16 17:26:09 +020024
Harald Weltecab5d152019-05-16 13:31:16 +020025#include "ccid_device.h"
26
Harald Welte505d4412019-05-16 17:26:09 +020027struct slotsim_slot {
28 struct osmo_timer_list pwron_timer;
29 struct osmo_timer_list xfr_timer;
30 /* bSeq of the operation currently in progress */
31 uint8_t seq;
32};
33
34struct slotsim_instance {
35 struct slotsim_slot slot[NR_SLOTS];
36};
37
38static struct slotsim_instance g_si;
39
40struct slotsim_slot *ccid_slot2slotsim_slot(struct ccid_slot *cs)
41{
42 OSMO_ASSERT(cs->slot_nr < ARRAY_SIZE(g_si.slot));
43 return &g_si.slot[cs->slot_nr];
44}
45
Harald Welte29ae5d42019-05-16 17:40:29 +020046static const uint8_t sysmousim_sjs1_atr[] = {
47 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31,
48 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20,
49 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 };
50
Harald Weltecab5d152019-05-16 13:31:16 +020051static const struct ccid_pars_decoded slotsim_def_pars = {
Harald Welte860d0062019-05-18 11:18:39 +020052 .fi = 372,
53 .di = 1,
Harald Weltecab5d152019-05-16 13:31:16 +020054 .clock_stop = CCID_CLOCK_STOP_NOTALLOWED,
55 .inverse_convention = false,
56 .t0 = {
57 .guard_time_etu = 0,
58 .waiting_integer = 0,
59 },
60 /* FIXME: T=1 */
61};
62
63static void slotsim_pre_proc_cb(struct ccid_slot *cs, struct msgb *msg)
64{
65 /* do nothing; real hardware would update the slot related state here */
66}
67
Harald Welte505d4412019-05-16 17:26:09 +020068static void slotsim_icc_power_on_async(struct ccid_slot *cs, struct msgb *msg,
69 const struct ccid_pc_to_rdr_icc_power_on *ipo)
70{
71 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
72
73 ss->seq = ipo->hdr.bSeq;
Harald Welte29ae5d42019-05-16 17:40:29 +020074 LOGPCS(cs, LOGL_DEBUG, "scheduling pwron_timer\n");
Harald Welte505d4412019-05-16 17:26:09 +020075 osmo_timer_schedule(&ss->pwron_timer, 1, 0);
76 msgb_free(msg);
77 /* continues in timer call-back below */
78}
79static void slotsim_pwron_timer_cb(void *data)
80{
81 struct ccid_slot *cs = data;
82 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
83 struct msgb *resp;
84
Harald Welte29ae5d42019-05-16 17:40:29 +020085 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
86
87 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,
88 sysmousim_sjs1_atr, sizeof(sysmousim_sjs1_atr));
Harald Welte505d4412019-05-16 17:26:09 +020089 ccid_slot_send_unbusy(cs, resp);
90}
91
92static void slotsim_xfr_block_async(struct ccid_slot *cs, struct msgb *msg,
93 const struct ccid_pc_to_rdr_xfr_block *xfb)
94{
95 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
96
97 ss->seq = xfb->hdr.bSeq;
Harald Welte29ae5d42019-05-16 17:40:29 +020098 LOGPCS(cs, LOGL_DEBUG, "scheduling xfr_timer\n");
Harald Welte505d4412019-05-16 17:26:09 +020099 osmo_timer_schedule(&ss->xfr_timer, 0, 50000);
100 msgb_free(msg);
101 /* continues in timer call-back below */
102}
103static void slotsim_xfr_timer_cb(void *data)
104{
105 struct ccid_slot *cs = data;
106 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
107 struct msgb *resp;
108
Harald Welte29ae5d42019-05-16 17:40:29 +0200109 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
110
Harald Welte505d4412019-05-16 17:26:09 +0200111 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, NULL, 0);
112 ccid_slot_send_unbusy(cs, resp);
113}
114
115
Harald Weltecab5d152019-05-16 13:31:16 +0200116static void slotsim_set_power(struct ccid_slot *cs, bool enable)
117{
118 if (enable) {
119 cs->icc_powered = true;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200120 cs->icc_in_reset = false;
Harald Weltecab5d152019-05-16 13:31:16 +0200121 } else {
122 cs->icc_powered = false;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200123 cs->icc_in_reset = true;
Harald Weltecab5d152019-05-16 13:31:16 +0200124 }
125}
126
127static void slotsim_set_clock(struct ccid_slot *cs, enum ccid_clock_command cmd)
128{
129 /* FIXME */
130 switch (cmd) {
131 case CCID_CLOCK_CMD_STOP:
132 break;
133 case CCID_CLOCK_CMD_RESTART:
134 break;
135 default:
136 OSMO_ASSERT(0);
137 }
138}
139
140static int slotsim_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,
141 const struct ccid_pars_decoded *pars_dec)
142{
143 /* we always acknowledge all parameters */
144 return 0;
145}
146
147static int slotsim_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps)
148{
149 /* we always acknowledge all rates/clocks */
150 return 0;
151}
152
Harald Welte505d4412019-05-16 17:26:09 +0200153
Harald Weltecab5d152019-05-16 13:31:16 +0200154static int slotsim_init(struct ccid_slot *cs)
155{
Harald Welte505d4412019-05-16 17:26:09 +0200156 struct slotsim_slot *ss = ccid_slot2slotsim_slot(cs);
Harald Welte29ae5d42019-05-16 17:40:29 +0200157
158 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
159 cs->icc_present = true;
160 cs->icc_powered = true;
Harald Welte505d4412019-05-16 17:26:09 +0200161 osmo_timer_setup(&ss->pwron_timer, slotsim_pwron_timer_cb, cs);
162 osmo_timer_setup(&ss->xfr_timer, slotsim_xfr_timer_cb, cs);
Harald Weltecab5d152019-05-16 13:31:16 +0200163 cs->default_pars = &slotsim_def_pars;
164 return 0;
165}
166
167const struct ccid_slot_ops slotsim_slot_ops = {
168 .init = slotsim_init,
169 .pre_proc_cb = slotsim_pre_proc_cb,
Harald Welte505d4412019-05-16 17:26:09 +0200170 .icc_power_on_async = slotsim_icc_power_on_async,
171 .xfr_block_async = slotsim_xfr_block_async,
Harald Weltecab5d152019-05-16 13:31:16 +0200172 .set_power = slotsim_set_power,
173 .set_clock = slotsim_set_clock,
174 .set_params = slotsim_set_params,
175 .set_rate_and_clock = slotsim_set_rate_and_clock,
176};