blob: 76279ecca9fda2e04b09894f79efad5f087498c7 [file] [log] [blame]
Harald Welte727d6752019-09-30 21:46:44 +02001/* Code providing a ccid_slot_ops implementation based on iso7716_fsm,
2 * (which in turn sits on top of card_uart) */
3
4#include <unistd.h>
5#include <errno.h>
6
7#include <osmocom/core/msgb.h>
8#include <osmocom/core/timer.h>
9#include <osmocom/core/logging.h>
10#include <osmocom/core/fsm.h>
11
12#include "ccid_device.h"
13#include "cuart.h"
14#include "iso7816_fsm.h"
15
16struct iso_fsm_slot {
17 /* CCID slot above us */
18 struct ccid_slot *cs;
19 /* main ISO7816-3 FSM instance beneath us */
20 struct osmo_fsm_inst *fi;
21 /* UART beneath the ISO7816-3 FSM */
22 struct card_uart *cuart;
23 /* bSeq of the operation currently in progress */
24 uint8_t seq;
25};
26
27struct iso_fsm_slot_instance {
28 struct iso_fsm_slot slot[NR_SLOTS];
29};
30
31static struct iso_fsm_slot_instance g_si;
32
Harald Welte4aab33f2019-09-28 23:19:31 +020033static struct iso_fsm_slot *ccid_slot2iso_fsm_slot(struct ccid_slot *cs)
Harald Welte727d6752019-09-30 21:46:44 +020034{
35 OSMO_ASSERT(cs->slot_nr < ARRAY_SIZE(g_si.slot));
36 return &g_si.slot[cs->slot_nr];
37}
38
Harald Welte4aab33f2019-09-28 23:19:31 +020039struct card_uart *cuart4slot_nr(uint8_t slot_nr)
40{
41 OSMO_ASSERT(slot_nr < ARRAY_SIZE(g_si.slot));
42 return g_si.slot[slot_nr].cuart;
43}
44
Harald Welte727d6752019-09-30 21:46:44 +020045static const uint8_t sysmousim_sjs1_atr[] = {
46 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31,
47 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20,
48 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 };
49
50static const struct ccid_pars_decoded iso_fsm_def_pars = {
51 .fi = 372,
52 .di = 1,
53 .clock_stop = CCID_CLOCK_STOP_NOTALLOWED,
54 .inverse_convention = false,
55 .t0 = {
56 .guard_time_etu = 0,
57 .waiting_integer = 0,
58 },
59 /* FIXME: T=1 */
60};
61
62static void iso_fsm_slot_pre_proc_cb(struct ccid_slot *cs, struct msgb *msg)
63{
64 /* do nothing; real hardware would update the slot related state here */
65}
66
67static void iso_fsm_slot_icc_power_on_async(struct ccid_slot *cs, struct msgb *msg,
68 const struct ccid_pc_to_rdr_icc_power_on *ipo)
69{
70 struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
71
72 ss->seq = ipo->hdr.bSeq;
73 LOGPCS(cs, LOGL_DEBUG, "scheduling power-up\n");
74
75 /* FIXME: do this via a FSM? */
76 card_uart_ctrl(ss->cuart, CUART_CTL_RST, true);
77 card_uart_ctrl(ss->cuart, CUART_CTL_POWER, true);
78 osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_POWER_UP_IND, NULL);
79 cs->icc_powered = true;
80 card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK, true);
81 usleep(10000);
82 card_uart_ctrl(ss->cuart, CUART_CTL_RST, false);
83 osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_RESET_REL_IND, NULL);
84
85 msgb_free(msg);
86 /* continues in iso_fsm_clot_user_cb once ATR is received */
87}
88static void iso_fsm_clot_user_cb(struct osmo_fsm_inst *fi, int event, int cause, void *data)
89{
90 struct iso_fsm_slot *ss = iso7816_fsm_get_user_priv(fi);
91 struct ccid_slot *cs = ss->cs;
92 struct msgb *tpdu, *resp;
93
94 LOGPCS(cs, LOGL_DEBUG, "%s(event=%d, cause=%d, data=%p)\n", __func__, event, cause, data);
95
96 switch (event) {
97 case ISO7816_E_ATR_DONE_IND:
98 tpdu = data;
99 /* FIXME: copy response data over */
100 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,
101 msgb_data(tpdu), msgb_length(tpdu));
102 ccid_slot_send_unbusy(cs, resp);
103 msgb_free(tpdu);
104 break;
105 case ISO7816_E_TPDU_DONE_IND:
106 tpdu = data;
107 /* FIXME: copy response data over */
108 resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_l2(tpdu), msgb_l2len(tpdu));
109 ccid_slot_send_unbusy(cs, resp);
110 msgb_free(tpdu);
111 break;
112 }
113}
114
115static void iso_fsm_slot_xfr_block_async(struct ccid_slot *cs, struct msgb *msg,
116 const struct ccid_pc_to_rdr_xfr_block *xfb)
117{
118 struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
119
120 LOGPCS(cs, LOGL_DEBUG, "scheduling TPDU transfer\n");
121 ss->seq = xfb->hdr.bSeq;
122 osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_TPDU_CMD, msg);
123 /* continues in iso_fsm_clot_user_cb once response/error/timeout is received */
124}
125
126
127static void iso_fsm_slot_set_power(struct ccid_slot *cs, bool enable)
128{
129 struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
130
131 if (enable) {
132 card_uart_ctrl(ss->cuart, CUART_CTL_POWER, true);
133 } else {
134 card_uart_ctrl(ss->cuart, CUART_CTL_POWER, false);
135 }
136}
137
138static void iso_fsm_slot_set_clock(struct ccid_slot *cs, enum ccid_clock_command cmd)
139{
140 struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
141
142 switch (cmd) {
143 case CCID_CLOCK_CMD_STOP:
144 card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK, false);
145 break;
146 case CCID_CLOCK_CMD_RESTART:
147 card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK, true);
148 break;
149 default:
150 OSMO_ASSERT(0);
151 }
152}
153
154static int iso_fsm_slot_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,
155 const struct ccid_pars_decoded *pars_dec)
156{
157 /* we always acknowledge all parameters */
158 return 0;
159}
160
161static int iso_fsm_slot_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps)
162{
163 /* we always acknowledge all rates/clocks */
164 return 0;
165}
166
167
168static int iso_fsm_slot_init(struct ccid_slot *cs)
169{
170 void *ctx = NULL; /* FIXME */
171 struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
172 struct card_uart *cuart = talloc_zero(ctx, struct card_uart);
173 char id_buf[16];
174 char *devname = "/dev/null";
175 int rc;
176
177 LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
178
179 if (cs->slot_nr == 0) {
180 cs->icc_present = true;
181 devname = "/dev/ttyUSB5";
182 }
183
184 if (!cuart)
185 return -ENOMEM;
186
187 snprintf(id_buf, sizeof(id_buf), "SIM%d", cs->slot_nr);
188 rc = card_uart_open(cuart, "tty", devname);
189 if (rc < 0) {
190 talloc_free(cuart);
191 return rc;
192 }
193 ss->fi = iso7816_fsm_alloc(ctx, LOGL_DEBUG, id_buf, cuart, iso_fsm_clot_user_cb, ss);
194 if (!ss->fi) {
195 talloc_free(cuart);
196 return -1;
197 }
198
199 cs->default_pars = &iso_fsm_def_pars;
200 ss->cuart = cuart;
201 ss->cs = cs;
202
203
204 return 0;
205}
206
207const struct ccid_slot_ops iso_fsm_slot_ops = {
208 .init = iso_fsm_slot_init,
209 .pre_proc_cb = iso_fsm_slot_pre_proc_cb,
210 .icc_power_on_async = iso_fsm_slot_icc_power_on_async,
211 .xfr_block_async = iso_fsm_slot_xfr_block_async,
212 .set_power = iso_fsm_slot_set_power,
213 .set_clock = iso_fsm_slot_set_clock,
214 .set_params = iso_fsm_slot_set_params,
215 .set_rate_and_clock = iso_fsm_slot_set_rate_and_clock,
216};