blob: cad24b8115cda58d64042b968fbe0b8740b1f79e [file] [log] [blame]
Kévin Redon9a12d682018-07-08 13:21:16 +02001/* ISO7816-3 state machine for the card side
Harald Welte9d3e3822015-11-09 00:50:54 +01002 *
Harald Weltee92cb502019-12-14 21:48:45 +01003 * (C) 2010-2019 by Harald Welte <laforge@gnumonks.org>
Kévin Redonebe672e2018-07-29 00:18:12 +02004 * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
Harald Welte9d3e3822015-11-09 00:50:54 +01005 *
Kévin Redon9a12d682018-07-08 13:21:16 +02006 * 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.
Harald Welte9d3e3822015-11-09 00:50:54 +010010 *
Kévin Redon9a12d682018-07-08 13:21:16 +020011 * 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.
Harald Welte9d3e3822015-11-09 00:50:54 +010015 *
Kévin Redon9a12d682018-07-08 13:21:16 +020016 * 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
Harald Welte9d3e3822015-11-09 00:50:54 +010019 */
Harald Weltec430ac12017-02-28 01:25:12 +010020#include <stdio.h>
Harald Welte4c473da2015-11-14 13:31:11 +010021#include <assert.h>
Harald Welte9d3e3822015-11-09 00:50:54 +010022#include <errno.h>
23#include <string.h>
24#include <stdint.h>
25#include <sys/types.h>
26
27#include "utils.h"
28#include "trace.h"
29#include "iso7816_fidi.h"
30#include "tc_etu.h"
31#include "card_emu.h"
Harald Welte25a9a802017-05-08 13:30:09 +020032#include "simtrace_prot.h"
Harald Welte8e7fca32017-05-07 16:14:33 +020033#include "usb_buf.h"
Harald Welte9d90d282018-06-29 22:25:42 +020034#include <osmocom/core/linuxlist.h>
35#include <osmocom/core/msgb.h>
Harald Welte9d3e3822015-11-09 00:50:54 +010036
37
38#define NUM_SLOTS 2
39
Harald Weltea5bbe782019-12-16 10:39:55 +010040/* bit-mask of supported CEMU_FEAT_F_ flags */
Harald Weltee213cc42019-12-16 10:53:22 +010041#define SUPPORTED_FEATURES (CEMU_FEAT_F_STATUS_IRQ)
Harald Weltea5bbe782019-12-16 10:39:55 +010042
Harald Welte9d3e3822015-11-09 00:50:54 +010043#define ISO7816_3_INIT_WTIME 9600
44#define ISO7816_3_DEFAULT_WI 10
45#define ISO7816_3_ATR_LEN_MAX (1+32) /* TS plus 32 chars */
46
47#define ISO7816_3_PB_NULL 0x60
48
49enum iso7816_3_card_state {
50 ISO_S_WAIT_POWER, /* waiting for power being applied */
51 ISO_S_WAIT_CLK, /* waiting for clock being applied */
52 ISO_S_WAIT_RST, /* waiting for reset being released */
53 ISO_S_WAIT_ATR, /* waiting for start of ATR */
54 ISO_S_IN_ATR, /* transmitting ATR to reader */
55 ISO_S_IN_PTS, /* transmitting ATR to reader */
56 ISO_S_WAIT_TPDU, /* waiting for data from reader */
57 ISO_S_IN_TPDU, /* inside a TPDU */
58};
59
Kévin Redon8a4fba52018-08-02 17:44:16 +020060const struct value_string iso7816_3_card_state_names[] = {
Harald Weltebfd27af2019-12-17 12:53:59 +010061 { ISO_S_WAIT_POWER, "WAIT_POWER" },
62 { ISO_S_WAIT_CLK, "WAIT_CLK" },
63 { ISO_S_WAIT_RST, "WAIT_RST" },
64 { ISO_S_WAIT_ATR, "WAIT_ATR" },
65 { ISO_S_IN_ATR, "IN_ATR" },
66 { ISO_S_IN_PTS, "IN_PTS" },
67 { ISO_S_WAIT_TPDU, "WAIT_TPDU" },
68 { ISO_S_IN_TPDU, "IN_TPDU" },
69 { 0, NULL }
Kévin Redon8a4fba52018-08-02 17:44:16 +020070};
71
72
Harald Welte9d3e3822015-11-09 00:50:54 +010073/* detailed sub-states of ISO_S_IN_PTS */
74enum pts_state {
75 PTS_S_WAIT_REQ_PTSS,
76 PTS_S_WAIT_REQ_PTS0,
77 PTS_S_WAIT_REQ_PTS1,
78 PTS_S_WAIT_REQ_PTS2,
79 PTS_S_WAIT_REQ_PTS3,
80 PTS_S_WAIT_REQ_PCK,
81 PTS_S_WAIT_RESP_PTSS = PTS_S_WAIT_REQ_PTSS | 0x10,
82 PTS_S_WAIT_RESP_PTS0 = PTS_S_WAIT_REQ_PTS0 | 0x10,
83 PTS_S_WAIT_RESP_PTS1 = PTS_S_WAIT_REQ_PTS1 | 0x10,
84 PTS_S_WAIT_RESP_PTS2 = PTS_S_WAIT_REQ_PTS2 | 0x10,
85 PTS_S_WAIT_RESP_PTS3 = PTS_S_WAIT_REQ_PTS3 | 0x10,
86 PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
87};
88
Harald Welte6a3a7142019-12-16 14:23:02 +010089const struct value_string pts_state_names[] = {
90 { PTS_S_WAIT_REQ_PTSS, "WAIT_REQ_PTSS" },
91 { PTS_S_WAIT_REQ_PTS0, "WAIT_REQ_PTS0" },
92 { PTS_S_WAIT_REQ_PTS1, "WAIT_REQ_PTS1" },
93 { PTS_S_WAIT_REQ_PTS2, "WAIT_REQ_PTS2" },
94 { PTS_S_WAIT_REQ_PTS3, "WAIT_REQ_PTS3" },
95 { PTS_S_WAIT_REQ_PCK, "WAIT_REQ_PCK" },
96 { PTS_S_WAIT_RESP_PTSS, "WAIT_RESP_PTSS" },
97 { PTS_S_WAIT_RESP_PTS0, "WAIT_RESP_PTS0" },
98 { PTS_S_WAIT_RESP_PTS1, "WAIT_RESP_PTS1" },
99 { PTS_S_WAIT_RESP_PTS2, "WAIT_RESP_PTS2" },
100 { PTS_S_WAIT_RESP_PTS3, "WAIT_RESP_PTS3" },
101 { PTS_S_WAIT_RESP_PCK, "WAIT_RESP_PCK" },
102 { 0, NULL }
103};
104
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200105/* PTS field byte index */
Harald Welte9d3e3822015-11-09 00:50:54 +0100106#define _PTSS 0
107#define _PTS0 1
108#define _PTS1 2
109#define _PTS2 3
110#define _PTS3 4
111#define _PCK 5
112
Harald Welte16cf4082015-11-11 19:02:48 +0100113/* T-PDU state machine states */
Harald Welte9d3e3822015-11-09 00:50:54 +0100114enum tpdu_state {
Harald Welte16cf4082015-11-11 19:02:48 +0100115 TPDU_S_WAIT_CLA, /* waiting for CLA byte from reader */
116 TPDU_S_WAIT_INS, /* waiting for INS byte from reader */
117 TPDU_S_WAIT_P1, /* waiting for P1 byte from reader */
118 TPDU_S_WAIT_P2, /* waiting for P2 byte from reader */
119 TPDU_S_WAIT_P3, /* waiting for P3 byte from reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100120 TPDU_S_WAIT_PB, /* waiting for Tx of procedure byte */
Kévin Redon0f4abf52018-08-02 17:42:48 +0200121 TPDU_S_WAIT_RX, /* waiting for more data from reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100122 TPDU_S_WAIT_TX, /* waiting for more data to reader */
123};
124
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200125const struct value_string tpdu_state_names[] = {
Harald Weltebfd27af2019-12-17 12:53:59 +0100126 { TPDU_S_WAIT_CLA, "WAIT_CLA" },
127 { TPDU_S_WAIT_INS, "WAIT_INS" },
128 { TPDU_S_WAIT_P1, "WAIT_P1" },
129 { TPDU_S_WAIT_P2, "WAIT_P2" },
130 { TPDU_S_WAIT_P3, "WAIT_P3" },
131 { TPDU_S_WAIT_PB, "WAIT_PB" },
132 { TPDU_S_WAIT_RX, "WAIT_RX" },
133 { TPDU_S_WAIT_TX, "WAIT_TX" },
134 { 0, NULL }
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200135};
136
137/* TPDU field byte index */
Harald Welte9d3e3822015-11-09 00:50:54 +0100138#define _CLA 0
139#define _INS 1
140#define _P1 2
141#define _P2 3
142#define _P3 4
143
144struct card_handle {
Harald Weltec3941092018-08-26 09:53:13 +0200145 unsigned int num;
Harald Weltedde112e2016-03-20 16:42:11 +0100146
Harald Weltea5bbe782019-12-16 10:39:55 +0100147 /* bit-mask of enabled optional features (CEMU_FEAT_F_*) */
148 uint32_t features;
149
Harald Welte9d3e3822015-11-09 00:50:54 +0100150 enum iso7816_3_card_state state;
151
152 /* signal levels */
Kévin Redon7233cf82019-11-14 19:37:32 +0100153 bool vcc_active; /*< if VCC is active (true = active/ON) */
154 bool in_reset; /*< if card is in reset (true = RST low/asserted, false = RST high/ released) */
155 bool clocked; /*< if clock is active ( true = active, false = inactive) */
Harald Welte9d3e3822015-11-09 00:50:54 +0100156
Harald Welte16cf4082015-11-11 19:02:48 +0100157 /* timing parameters, from PTS */
Harald Welte9d3e3822015-11-09 00:50:54 +0100158 uint8_t fi;
159 uint8_t di;
160 uint8_t wi;
161
162 uint8_t tc_chan; /* TC channel number */
163 uint8_t uart_chan; /* UART channel */
164
Harald Welte8e7fca32017-05-07 16:14:33 +0200165 uint8_t in_ep; /* USB IN EP */
166 uint8_t irq_ep; /* USB IN EP */
167
Harald Welte9d3e3822015-11-09 00:50:54 +0100168 uint32_t waiting_time; /* in clocks */
169
170 /* ATR state machine */
171 struct {
172 uint8_t idx;
173 uint8_t len;
174 //uint8_t hist_len;
175 //uint8_t last_td;
176 uint8_t atr[ISO7816_3_ATR_LEN_MAX];
177 } atr;
178
179 /* PPS / PTS support */
180 struct {
181 enum pts_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100182 uint8_t req[6]; /* request bytes */
183 uint8_t resp[6]; /* response bytes */
Harald Welte9d3e3822015-11-09 00:50:54 +0100184 } pts;
185
186 /* TPDU */
187 struct {
188 enum tpdu_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100189 uint8_t hdr[5]; /* CLA INS P1 P2 P3 */
Harald Welte9d3e3822015-11-09 00:50:54 +0100190 } tpdu;
191
Harald Welte8e7fca32017-05-07 16:14:33 +0200192 struct msgb *uart_rx_msg; /* UART RX -> USB TX */
193 struct msgb *uart_tx_msg; /* USB RX -> UART TX */
Harald Welte9d3e3822015-11-09 00:50:54 +0100194
Harald Welte54cb3d02016-02-29 14:12:40 +0100195 struct llist_head uart_tx_queue;
196
Harald Welte9d3e3822015-11-09 00:50:54 +0100197 struct {
198 uint32_t tx_bytes;
199 uint32_t rx_bytes;
200 uint32_t pps;
201 } stats;
202};
203
Harald Weltee92cb502019-12-14 21:48:45 +0100204/* reset all the 'dynamic' state of the card handle to the initial/default values */
205static void card_handle_reset(struct card_handle *ch)
206{
Harald Welte81f4ef72019-12-14 22:20:00 +0100207 struct msgb *msg;
208
209 tc_etu_disable(ch->tc_chan);
210
Harald Welte81f4ef72019-12-14 22:20:00 +0100211 /* release any buffers we may still own */
212 if (ch->uart_tx_msg) {
213 usb_buf_free(ch->uart_tx_msg);
214 ch->uart_tx_msg = NULL;
215 }
216 if (ch->uart_rx_msg) {
217 usb_buf_free(ch->uart_rx_msg);
218 ch->uart_rx_msg = NULL;
219 }
220 while ((msg = msgb_dequeue(&ch->uart_tx_queue))) {
221 usb_buf_free(msg);
222 }
Harald Weltee92cb502019-12-14 21:48:45 +0100223}
224
Harald Welte54cb3d02016-02-29 14:12:40 +0100225struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch)
226{
227 return &ch->uart_tx_queue;
228}
229
Harald Welte2935b3c2015-11-14 20:00:14 +0100230static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts);
Harald Weltee7194ab2015-11-14 21:03:25 +0100231static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss);
Harald Welte2935b3c2015-11-14 20:00:14 +0100232
Harald Welte25a9a802017-05-08 13:30:09 +0200233/* update simtrace header msg_len and submit USB buffer */
234void usb_buf_upd_len_and_submit(struct msgb *msg)
235{
Harald Welteb91f6ad2017-05-10 22:51:30 +0200236 struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte25a9a802017-05-08 13:30:09 +0200237
238 sh->msg_len = msgb_length(msg);
239
240 usb_buf_submit(msg);
241}
242
243/* Allocate USB buffer and push + initialize simtrace_msg_hdr */
244struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
245{
Kévin Redonc90de692019-11-18 22:32:58 +0100246 struct msgb *msg = NULL;
Harald Welte25a9a802017-05-08 13:30:09 +0200247 struct simtrace_msg_hdr *sh;
248
Kévin Redonc90de692019-11-18 22:32:58 +0100249 while (!msg) {
250 msg = usb_buf_alloc(ep); // try to allocate some memory
251 if (!msg) { // allocation failed, we might be out of memory
Harald Weltef4a625b2019-12-14 19:07:57 +0100252 struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
253 if (!bep) {
Kévin Redonc90de692019-11-18 22:32:58 +0100254 TRACE_ERROR("ep %u: %s queue does not exist\n\r",
255 ep, __func__);
256 return NULL;
257 }
Harald Weltef4a625b2019-12-14 19:07:57 +0100258 if (llist_empty(&bep->queue)) {
Kévin Redonc90de692019-11-18 22:32:58 +0100259 TRACE_ERROR("ep %u: %s EOMEM (queue already empty)\n\r",
260 ep, __func__);
261 return NULL;
262 }
Harald Weltef4a625b2019-12-14 19:07:57 +0100263 msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
Kévin Redonc90de692019-11-18 22:32:58 +0100264 if (!msg) {
265 TRACE_ERROR("ep %u: %s no msg in non-empty queue\n\r",
266 ep, __func__);
267 return NULL;
268 }
269 usb_buf_free(msg);
270 msg = NULL;
271 TRACE_DEBUG("ep %u: %s queue msg dropped\n\r",
272 ep, __func__);
273 }
274 }
Harald Welte25a9a802017-05-08 13:30:09 +0200275
276 msg->l1h = msgb_put(msg, sizeof(*sh));
277 sh = (struct simtrace_msg_hdr *) msg->l1h;
278 memset(sh, 0, sizeof(*sh));
279 sh->msg_class = msg_class;
280 sh->msg_type = msg_type;
281 msg->l2h = msg->l1h + sizeof(*sh);
282
283 return msg;
284}
285
Kévin Redon680bdab2018-07-18 14:00:57 +0200286/* Update cardemu_usb_msg_rx_data length + submit buffer */
Harald Welteb5288e82015-11-14 21:15:52 +0100287static void flush_rx_buffer(struct card_handle *ch)
288{
Harald Welte8e7fca32017-05-07 16:14:33 +0200289 struct msgb *msg;
Harald Welteb5288e82015-11-14 21:15:52 +0100290 struct cardemu_usb_msg_rx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200291 uint32_t data_len;
Harald Welteb5288e82015-11-14 21:15:52 +0100292
Harald Welte8e7fca32017-05-07 16:14:33 +0200293 msg = ch->uart_rx_msg;
294 if (!msg)
Harald Welteb5288e82015-11-14 21:15:52 +0100295 return;
296
Harald Welte8e7fca32017-05-07 16:14:33 +0200297 ch->uart_rx_msg = NULL;
Harald Welteb5288e82015-11-14 21:15:52 +0100298
Kévin Redon680bdab2018-07-18 14:00:57 +0200299 /* store length of data payload field in header */
Harald Welte25a9a802017-05-08 13:30:09 +0200300 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
301 rd->data_len = msgb_l2len(msg) - sizeof(*rd);
Harald Welte54cb3d02016-02-29 14:12:40 +0100302
Kévin Redon910e6832018-08-02 17:47:57 +0200303 TRACE_INFO("%u: %s (%u)\n\r",
304 ch->num, __func__, rd->data_len);
305
Harald Welte25a9a802017-05-08 13:30:09 +0200306 usb_buf_upd_len_and_submit(msg);
Harald Welteb5288e82015-11-14 21:15:52 +0100307}
308
Kévin Redon680bdab2018-07-18 14:00:57 +0200309/* convert a non-contiguous PTS request/response into a contiguous
Harald Welte4ba66d02016-02-25 19:38:56 +0100310 * buffer, returning the number of bytes used in the buffer */
311static int serialize_pts(uint8_t *out, const uint8_t *in)
312{
313 int i = 0;
314
315 out[i++] = in[_PTSS];
316 out[i++] = in[_PTS0];
317 if (in[_PTS0] & (1 << 4))
318 out[i++] = in[_PTS1];
319 if (in[_PTS0] & (1 << 5))
320 out[i++] = in[_PTS2];
321 if (in[_PTS0] & (1 << 6))
322 out[i++] = in[_PTS3];
323 out[i++] = in[_PCK];
324
325 return i;
326}
327
Harald Welte17db2f12016-02-26 09:48:57 +0100328static uint8_t csum_pts(const uint8_t *in)
329{
330 uint8_t out[6];
331 int len = serialize_pts(out, in);
332 uint8_t csum = 0;
333 int i;
334
335 /* we don't include the PCK byte in the checksumming process */
336 len -= 1;
337
338 for (i = 0; i < len; i++)
339 csum = csum ^ out[i];
340
341 return csum;
342}
343
Harald Welte4ba66d02016-02-25 19:38:56 +0100344static void flush_pts(struct card_handle *ch)
345{
Harald Welte8e7fca32017-05-07 16:14:33 +0200346 struct msgb *msg;
Harald Welte4ba66d02016-02-25 19:38:56 +0100347 struct cardemu_usb_msg_pts_info *ptsi;
348
Harald Welte25a9a802017-05-08 13:30:09 +0200349 msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte8e7fca32017-05-07 16:14:33 +0200350 if (!msg)
Harald Welte4ba66d02016-02-25 19:38:56 +0100351 return;
352
Harald Welte25a9a802017-05-08 13:30:09 +0200353 ptsi = (struct cardemu_usb_msg_pts_info *) msgb_put(msg, sizeof(*ptsi));
Harald Welted295b922016-03-18 21:01:36 +0100354 ptsi->pts_len = serialize_pts(ptsi->req, ch->pts.req);
Harald Welte4ba66d02016-02-25 19:38:56 +0100355 serialize_pts(ptsi->resp, ch->pts.resp);
356
Harald Welte25a9a802017-05-08 13:30:09 +0200357 usb_buf_upd_len_and_submit(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100358}
359
Harald Welte8c496362016-02-27 16:24:09 +0100360static void emu_update_fidi(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100361{
362 int rc;
363
364 rc = compute_fidi_ratio(ch->fi, ch->di);
365 if (rc > 0 && rc < 0x400) {
Harald Weltedde112e2016-03-20 16:42:11 +0100366 TRACE_INFO("%u: computed Fi(%u) Di(%u) ratio: %d\r\n",
367 ch->num, ch->fi, ch->di, rc);
Harald Welte9d3e3822015-11-09 00:50:54 +0100368 /* make sure UART uses new F/D ratio */
369 card_emu_uart_update_fidi(ch->uart_chan, rc);
370 /* notify ETU timer about this */
371 tc_etu_set_etu(ch->tc_chan, rc);
372 } else
Harald Weltedde112e2016-03-20 16:42:11 +0100373 TRACE_INFO("%u: computed FiDi ration %d unsupported\r\n",
374 ch->num, rc);
Harald Welte9d3e3822015-11-09 00:50:54 +0100375}
376
377/* Update the ISO 7816-3 TPDU receiver state */
378static void card_set_state(struct card_handle *ch,
379 enum iso7816_3_card_state new_state)
380{
Harald Welte903d63a2016-03-20 13:38:39 +0100381 if (ch->state == new_state)
382 return;
383
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200384 TRACE_DEBUG("%u: 7816 card state %s -> %s\r\n", ch->num,
385 get_value_string(iso7816_3_card_state_names, ch->state),
386 get_value_string(iso7816_3_card_state_names, new_state));
Harald Welte903d63a2016-03-20 13:38:39 +0100387 ch->state = new_state;
388
Harald Welte9d3e3822015-11-09 00:50:54 +0100389 switch (new_state) {
390 case ISO_S_WAIT_POWER:
391 case ISO_S_WAIT_CLK:
392 case ISO_S_WAIT_RST:
393 /* disable Rx and Tx of UART */
394 card_emu_uart_enable(ch->uart_chan, 0);
395 break;
396 case ISO_S_WAIT_ATR:
397 /* Reset to initial Fi / Di ratio */
398 ch->fi = 1;
399 ch->di = 1;
Harald Welte8c496362016-02-27 16:24:09 +0100400 emu_update_fidi(ch);
Kévin Redonebe672e2018-07-29 00:18:12 +0200401 /* the ATR should only be sent 400 to 40k clock cycles after the RESET.
402 * we use the tc_etu mechanism to wait this time.
403 * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
404 */
405 tc_etu_set_wtime(ch->tc_chan, 2);
Harald Welte4d4405f2019-12-15 13:23:51 +0100406 /* enable the TC/ETU counter once reset has been released */
Kévin Redonebe672e2018-07-29 00:18:12 +0200407 tc_etu_enable(ch->tc_chan);
408 break;
409 case ISO_S_IN_ATR:
Kévin Redon680bdab2018-07-18 14:00:57 +0200410 /* initialize to default WI, this will be overwritten if we
Kévin Redonebe672e2018-07-29 00:18:12 +0200411 * send TC2, and it will be programmed into hardware after
Harald Welte9d3e3822015-11-09 00:50:54 +0100412 * ATR is finished */
413 ch->wi = ISO7816_3_DEFAULT_WI;
414 /* update waiting time to initial waiting time */
415 ch->waiting_time = ISO7816_3_INIT_WTIME;
Kévin Redonebe672e2018-07-29 00:18:12 +0200416 /* set initial waiting time */
Harald Welte9d3e3822015-11-09 00:50:54 +0100417 tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
418 /* Set ATR sub-state to initial state */
419 ch->atr.idx = 0;
Kévin Redonebe672e2018-07-29 00:18:12 +0200420 /* enable USART transmission to reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100421 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
Kévin Redonebe672e2018-07-29 00:18:12 +0200422 /* trigger USART TX IRQ to sent first ATR byte TS */
423 card_emu_uart_interrupt(ch->uart_chan);
Harald Welte9d3e3822015-11-09 00:50:54 +0100424 break;
425 case ISO_S_WAIT_TPDU:
426 /* enable the receiver, disable transmitter */
Harald Welte2935b3c2015-11-14 20:00:14 +0100427 set_tpdu_state(ch, TPDU_S_WAIT_CLA);
Harald Welte9d3e3822015-11-09 00:50:54 +0100428 card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
429 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100430 case ISO_S_IN_PTS:
431 case ISO_S_IN_TPDU:
432 /* do nothing */
433 break;
434 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100435}
436
Kévin Redonebe672e2018-07-29 00:18:12 +0200437/**********************************************************************
438 * ATR handling
439 **********************************************************************/
440
441/*! Transmit ATR data to reader
442 * @param[in] ch card interface connected to reader
443 * @return numbers of bytes transmitted
444 */
445static int tx_byte_atr(struct card_handle *ch)
446{
447 if (NULL == ch) {
448 TRACE_ERROR("ATR TX: no card handle provided\n\r");
449 return 0;
450 }
451 if (ISO_S_IN_ATR != ch->state) {
452 TRACE_ERROR("%u: ATR TX: no in ATR state\n\r", ch->num);
453 return 0;
454 }
455
456 /* Transmit ATR */
457 if (ch->atr.idx < ch->atr.len) {
458 uint8_t byte = ch->atr.atr[ch->atr.idx++];
459 card_emu_uart_tx(ch->uart_chan, byte);
Kévin Redonebe672e2018-07-29 00:18:12 +0200460 return 1;
461 } else { /* The ATR has been completely transmitted */
Kévin Redon8b8e58b2018-07-30 18:19:11 +0200462 /* search for TC2 to updated WI */
463 ch->wi = ISO7816_3_DEFAULT_WI;
464 if (ch->atr.len >= 2 && ch->atr.atr[1] & 0xf0) { /* Y1 has some data */
465 uint8_t atr_td1 = 2;
466 if (ch->atr.atr[1] & 0x10) { /* TA1 is present */
467 atr_td1++;
468 }
469 if (ch->atr.atr[1] & 0x20) { /* TB1 is present */
470 atr_td1++;
471 }
472 if (ch->atr.atr[1] & 0x40) { /* TC1 is present */
473 atr_td1++;
474 }
475 if (ch->atr.atr[1] & 0x80) { /* TD1 is present */
476 if (ch->atr.len > atr_td1 && ch->atr.atr[atr_td1] & 0xf0) { /* Y2 has some data */
477 uint8_t atr_tc2 = atr_td1+1;
478 if (ch->atr.atr[atr_td1] & 0x10) { /* TA2 is present */
479 atr_tc2++;
480 }
481 if (ch->atr.atr[atr_td1] & 0x20) { /* TB2 is present */
482 atr_tc2++;
483 }
484 if (ch->atr.atr[atr_td1] & 0x40) { /* TC2 is present */
485 if (ch->atr.len > atr_tc2 && ch->atr.atr[atr_tc2]) { /* TC2 encodes WI */
486 ch->wi = ch->atr.atr[atr_tc2]; /* set WI */
487 }
488 }
489 }
490 }
491 }
492 /* update waiting time (see ISO 7816-3 10.2) */
493 ch->waiting_time = ch->wi * 960 * ch->fi;
494 tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
Kévin Redonebe672e2018-07-29 00:18:12 +0200495 /* go to next state */
496 card_set_state(ch, ISO_S_WAIT_TPDU);
497 return 0;
498 }
499
500 /* return number of bytes transmitted */
501 return 1;
502}
Harald Welte9d3e3822015-11-09 00:50:54 +0100503
504/**********************************************************************
505 * PTS / PPS handling
506 **********************************************************************/
507
Kévin Redon680bdab2018-07-18 14:00:57 +0200508/* Update the PTS sub-state */
Harald Welte9d3e3822015-11-09 00:50:54 +0100509static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss)
510{
Harald Welte6a3a7142019-12-16 14:23:02 +0100511 TRACE_DEBUG("%u: 7816 PTS state %s -> %s\r\n", ch->num,
512 get_value_string(pts_state_names, ch->pts.state),
513 get_value_string(pts_state_names, new_ptss));
Harald Welte9d3e3822015-11-09 00:50:54 +0100514 ch->pts.state = new_ptss;
515}
516
517/* Determine the next PTS state */
518static enum pts_state next_pts_state(struct card_handle *ch)
519{
520 uint8_t is_resp = ch->pts.state & 0x10;
521 uint8_t sstate = ch->pts.state & 0x0f;
522 uint8_t *pts_ptr;
523
524 if (!is_resp)
525 pts_ptr = ch->pts.req;
526 else
527 pts_ptr = ch->pts.resp;
528
529 switch (sstate) {
530 case PTS_S_WAIT_REQ_PTSS:
531 goto from_ptss;
532 case PTS_S_WAIT_REQ_PTS0:
533 goto from_pts0;
534 case PTS_S_WAIT_REQ_PTS1:
535 goto from_pts1;
536 case PTS_S_WAIT_REQ_PTS2:
537 goto from_pts2;
538 case PTS_S_WAIT_REQ_PTS3:
539 goto from_pts3;
540 }
541
542 if (ch->pts.state == PTS_S_WAIT_REQ_PCK)
543 return PTS_S_WAIT_RESP_PTSS;
544
545from_ptss:
546 return PTS_S_WAIT_REQ_PTS0 | is_resp;
547from_pts0:
548 if (pts_ptr[_PTS0] & (1 << 4))
549 return PTS_S_WAIT_REQ_PTS1 | is_resp;
550from_pts1:
551 if (pts_ptr[_PTS0] & (1 << 5))
552 return PTS_S_WAIT_REQ_PTS2 | is_resp;
553from_pts2:
554 if (pts_ptr[_PTS0] & (1 << 6))
555 return PTS_S_WAIT_REQ_PTS3 | is_resp;
556from_pts3:
557 return PTS_S_WAIT_REQ_PCK | is_resp;
558}
559
560
Harald Welteccb8a222016-03-20 13:37:11 +0100561static int
Harald Welte9d3e3822015-11-09 00:50:54 +0100562process_byte_pts(struct card_handle *ch, uint8_t byte)
563{
564 switch (ch->pts.state) {
565 case PTS_S_WAIT_REQ_PTSS:
566 ch->pts.req[_PTSS] = byte;
567 break;
568 case PTS_S_WAIT_REQ_PTS0:
569 ch->pts.req[_PTS0] = byte;
570 break;
571 case PTS_S_WAIT_REQ_PTS1:
572 ch->pts.req[_PTS1] = byte;
573 break;
574 case PTS_S_WAIT_REQ_PTS2:
575 ch->pts.req[_PTS2] = byte;
576 break;
577 case PTS_S_WAIT_REQ_PTS3:
578 ch->pts.req[_PTS3] = byte;
579 break;
580 case PTS_S_WAIT_REQ_PCK:
581 ch->pts.req[_PCK] = byte;
Harald Welte17db2f12016-02-26 09:48:57 +0100582 if (ch->pts.req[_PCK] != csum_pts(ch->pts.req)) {
Harald Weltedde112e2016-03-20 16:42:11 +0100583 TRACE_ERROR("%u: Error in PTS Checksum!\r\n",
584 ch->num);
Harald Welte17db2f12016-02-26 09:48:57 +0100585 /* Wait for the next TPDU */
586 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
587 return ISO_S_WAIT_TPDU;
588 }
Harald Welte4ba66d02016-02-25 19:38:56 +0100589 /* FIXME: check if proposal matches capabilities in ATR */
Harald Welte9d3e3822015-11-09 00:50:54 +0100590 memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
591 break;
Harald Welte4c473da2015-11-14 13:31:11 +0100592 default:
Harald Welte6a3a7142019-12-16 14:23:02 +0100593 TRACE_ERROR("%u: process_byte_pts() in invalid PTS state %s\r\n", ch->num,
594 get_value_string(pts_state_names, ch->pts.state));
Harald Welte4c473da2015-11-14 13:31:11 +0100595 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100596 }
597 /* calculate the next state and set it */
598 set_pts_state(ch, next_pts_state(ch));
599
Harald Welte4ba66d02016-02-25 19:38:56 +0100600 if (ch->pts.state == PTS_S_WAIT_RESP_PTSS) {
601 flush_pts(ch);
602 /* activate UART TX to transmit PTS response */
603 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
Harald Welte53079bb2016-03-20 14:58:35 +0100604 /* don't fall-through to the 'return ISO_S_IN_PTS'
605 * below, rather keep ISO7816 state as-is, it will be
606 * further updated by the tx-completion handler */
Harald Welteccb8a222016-03-20 13:37:11 +0100607 return -1;
Harald Welte4ba66d02016-02-25 19:38:56 +0100608 }
609
Harald Welte9d3e3822015-11-09 00:50:54 +0100610 return ISO_S_IN_PTS;
611}
612
613/* return a single byte to be transmitted to the reader */
Harald Welte855ba9e2016-02-24 21:00:46 +0100614static int tx_byte_pts(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100615{
Harald Welte855ba9e2016-02-24 21:00:46 +0100616 uint8_t byte;
617
618 /* 1: Determine the next transmit byte */
Harald Welte9d3e3822015-11-09 00:50:54 +0100619 switch (ch->pts.state) {
620 case PTS_S_WAIT_RESP_PTSS:
Harald Welte855ba9e2016-02-24 21:00:46 +0100621 byte = ch->pts.resp[_PTSS];
Harald Welte9d3e3822015-11-09 00:50:54 +0100622 break;
623 case PTS_S_WAIT_RESP_PTS0:
Harald Welte855ba9e2016-02-24 21:00:46 +0100624 byte = ch->pts.resp[_PTS0];
Harald Welte9d3e3822015-11-09 00:50:54 +0100625 break;
626 case PTS_S_WAIT_RESP_PTS1:
Harald Welte855ba9e2016-02-24 21:00:46 +0100627 byte = ch->pts.resp[_PTS1];
Harald Welte9d3e3822015-11-09 00:50:54 +0100628 /* This must be TA1 */
Harald Welte855ba9e2016-02-24 21:00:46 +0100629 ch->fi = byte >> 4;
630 ch->di = byte & 0xf;
Harald Weltedde112e2016-03-20 16:42:11 +0100631 TRACE_DEBUG("%u: found Fi=%u Di=%u\r\n", ch->num,
632 ch->fi, ch->di);
Harald Welte9d3e3822015-11-09 00:50:54 +0100633 break;
634 case PTS_S_WAIT_RESP_PTS2:
Harald Welte855ba9e2016-02-24 21:00:46 +0100635 byte = ch->pts.resp[_PTS2];
Harald Welte9d3e3822015-11-09 00:50:54 +0100636 break;
637 case PTS_S_WAIT_RESP_PTS3:
Harald Welte855ba9e2016-02-24 21:00:46 +0100638 byte = ch->pts.resp[_PTS3];
Harald Welte9d3e3822015-11-09 00:50:54 +0100639 break;
640 case PTS_S_WAIT_RESP_PCK:
Harald Welte855ba9e2016-02-24 21:00:46 +0100641 byte = ch->pts.resp[_PCK];
Harald Welte855ba9e2016-02-24 21:00:46 +0100642 break;
Harald Welted79dc4f2015-11-14 13:32:21 +0100643 default:
Harald Welte6a3a7142019-12-16 14:23:02 +0100644 TRACE_ERROR("%u: get_byte_pts() in invalid PTS state %s\r\n", ch->num,
645 get_value_string(pts_state_names, ch->pts.state));
Harald Welte855ba9e2016-02-24 21:00:46 +0100646 return 0;
647 }
648
649 /* 2: Transmit the byte */
650 card_emu_uart_tx(ch->uart_chan, byte);
651
652 /* 3: Update the state */
653
654 switch (ch->pts.state) {
655 case PTS_S_WAIT_RESP_PCK:
Harald Weltec58bba02016-03-20 14:57:53 +0100656 card_emu_uart_wait_tx_idle(ch->uart_chan);
Harald Welte52d55462016-03-20 13:38:05 +0100657 /* update baud rate generator with Fi/Di */
658 emu_update_fidi(ch);
Harald Welte855ba9e2016-02-24 21:00:46 +0100659 /* Wait for the next TPDU */
660 card_set_state(ch, ISO_S_WAIT_TPDU);
Harald Welte855ba9e2016-02-24 21:00:46 +0100661 break;
662 default:
663 /* calculate the next state and set it */
664 set_pts_state(ch, next_pts_state(ch));
Harald Welted79dc4f2015-11-14 13:32:21 +0100665 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100666 }
Harald Welted79dc4f2015-11-14 13:32:21 +0100667
Harald Welte855ba9e2016-02-24 21:00:46 +0100668 /* return number of bytes transmitted */
669 return 1;
Harald Welte9d3e3822015-11-09 00:50:54 +0100670}
671
672
673/**********************************************************************
674 * TPDU handling
675 **********************************************************************/
676
Harald Welte4d804672015-11-14 23:02:38 +0100677
678/* compute number of data bytes according to Chapter 10.3.2 of 7816-3 */
679static unsigned int t0_num_data_bytes(uint8_t p3, int reader_to_card)
680{
681 if (reader_to_card) {
682 return p3;
683 } else {
684 if (p3 == 0)
685 return 256;
686 else
687 return p3;
688 }
689}
690
Harald Welte9d3e3822015-11-09 00:50:54 +0100691/* add a just-received TPDU byte (from reader) to USB buffer */
Harald Welte61bb30e2015-11-14 23:44:14 +0100692static void add_tpdu_byte(struct card_handle *ch, uint8_t byte)
Harald Welte9d3e3822015-11-09 00:50:54 +0100693{
Harald Welte8e7fca32017-05-07 16:14:33 +0200694 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100695 struct cardemu_usb_msg_rx_data *rd;
Harald Welte4d804672015-11-14 23:02:38 +0100696 unsigned int num_data_bytes = t0_num_data_bytes(ch->tpdu.hdr[_P3], 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100697
698 /* ensure we have a buffer */
Harald Welte8e7fca32017-05-07 16:14:33 +0200699 if (!ch->uart_rx_msg) {
Harald Welte25a9a802017-05-08 13:30:09 +0200700 msg = ch->uart_rx_msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
701 SIMTRACE_MSGT_DO_CEMU_RX_DATA);
Harald Welte8e7fca32017-05-07 16:14:33 +0200702 if (!ch->uart_rx_msg) {
Harald Weltedde112e2016-03-20 16:42:11 +0100703 TRACE_ERROR("%u: Received UART byte but ENOMEM\r\n",
704 ch->num);
Harald Welte9d3e3822015-11-09 00:50:54 +0100705 return;
Harald Welte4d804672015-11-14 23:02:38 +0100706 }
Harald Welte25a9a802017-05-08 13:30:09 +0200707 msgb_put(msg, sizeof(*rd));
Harald Welte9d3e3822015-11-09 00:50:54 +0100708 } else
Harald Welte8e7fca32017-05-07 16:14:33 +0200709 msg = ch->uart_rx_msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100710
Harald Welte25a9a802017-05-08 13:30:09 +0200711 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200712 msgb_put_u8(msg, byte);
Harald Welte9d3e3822015-11-09 00:50:54 +0100713
714 /* check if the buffer is full. If so, send it */
Harald Welte25a9a802017-05-08 13:30:09 +0200715 if (msgb_l2len(msg) >= sizeof(*rd) + num_data_bytes) {
Harald Welte4d804672015-11-14 23:02:38 +0100716 rd->flags |= CEMU_DATA_F_FINAL;
Harald Welteb5288e82015-11-14 21:15:52 +0100717 flush_rx_buffer(ch);
Harald Welte61bb30e2015-11-14 23:44:14 +0100718 /* We need to transmit the SW now, */
719 set_tpdu_state(ch, TPDU_S_WAIT_TX);
Harald Welte8e7fca32017-05-07 16:14:33 +0200720 } else if (msgb_tailroom(msg) <= 0)
Harald Welte4d804672015-11-14 23:02:38 +0100721 flush_rx_buffer(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100722}
723
724static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts)
725{
Harald Welte05b41c62015-11-14 20:58:48 +0100726 if (ch->tpdu.state == new_ts)
727 return;
728
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200729 TRACE_DEBUG("%u: 7816 TPDU state %s -> %s\r\n", ch->num,
730 get_value_string(tpdu_state_names, ch->tpdu.state),
731 get_value_string(tpdu_state_names, new_ts));
Harald Welte903d63a2016-03-20 13:38:39 +0100732 ch->tpdu.state = new_ts;
733
Harald Welte9d3e3822015-11-09 00:50:54 +0100734 switch (new_ts) {
735 case TPDU_S_WAIT_CLA:
Harald Welte05b41c62015-11-14 20:58:48 +0100736 case TPDU_S_WAIT_RX:
Harald Welte9d3e3822015-11-09 00:50:54 +0100737 card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
738 break;
739 case TPDU_S_WAIT_PB:
740 /* we just completed the TPDU header from reader to card
741 * and now need to disable the receiver, enable the
742 * transmitter and transmit the procedure byte */
743 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
744 break;
Harald Weltead434402016-03-02 11:18:29 +0100745 default:
746 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100747 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100748}
749
750static enum tpdu_state next_tpdu_state(struct card_handle *ch)
751{
752 switch (ch->tpdu.state) {
753 case TPDU_S_WAIT_CLA:
754 return TPDU_S_WAIT_INS;
755 case TPDU_S_WAIT_INS:
756 return TPDU_S_WAIT_P1;
757 case TPDU_S_WAIT_P1:
758 return TPDU_S_WAIT_P2;
759 case TPDU_S_WAIT_P2:
760 return TPDU_S_WAIT_P3;
761 case TPDU_S_WAIT_P3:
762 return TPDU_S_WAIT_PB;
763 /* simply stay in Rx or Tx by default */
764 case TPDU_S_WAIT_PB:
765 return TPDU_S_WAIT_PB;
766 case TPDU_S_WAIT_RX:
767 return TPDU_S_WAIT_RX;
768 case TPDU_S_WAIT_TX:
769 return TPDU_S_WAIT_TX;
770 }
Harald Welte4c473da2015-11-14 13:31:11 +0100771 /* we should never reach here */
772 assert(0);
773 return -1;
Harald Welte9d3e3822015-11-09 00:50:54 +0100774}
775
776static void send_tpdu_header(struct card_handle *ch)
777{
Harald Welte8e7fca32017-05-07 16:14:33 +0200778 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100779 struct cardemu_usb_msg_rx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200780 uint8_t *cur;
Harald Welte9d3e3822015-11-09 00:50:54 +0100781
Harald Weltedde112e2016-03-20 16:42:11 +0100782 TRACE_INFO("%u: %s: %02x %02x %02x %02x %02x\r\n",
783 ch->num, __func__,
Harald Welte43f79492016-02-29 10:06:54 +0100784 ch->tpdu.hdr[0], ch->tpdu.hdr[1],
785 ch->tpdu.hdr[2], ch->tpdu.hdr[3],
786 ch->tpdu.hdr[4]);
787
Harald Welte9d3e3822015-11-09 00:50:54 +0100788 /* if we already/still have a context, send it off */
Harald Welte8e7fca32017-05-07 16:14:33 +0200789 if (ch->uart_rx_msg) {
Harald Weltedde112e2016-03-20 16:42:11 +0100790 TRACE_DEBUG("%u: have old buffer\r\n", ch->num);
Harald Welte8e7fca32017-05-07 16:14:33 +0200791 if (msgb_l2len(ch->uart_rx_msg)) {
Harald Weltedde112e2016-03-20 16:42:11 +0100792 TRACE_DEBUG("%u: flushing old buffer\r\n", ch->num);
Harald Weltef1697e22016-03-02 10:28:54 +0100793 flush_rx_buffer(ch);
794 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100795 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200796 TRACE_DEBUG("%u: allocating new buffer\r\n", ch->num);
797 /* ensure we have a new buffer */
Harald Welte25a9a802017-05-08 13:30:09 +0200798 ch->uart_rx_msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
799 SIMTRACE_MSGT_DO_CEMU_RX_DATA);
Harald Welte8e7fca32017-05-07 16:14:33 +0200800 if (!ch->uart_rx_msg) {
801 TRACE_ERROR("%u: %s: ENOMEM\r\n", ch->num, __func__);
802 return;
803 }
804 msg = ch->uart_rx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200805 rd = (struct cardemu_usb_msg_rx_data *) msgb_put(msg, sizeof(*rd));
Harald Welte9d3e3822015-11-09 00:50:54 +0100806
Harald Welte8e7fca32017-05-07 16:14:33 +0200807 /* initialize header */
Harald Welte9d3e3822015-11-09 00:50:54 +0100808 rd->flags = CEMU_DATA_F_TPDU_HDR;
Harald Welte9d3e3822015-11-09 00:50:54 +0100809
810 /* copy TPDU header to data field */
Harald Welte8e7fca32017-05-07 16:14:33 +0200811 cur = msgb_put(msg, sizeof(ch->tpdu.hdr));
812 memcpy(cur, ch->tpdu.hdr, sizeof(ch->tpdu.hdr));
Harald Welteb5288e82015-11-14 21:15:52 +0100813 /* rd->data_len is set in flush_rx_buffer() */
Harald Welte9d3e3822015-11-09 00:50:54 +0100814
Harald Welteb5288e82015-11-14 21:15:52 +0100815 flush_rx_buffer(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100816}
817
818static enum iso7816_3_card_state
819process_byte_tpdu(struct card_handle *ch, uint8_t byte)
820{
821 switch (ch->tpdu.state) {
822 case TPDU_S_WAIT_CLA:
823 ch->tpdu.hdr[_CLA] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100824 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100825 break;
826 case TPDU_S_WAIT_INS:
827 ch->tpdu.hdr[_INS] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100828 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100829 break;
830 case TPDU_S_WAIT_P1:
831 ch->tpdu.hdr[_P1] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100832 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100833 break;
834 case TPDU_S_WAIT_P2:
835 ch->tpdu.hdr[_P2] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100836 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100837 break;
838 case TPDU_S_WAIT_P3:
839 ch->tpdu.hdr[_P3] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100840 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100841 /* FIXME: start timer to transmit further 0x60 */
842 /* send the TPDU header as part of a procedure byte
843 * request to the USB host */
844 send_tpdu_header(ch);
845 break;
846 case TPDU_S_WAIT_RX:
Harald Welte61bb30e2015-11-14 23:44:14 +0100847 add_tpdu_byte(ch, byte);
848 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100849 default:
Harald Welte6a3a7142019-12-16 14:23:02 +0100850 TRACE_ERROR("%u: process_byte_tpdu() in invalid TPDU state %s\r\n", ch->num,
851 get_value_string(tpdu_state_names, ch->tpdu.state));
Harald Welte9d3e3822015-11-09 00:50:54 +0100852 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100853
854 /* ensure we stay in TPDU ISO state */
855 return ISO_S_IN_TPDU;
856}
857
Harald Welte855ba9e2016-02-24 21:00:46 +0100858/* tx a single byte to be transmitted to the reader */
859static int tx_byte_tpdu(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100860{
Harald Welte8e7fca32017-05-07 16:14:33 +0200861 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100862 struct cardemu_usb_msg_tx_data *td;
Harald Welte855ba9e2016-02-24 21:00:46 +0100863 uint8_t byte;
Harald Welte9d3e3822015-11-09 00:50:54 +0100864
865 /* ensure we are aware of any data that might be pending for
866 * transmit */
Harald Welte8e7fca32017-05-07 16:14:33 +0200867 if (!ch->uart_tx_msg) {
Harald Welte53079bb2016-03-20 14:58:35 +0100868 /* uart_tx_queue is filled from main loop, so no need
869 * for irq-safe operations */
Harald Welte54cb3d02016-02-29 14:12:40 +0100870 if (llist_empty(&ch->uart_tx_queue))
Harald Welte9d3e3822015-11-09 00:50:54 +0100871 return 0;
872
Harald Welte54cb3d02016-02-29 14:12:40 +0100873 /* dequeue first at head */
Harald Welte8e7fca32017-05-07 16:14:33 +0200874 ch->uart_tx_msg = msgb_dequeue(&ch->uart_tx_queue);
Harald Welte25a9a802017-05-08 13:30:09 +0200875 ch->uart_tx_msg->l1h = ch->uart_tx_msg->head;
876 ch->uart_tx_msg->l2h = ch->uart_tx_msg->l1h + sizeof(struct simtrace_msg_hdr);
Harald Welte8e7fca32017-05-07 16:14:33 +0200877 msg = ch->uart_tx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200878 /* remove the header */
879 msgb_pull(msg, sizeof(struct simtrace_msg_hdr) + sizeof(*td));
Harald Welte9d3e3822015-11-09 00:50:54 +0100880 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200881 msg = ch->uart_tx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200882 td = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100883
Harald Welte8e7fca32017-05-07 16:14:33 +0200884 /* take the next pending byte out of the msgb */
885 byte = msgb_pull_u8(msg);
Harald Welte855ba9e2016-02-24 21:00:46 +0100886
887 card_emu_uart_tx(ch->uart_chan, byte);
Harald Welte9d3e3822015-11-09 00:50:54 +0100888
Kévin Redon0f4abf52018-08-02 17:42:48 +0200889 /* this must happen _after_ the byte has been transmitted */
Harald Weltef16b6182016-02-24 22:18:46 +0100890 switch (ch->tpdu.state) {
891 case TPDU_S_WAIT_PB:
892 /* if we just transmitted the procedure byte, we need to decide
893 * if we want to continue to receive or transmit */
894 if (td->flags & CEMU_DATA_F_PB_AND_TX)
895 set_tpdu_state(ch, TPDU_S_WAIT_TX);
896 else if (td->flags & CEMU_DATA_F_PB_AND_RX)
897 set_tpdu_state(ch, TPDU_S_WAIT_RX);
898 break;
Harald Weltead434402016-03-02 11:18:29 +0100899 default:
900 break;
Harald Weltef16b6182016-02-24 22:18:46 +0100901 }
902
Harald Welte9d3e3822015-11-09 00:50:54 +0100903 /* check if the buffer has now been fully transmitted */
Harald Welte8e7fca32017-05-07 16:14:33 +0200904 if (msgb_length(msg) == 0) {
Harald Welte52922ff2015-11-14 20:59:56 +0100905 if (td->flags & CEMU_DATA_F_PB_AND_RX) {
906 /* we have just sent the procedure byte and now
907 * need to continue receiving */
908 set_tpdu_state(ch, TPDU_S_WAIT_RX);
Harald Welte2935b3c2015-11-14 20:00:14 +0100909 } else {
Harald Welte52922ff2015-11-14 20:59:56 +0100910 /* we have transmitted all bytes */
911 if (td->flags & CEMU_DATA_F_FINAL) {
912 /* this was the final part of the APDU, go
Harald Welte53079bb2016-03-20 14:58:35 +0100913 * back to state one */
Harald Welte52922ff2015-11-14 20:59:56 +0100914 card_set_state(ch, ISO_S_WAIT_TPDU);
Harald Welte52922ff2015-11-14 20:59:56 +0100915 }
Harald Welte2935b3c2015-11-14 20:00:14 +0100916 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200917 usb_buf_free(msg);
918 ch->uart_tx_msg = NULL;
Harald Welte9d3e3822015-11-09 00:50:54 +0100919 }
920
921 return 1;
922}
923
924/**********************************************************************
925 * Public API
926 **********************************************************************/
927
928/* process a single byte received from the reader */
929void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
930{
931 int new_state = -1;
932
933 ch->stats.rx_bytes++;
934
935 switch (ch->state) {
Harald Welte9d3e3822015-11-09 00:50:54 +0100936 case ISO_S_WAIT_TPDU:
937 if (byte == 0xff) {
Harald Welte02d0d732019-12-15 13:19:24 +0100938 /* reset PTS to initial state */
939 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
Harald Welte9d3e3822015-11-09 00:50:54 +0100940 new_state = process_byte_pts(ch, byte);
941 ch->stats.pps++;
942 goto out_silent;
943 }
944 /* fall-through */
945 case ISO_S_IN_TPDU:
946 new_state = process_byte_tpdu(ch, byte);
947 break;
948 case ISO_S_IN_PTS:
949 new_state = process_byte_pts(ch, byte);
950 goto out_silent;
Kévin Redon5f6b8712018-07-11 09:49:06 +0200951 default:
Harald Welte6a3a7142019-12-16 14:23:02 +0100952 TRACE_ERROR("%u: Received UART char in invalid 7816 state %s\r\n", ch->num,
953 get_value_string(iso7816_3_card_state_names, ch->state));
Kévin Redon5f6b8712018-07-11 09:49:06 +0200954 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100955 }
956
957out_silent:
958 if (new_state != -1)
959 card_set_state(ch, new_state);
960}
961
Harald Welte855ba9e2016-02-24 21:00:46 +0100962/* transmit a single byte to the reader */
963int card_emu_tx_byte(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100964{
965 int rc = 0;
966
967 switch (ch->state) {
968 case ISO_S_IN_ATR:
Kévin Redonebe672e2018-07-29 00:18:12 +0200969 rc = tx_byte_atr(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100970 break;
971 case ISO_S_IN_PTS:
Harald Welte855ba9e2016-02-24 21:00:46 +0100972 rc = tx_byte_pts(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100973 break;
974 case ISO_S_IN_TPDU:
Harald Welte855ba9e2016-02-24 21:00:46 +0100975 rc = tx_byte_tpdu(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100976 break;
Harald Weltead434402016-03-02 11:18:29 +0100977 default:
978 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100979 }
980
981 if (rc)
982 ch->stats.tx_bytes++;
983
Harald Welte4d804672015-11-14 23:02:38 +0100984 /* if we return 0 here, the UART needs to disable transmit-ready
985 * interrupts */
Harald Welte9d3e3822015-11-09 00:50:54 +0100986 return rc;
987}
988
Harald Welteacae4122016-03-02 10:27:58 +0100989void card_emu_have_new_uart_tx(struct card_handle *ch)
990{
991 switch (ch->state) {
992 case ISO_S_IN_TPDU:
993 switch (ch->tpdu.state) {
994 case TPDU_S_WAIT_TX:
995 case TPDU_S_WAIT_PB:
996 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
997 break;
998 default:
999 break;
1000 }
1001 default:
1002 break;
1003 }
1004}
1005
Harald Welte140f0072019-12-16 10:23:32 +01001006void card_emu_report_status(struct card_handle *ch, bool report_on_irq)
Harald Welteff160652016-03-19 21:59:06 +01001007{
Harald Welte8e7fca32017-05-07 16:14:33 +02001008 struct msgb *msg;
Harald Welteff160652016-03-19 21:59:06 +01001009 struct cardemu_usb_msg_status *sts;
Harald Welte140f0072019-12-16 10:23:32 +01001010 uint8_t ep = ch->in_ep;
Harald Welteff160652016-03-19 21:59:06 +01001011
Harald Welte140f0072019-12-16 10:23:32 +01001012 if (report_on_irq)
1013 ep = ch->irq_ep;
1014
1015 msg = usb_buf_alloc_st(ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_STATUS);
Harald Welte8e7fca32017-05-07 16:14:33 +02001016 if (!msg)
Harald Welteff160652016-03-19 21:59:06 +01001017 return;
Harald Welte8e7fca32017-05-07 16:14:33 +02001018
Harald Welte25a9a802017-05-08 13:30:09 +02001019 sts = (struct cardemu_usb_msg_status *) msgb_put(msg, sizeof(*sts));
Harald Welteff160652016-03-19 21:59:06 +01001020 sts->flags = 0;
1021 if (ch->vcc_active)
1022 sts->flags |= CEMU_STATUS_F_VCC_PRESENT;
1023 if (ch->clocked)
1024 sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;
1025 if (ch->in_reset)
1026 sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;
1027 /* FIXME: voltage + card insert */
1028 sts->fi = ch->fi;
1029 sts->di = ch->di;
1030 sts->wi = ch->wi;
1031 sts->waiting_time = ch->waiting_time;
1032
Harald Welte25a9a802017-05-08 13:30:09 +02001033 usb_buf_upd_len_and_submit(msg);
Harald Welteff160652016-03-19 21:59:06 +01001034}
1035
Harald Weltea5bbe782019-12-16 10:39:55 +01001036static void card_emu_report_config(struct card_handle *ch)
1037{
1038 struct msgb *msg;
1039 struct cardemu_usb_msg_config *cfg;
1040 uint8_t ep = ch->in_ep;
1041
1042 msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);
1043 if (!msg)
1044 return;
1045
1046 cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));
1047 cfg->features = ch->features;
1048
1049 usb_buf_upd_len_and_submit(msg);
1050}
1051
Harald Welte9d3e3822015-11-09 00:50:54 +01001052/* hardware driver informs us that a card I/O signal has changed */
1053void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
1054{
Harald Weltee213cc42019-12-16 10:53:22 +01001055 uint32_t chg_mask = 0;
1056
Harald Welte9d3e3822015-11-09 00:50:54 +01001057 switch (io) {
1058 case CARD_IO_VCC:
Harald Welte47ee2832016-02-29 10:09:46 +01001059 if (active == 0 && ch->vcc_active == 1) {
Harald Weltedde112e2016-03-20 16:42:11 +01001060 TRACE_INFO("%u: VCC deactivated\r\n", ch->num);
Harald Welte81f4ef72019-12-14 22:20:00 +01001061 card_handle_reset(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +01001062 card_set_state(ch, ISO_S_WAIT_POWER);
Harald Weltee213cc42019-12-16 10:53:22 +01001063 chg_mask |= CEMU_STATUS_F_VCC_PRESENT;
Harald Welte47ee2832016-02-29 10:09:46 +01001064 } else if (active == 1 && ch->vcc_active == 0) {
Harald Weltedde112e2016-03-20 16:42:11 +01001065 TRACE_INFO("%u: VCC activated\r\n", ch->num);
Harald Welte9d3e3822015-11-09 00:50:54 +01001066 card_set_state(ch, ISO_S_WAIT_CLK);
Harald Weltee213cc42019-12-16 10:53:22 +01001067 chg_mask |= CEMU_STATUS_F_VCC_PRESENT;
Harald Welte47ee2832016-02-29 10:09:46 +01001068 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001069 ch->vcc_active = active;
1070 break;
1071 case CARD_IO_CLK:
Harald Welte47ee2832016-02-29 10:09:46 +01001072 if (active == 1 && ch->clocked == 0) {
Harald Weltedde112e2016-03-20 16:42:11 +01001073 TRACE_INFO("%u: CLK activated\r\n", ch->num);
Harald Welte47ee2832016-02-29 10:09:46 +01001074 if (ch->state == ISO_S_WAIT_CLK)
1075 card_set_state(ch, ISO_S_WAIT_RST);
Harald Weltee213cc42019-12-16 10:53:22 +01001076 chg_mask |= CEMU_STATUS_F_CLK_ACTIVE;
Harald Welte47ee2832016-02-29 10:09:46 +01001077 } else if (active == 0 && ch->clocked == 1) {
Harald Weltedde112e2016-03-20 16:42:11 +01001078 TRACE_INFO("%u: CLK deactivated\r\n", ch->num);
Harald Weltee213cc42019-12-16 10:53:22 +01001079 chg_mask |= CEMU_STATUS_F_CLK_ACTIVE;
Harald Welte47ee2832016-02-29 10:09:46 +01001080 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001081 ch->clocked = active;
1082 break;
1083 case CARD_IO_RST:
Harald Welte47ee2832016-02-29 10:09:46 +01001084 if (active == 0 && ch->in_reset) {
Harald Weltedde112e2016-03-20 16:42:11 +01001085 TRACE_INFO("%u: RST released\r\n", ch->num);
Harald Welte47ee2832016-02-29 10:09:46 +01001086 if (ch->vcc_active && ch->clocked) {
1087 /* enable the TC/ETU counter once reset has been released */
1088 tc_etu_enable(ch->tc_chan);
Kévin Redonebe672e2018-07-29 00:18:12 +02001089 /* prepare to send the ATR */
Harald Welte47ee2832016-02-29 10:09:46 +01001090 card_set_state(ch, ISO_S_WAIT_ATR);
Harald Welte47ee2832016-02-29 10:09:46 +01001091 }
Harald Weltee213cc42019-12-16 10:53:22 +01001092 chg_mask |= CEMU_STATUS_F_RESET_ACTIVE;
Harald Welte47ee2832016-02-29 10:09:46 +01001093 } else if (active && !ch->in_reset) {
Harald Weltedde112e2016-03-20 16:42:11 +01001094 TRACE_INFO("%u: RST asserted\r\n", ch->num);
Harald Welte81f4ef72019-12-14 22:20:00 +01001095 card_handle_reset(ch);
Harald Weltee213cc42019-12-16 10:53:22 +01001096 chg_mask |= CEMU_STATUS_F_RESET_ACTIVE;
Harald Welte9d3e3822015-11-09 00:50:54 +01001097 }
1098 ch->in_reset = active;
1099 break;
1100 }
Harald Weltee9f429d2019-12-15 13:21:17 +01001101
1102 switch (ch->state) {
1103 case ISO_S_WAIT_POWER:
1104 case ISO_S_WAIT_CLK:
1105 case ISO_S_WAIT_RST:
1106 /* check end activation state (even if the reader does
1107 * not respect the activation sequence) */
1108 if (ch->vcc_active && ch->clocked && !ch->in_reset) {
Harald Weltee9f429d2019-12-15 13:21:17 +01001109 /* prepare to send the ATR */
1110 card_set_state(ch, ISO_S_WAIT_ATR);
1111 }
1112 break;
1113 default:
1114 break;
1115 }
Harald Weltee213cc42019-12-16 10:53:22 +01001116
1117 /* notify the host about the state change */
1118 if ((ch->features & CEMU_FEAT_F_STATUS_IRQ) && chg_mask)
1119 card_emu_report_status(ch, true);
Harald Welte9d3e3822015-11-09 00:50:54 +01001120}
1121
1122/* User sets a new ATR to be returned during next card reset */
1123int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
1124{
1125 if (len > sizeof(ch->atr.atr))
1126 return -1;
1127
1128 memcpy(ch->atr.atr, atr, len);
1129 ch->atr.len = len;
1130 ch->atr.idx = 0;
1131
Kévin Redonebe672e2018-07-29 00:18:12 +02001132#if TRACE_LEVEL >= TRACE_LEVEL_INFO
1133 uint8_t i;
1134 TRACE_INFO("%u: ATR set: ", ch->num);
1135 for (i = 0; i < ch->atr.len; i++) {
1136 TRACE_INFO_WP("%02x ", atr[i]);
1137 }
1138 TRACE_INFO_WP("\n\r");
1139#endif
1140 /* FIXME: race condition with transmitting ATR to reader? */
Harald Welte9d3e3822015-11-09 00:50:54 +01001141
1142 return 0;
1143}
1144
1145/* hardware driver informs us that one (more) ETU has expired */
1146void tc_etu_wtime_half_expired(void *handle)
1147{
1148 struct card_handle *ch = handle;
1149 /* transmit NULL procedure byte well before waiting time expires */
Harald Weltedda73552016-03-02 10:29:55 +01001150 switch (ch->state) {
1151 case ISO_S_IN_TPDU:
1152 switch (ch->tpdu.state) {
1153 case TPDU_S_WAIT_PB:
1154 case TPDU_S_WAIT_TX:
1155 putchar('N');
1156 card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);
1157 break;
1158 default:
1159 break;
1160 }
1161 break;
1162 default:
1163 break;
1164 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001165}
1166
1167/* hardware driver informs us that one (more) ETU has expired */
1168void tc_etu_wtime_expired(void *handle)
1169{
Harald Weltedde112e2016-03-20 16:42:11 +01001170 struct card_handle *ch = handle;
Kévin Redonebe672e2018-07-29 00:18:12 +02001171 switch (ch->state) {
1172 case ISO_S_WAIT_ATR:
1173 /* ISO 7816-3 6.2.1 time tc has passed, we can now send the ATR */
1174 card_set_state(ch, ISO_S_IN_ATR);
1175 break;
1176 default:
1177 TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
1178 break;
1179 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001180}
1181
Kévin Redon503e1842019-05-15 00:23:21 +02001182/* shortest ATR possible (uses default speed and no options) */
1183static const uint8_t default_atr[] = { 0x3B, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +01001184
1185static struct card_handle card_handles[NUM_SLOTS];
1186
Harald Weltea5bbe782019-12-16 10:39:55 +01001187int card_emu_set_config(struct card_handle *ch, const struct cardemu_usb_msg_config *scfg,
1188 unsigned int scfg_len)
1189{
1190 if (scfg_len >= sizeof(uint32_t))
1191 ch->features = (scfg->features & SUPPORTED_FEATURES);
1192
1193 /* send back a report of our current configuration */
1194 card_emu_report_config(ch);
1195
1196 return 0;
1197}
1198
Kévin Redon7233cf82019-11-14 19:37:32 +01001199struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)
Harald Welte9d3e3822015-11-09 00:50:54 +01001200{
1201 struct card_handle *ch;
1202
1203 if (slot_num >= ARRAY_SIZE(card_handles))
1204 return NULL;
1205
1206 ch = &card_handles[slot_num];
1207
1208 memset(ch, 0, sizeof(*ch));
1209
Harald Welte54cb3d02016-02-29 14:12:40 +01001210 INIT_LLIST_HEAD(&ch->uart_tx_queue);
1211
Harald Weltedde112e2016-03-20 16:42:11 +01001212 ch->num = slot_num;
Harald Welte8e7fca32017-05-07 16:14:33 +02001213 ch->irq_ep = irq_ep;
1214 ch->in_ep = in_ep;
Harald Welte9d3e3822015-11-09 00:50:54 +01001215 ch->state = ISO_S_WAIT_POWER;
Kévin Redon7233cf82019-11-14 19:37:32 +01001216 ch->vcc_active = vcc_active;
1217 ch->in_reset = in_reset;
1218 ch->clocked = clocked;
Harald Welte9d3e3822015-11-09 00:50:54 +01001219
1220 ch->fi = 0;
1221 ch->di = 1;
1222 ch->wi = ISO7816_3_DEFAULT_WI;
1223
1224 ch->tc_chan = tc_chan;
1225 ch->uart_chan = uart_chan;
1226 ch->waiting_time = ISO7816_3_INIT_WTIME;
1227
1228 ch->atr.idx = 0;
1229 ch->atr.len = sizeof(default_atr);
1230 memcpy(ch->atr.atr, default_atr, ch->atr.len);
1231
Harald Weltee92cb502019-12-14 21:48:45 +01001232 card_handle_reset(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +01001233
1234 tc_etu_init(ch->tc_chan, ch);
1235
1236 return ch;
1237}