blob: 5d5bd3e878bdaa21d80807b4f68fad8727a5ea1a [file] [log] [blame]
Harald Welte9d3e3822015-11-09 00:50:54 +01001#include <stdint.h>
2#include <stdio.h>
3#include <string.h>
4#include <assert.h>
5#include <stdlib.h>
6
7#include "card_emu.h"
Harald Welte25a9a802017-05-08 13:30:09 +02008#include "simtrace_prot.h"
Harald Welte9d3e3822015-11-09 00:50:54 +01009#include "tc_etu.h"
Harald Welte8e7fca32017-05-07 16:14:33 +020010#include "usb_buf.h"
11
12#define PHONE_DATAIN 1
13#define PHONE_INT 2
14#define PHONE_DATAOUT 3
Harald Welte9d3e3822015-11-09 00:50:54 +010015
Harald Welte05164642021-04-06 01:18:01 +020016/* stub for stdio */
17signed int printf_sync(const char *pFormat, ...)
18{
19 va_list ap;
20 signed int result;
21
22 va_start(ap, pFormat);
23 result = vprintf(pFormat, ap);
24 va_end(ap);
25
26 return result;
27}
28
29
Harald Welted401b122019-10-11 10:35:33 +020030/***********************************************************************
31 * stub functions required by card_emu.c
32 ***********************************************************************/
Harald Welte9d3e3822015-11-09 00:50:54 +010033
Harald Weltea1cd0f32017-02-27 14:29:07 +010034void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
35{
36}
37
Harald Welte9d3e3822015-11-09 00:50:54 +010038int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
39{
40 printf("uart_update_fidi(uart_chan=%u, fidi=%u)\n", uart_chan, fidi);
41 return 0;
42}
43
Harald Welte86d047b2016-02-25 00:26:17 +010044/* a buffer in which we store those bytes send by the UART towards the card
45 * reader, so we can verify in test cases what was actually written */
46static uint8_t tx_debug_buf[1024];
47static unsigned int tx_debug_buf_idx;
48
Harald Welted401b122019-10-11 10:35:33 +020049/* the card emulator wants to send some data to the host [reader] */
Harald Welte9d3e3822015-11-09 00:50:54 +010050int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
51{
Harald Welte6bf8c122016-02-24 21:04:08 +010052 printf("UART_TX(%02x)\n", byte);
Harald Welte86d047b2016-02-25 00:26:17 +010053 tx_debug_buf[tx_debug_buf_idx++] = byte;
Harald Welte9d3e3822015-11-09 00:50:54 +010054 return 1;
55}
56
57void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
58{
Harald Welteb4362862015-11-14 19:02:33 +010059 char *rts;
60 switch (rxtx) {
61 case 0:
62 rts = "OFF";
63 break;
64 case ENABLE_TX:
65 rts = "TX";
66 break;
Harald Welte752bc7f2021-04-05 19:08:11 +020067 case ENABLE_TX_TIMER_ONLY:
68 rts = "TX-TIMER-ONLY";
69 break;
Harald Welteb4362862015-11-14 19:02:33 +010070 case ENABLE_RX:
71 rts = "RX";
72 break;
73 default:
74 rts = "unknown";
75 break;
76 };
77
78 printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
Harald Welte9d3e3822015-11-09 00:50:54 +010079}
80
Kévin Redonebe672e2018-07-29 00:18:12 +020081void card_emu_uart_interrupt(uint8_t uart_chan)
82{
83 printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
84}
85
Harald Welte752bc7f2021-04-05 19:08:11 +020086void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
Harald Welte9d3e3822015-11-09 00:50:54 +010087{
Harald Welte752bc7f2021-04-05 19:08:11 +020088 printf("%s(uart_chan=%u, wtime=%u)\n", __func__, uart_chan, wt);
Harald Welte9d3e3822015-11-09 00:50:54 +010089}
90
Harald Welte752bc7f2021-04-05 19:08:11 +020091void card_emu_uart_reset_wt(uint8_t uart_chan)
Harald Welte9d3e3822015-11-09 00:50:54 +010092{
Harald Welte752bc7f2021-04-05 19:08:11 +020093 printf("%s(uart_chan=%u\n", __func__, uart_chan);
Harald Welte6bf8c122016-02-24 21:04:08 +010094}
Harald Welte9d3e3822015-11-09 00:50:54 +010095
Harald Welted401b122019-10-11 10:35:33 +020096
97
98/***********************************************************************
99 * test helper functions
100 ***********************************************************************/
101
102
103static void reader_check_and_clear(const uint8_t *data, unsigned int len)
104{
105 assert(len == tx_debug_buf_idx);
106 assert(!memcmp(tx_debug_buf, data, len));
107 tx_debug_buf_idx = 0;
108}
109
110static const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100111
112static int verify_atr(struct card_handle *ch)
113{
Harald Welte9d3e3822015-11-09 00:50:54 +0100114 unsigned int i;
115
Harald Welte6bf8c122016-02-24 21:04:08 +0100116 printf("receiving + verifying ATR:\n");
Harald Welte9d3e3822015-11-09 00:50:54 +0100117 for (i = 0; i < sizeof(atr); i++) {
Harald Welte6bf8c122016-02-24 21:04:08 +0100118 assert(card_emu_tx_byte(ch) == 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100119 }
Harald Welte6bf8c122016-02-24 21:04:08 +0100120 assert(card_emu_tx_byte(ch) == 0);
Harald Welte86d047b2016-02-25 00:26:17 +0100121 reader_check_and_clear(atr, sizeof(atr));
Harald Welte9d3e3822015-11-09 00:50:54 +0100122
123 return 1;
124}
125
126static void io_start_card(struct card_handle *ch)
127{
Harald Welte86d047b2016-02-25 00:26:17 +0100128 card_emu_set_atr(ch, atr, sizeof(atr));
129
Harald Welte9d3e3822015-11-09 00:50:54 +0100130 /* bring the card up from the dead */
131 card_emu_io_statechg(ch, CARD_IO_VCC, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100132 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100133 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100134 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100135 card_emu_io_statechg(ch, CARD_IO_RST, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100136 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100137
138 /* release from reset and verify th ATR */
139 card_emu_io_statechg(ch, CARD_IO_RST, 0);
Kévin Redonebe672e2018-07-29 00:18:12 +0200140 /* simulate waiting time before ATR expired */
Harald Welte752bc7f2021-04-05 19:08:11 +0200141 card_emu_wtime_expired(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100142 verify_atr(ch);
143}
144
Harald Welted401b122019-10-11 10:35:33 +0200145/* emulate the host/reader sending some bytes to the [emulated] card */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100146static void reader_send_bytes(struct card_handle *ch, const uint8_t *bytes, unsigned int len)
Harald Welte9d3e3822015-11-09 00:50:54 +0100147{
148 unsigned int i;
Harald Welte84ec2522015-11-14 23:03:50 +0100149 for (i = 0; i < len; i++) {
150 printf("UART_RX(%02x)\n", bytes[i]);
Harald Welte9d3e3822015-11-09 00:50:54 +0100151 card_emu_process_rx_byte(ch, bytes[i]);
Harald Welte84ec2522015-11-14 23:03:50 +0100152 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100153}
154
Harald Welte8e7fca32017-05-07 16:14:33 +0200155static void dump_rctx(struct msgb *msg)
Harald Welte9d3e3822015-11-09 00:50:54 +0100156{
Harald Welte25a9a802017-05-08 13:30:09 +0200157 struct simtrace_msg_hdr *mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100158 struct cardemu_usb_msg_rx_data *rxd;
159 int i;
Harald Welte8e7fca32017-05-07 16:14:33 +0200160#if 0
Harald Welte9d3e3822015-11-09 00:50:54 +0100161
162 printf("req_ctx(%p): state=%u, size=%u, tot_len=%u, idx=%u, data=%p\n",
163 rctx, rctx->state, rctx->size, rctx->tot_len, rctx->idx, rctx->data);
Harald Weltea1cd0f32017-02-27 14:29:07 +0100164 printf(" msg_type=%u, seq_nr=%u, msg_len=%u\n",
165 mh->msg_type, mh->seq_nr, mh->msg_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200166#endif
167 printf("%s\n", msgb_hexdump(msg));
Harald Welte9d3e3822015-11-09 00:50:54 +0100168
169 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200170 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
171 rxd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100172 printf(" flags=%x, data=", rxd->flags);
Harald Welted295b922016-03-18 21:01:36 +0100173 for (i = 0; i < rxd->data_len; i++)
Harald Welte9d3e3822015-11-09 00:50:54 +0100174 printf(" %02x", rxd->data[i]);
175 printf("\n");
176 break;
177 }
178}
179
Harald Welte8e7fca32017-05-07 16:14:33 +0200180static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int len)
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100181{
Harald Weltef4a625b2019-12-14 19:07:57 +0100182 struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
Harald Welte8e7fca32017-05-07 16:14:33 +0200183 struct msgb *msg;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100184 struct cardemu_usb_msg_tx_data *td;
185 struct cardemu_usb_msg_rx_data *rd;
Harald Welte25a9a802017-05-08 13:30:09 +0200186 struct simtrace_msg_hdr *mh;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100187
Harald Weltef4a625b2019-12-14 19:07:57 +0100188 assert(bep);
189 msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200190 assert(msg);
191 dump_rctx(msg);
192 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200193 mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100194
195 /* verify the contents of the rctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200196 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200197 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
198 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200199 assert(rd->data_len == len);
200 assert(!memcmp(rd->data, data, len));
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100201 break;
202#if 0
203 case RCTX_S_UART_RX_PENDING:
Harald Welte25a9a802017-05-08 13:30:09 +0200204 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welted295b922016-03-18 21:01:36 +0100205 assert(rd->data_len == len);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100206 assert(!memcmp(rd->data, data, len));
207 break;
208#endif
209 default:
210 assert(0);
211 }
212
213 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200214 usb_buf_free(msg);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100215}
216
Harald Welte4ba66d02016-02-25 19:38:56 +0100217static void get_and_verify_rctx_pps(const uint8_t *data, unsigned int len)
218{
Harald Weltef4a625b2019-12-14 19:07:57 +0100219 struct usb_buffered_ep *bep = usb_get_buf_ep(PHONE_DATAIN);
Harald Welte8e7fca32017-05-07 16:14:33 +0200220 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200221 struct simtrace_msg_hdr *mh;
Harald Welte4ba66d02016-02-25 19:38:56 +0100222 struct cardemu_usb_msg_pts_info *ptsi;
223
Harald Weltef4a625b2019-12-14 19:07:57 +0100224 assert(bep);
225 msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200226 assert(msg);
227 dump_rctx(msg);
228 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200229 mh = (struct simtrace_msg_hdr *) msg->l1h;
230 ptsi = (struct cardemu_usb_msg_pts_info *) msg->l2h;
Harald Welte4ba66d02016-02-25 19:38:56 +0100231
Harald Welte4ba66d02016-02-25 19:38:56 +0100232 /* FIXME: verify */
Harald Welte25a9a802017-05-08 13:30:09 +0200233 assert(mh->msg_type == SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte4ba66d02016-02-25 19:38:56 +0100234 assert(!memcmp(ptsi->req, data, len));
235 assert(!memcmp(ptsi->resp, data, len));
236
237 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200238 usb_buf_free(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100239}
240
Harald Welteb4362862015-11-14 19:02:33 +0100241/* emulate a TPDU header being sent by the reader/phone */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100242static void rdr_send_tpdu_hdr(struct card_handle *ch, const uint8_t *tpdu_hdr)
Harald Welte9d3e3822015-11-09 00:50:54 +0100243{
Harald Welte8e7fca32017-05-07 16:14:33 +0200244 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
245
Harald Welte9d3e3822015-11-09 00:50:54 +0100246 /* we don't want a receive context to become available during
247 * the first four bytes */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100248 reader_send_bytes(ch, tpdu_hdr, 4);
Harald Welte8e7fca32017-05-07 16:14:33 +0200249 assert(llist_empty(queue));
Harald Welte9d3e3822015-11-09 00:50:54 +0100250
Harald Welteeef6c2a2016-02-24 22:19:03 +0100251 reader_send_bytes(ch, tpdu_hdr+4, 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100252 /* but then after the final byte of the TPDU header, we want a
253 * receive context to be available for USB transmission */
Harald Welte8e7fca32017-05-07 16:14:33 +0200254 get_and_verify_rctx(PHONE_DATAIN, tpdu_hdr, 5);
Harald Welteb4362862015-11-14 19:02:33 +0100255}
256
Harald Welte25a9a802017-05-08 13:30:09 +0200257/* emulate a SIMTRACE_MSGT_DT_CEMU_TX_DATA received from USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200258static void host_to_device_data(struct card_handle *ch, const uint8_t *data, uint16_t len,
259 unsigned int flags)
Harald Welteb4362862015-11-14 19:02:33 +0100260{
Harald Welte8e7fca32017-05-07 16:14:33 +0200261 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200262 struct simtrace_msg_hdr *mh;
Harald Welte84ec2522015-11-14 23:03:50 +0100263 struct cardemu_usb_msg_tx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200264 struct llist_head *queue;
Harald Welteb4362862015-11-14 19:02:33 +0100265
266 /* allocate a free req_ctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200267 msg = usb_buf_alloc(PHONE_DATAOUT);
268 assert(msg);
Harald Welte25a9a802017-05-08 13:30:09 +0200269 /* initialize the common header */
Harald Welte8e7fca32017-05-07 16:14:33 +0200270 msg->l1h = msg->head;
Harald Welte25a9a802017-05-08 13:30:09 +0200271 mh = (struct simtrace_msg_hdr *) msgb_put(msg, sizeof(*mh));
272 mh->msg_class = SIMTRACE_MSGC_CARDEM;
273 mh->msg_type = SIMTRACE_MSGT_DT_CEMU_TX_DATA;
Harald Welteb4362862015-11-14 19:02:33 +0100274
Harald Welte25a9a802017-05-08 13:30:09 +0200275 /* initialize the tx_data message */
276 msg->l2h = msgb_put(msg, sizeof(*rd) + len);
277 rd = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welteeef6c2a2016-02-24 22:19:03 +0100278 rd->flags = flags;
Harald Welteb4362862015-11-14 19:02:33 +0100279 /* copy data and set length */
Harald Welted295b922016-03-18 21:01:36 +0100280 rd->data_len = len;
Harald Welteb4362862015-11-14 19:02:33 +0100281 memcpy(rd->data, data, len);
Harald Welte25a9a802017-05-08 13:30:09 +0200282
283 mh->msg_len = sizeof(*mh) + sizeof(*rd) + len;
Harald Welteb4362862015-11-14 19:02:33 +0100284
285 /* hand the req_ctx to the UART transmit code */
Harald Welte8e7fca32017-05-07 16:14:33 +0200286 queue = card_emu_get_uart_tx_queue(ch);
287 assert(queue);
288 msgb_enqueue(queue, msg);
Harald Welteb4362862015-11-14 19:02:33 +0100289}
290
Harald Welteeef6c2a2016-02-24 22:19:03 +0100291/* card-transmit any pending characters */
Harald Welte86d047b2016-02-25 00:26:17 +0100292static int card_tx_verify_chars(struct card_handle *ch, const uint8_t *data, unsigned int data_len)
Harald Welteb4362862015-11-14 19:02:33 +0100293{
Harald Welteb4362862015-11-14 19:02:33 +0100294 int count = 0;
295
Harald Welte6bf8c122016-02-24 21:04:08 +0100296 while (card_emu_tx_byte(ch)) {
Harald Welteb4362862015-11-14 19:02:33 +0100297 count++;
298 }
Harald Welte86d047b2016-02-25 00:26:17 +0100299
300 assert(count == data_len);
301 reader_check_and_clear(data, data_len);
302
Harald Welteb4362862015-11-14 19:02:33 +0100303 return count;
Harald Welte9d3e3822015-11-09 00:50:54 +0100304}
305
Harald Welte84ec2522015-11-14 23:03:50 +0100306const uint8_t tpdu_hdr_sel_mf[] = { 0xA0, 0xA4, 0x00, 0x00, 0x00 };
Harald Welte61bb30e2015-11-14 23:44:14 +0100307const uint8_t tpdu_pb_sw[] = { 0x90, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100308
Harald Weltec043e642016-02-24 23:26:55 +0100309static void
310test_tpdu_reader2card(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
311{
Harald Weltec043e642016-02-24 23:26:55 +0100312 printf("\n==> transmitting APDU (HDR + PB + card-RX)\n");
313
314 /* emulate the reader sending a TPDU header */
315 rdr_send_tpdu_hdr(ch, hdr);
316 /* we shouldn't have any pending card-TX yet */
Harald Welte86d047b2016-02-25 00:26:17 +0100317 card_tx_verify_chars(ch, NULL, 0);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100318
Harald Weltec043e642016-02-24 23:26:55 +0100319 /* card emulator PC sends a singly byte PB response via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200320 host_to_device_data(ch, hdr+1, 1, CEMU_DATA_F_FINAL | CEMU_DATA_F_PB_AND_RX);
Harald Weltec043e642016-02-24 23:26:55 +0100321 /* card actually sends that single PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100322 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100323
324 /* emulate more characters from reader to card */
325 reader_send_bytes(ch, body, body_len);
326
327 /* check if we have received them on the USB side */
Harald Welte8e7fca32017-05-07 16:14:33 +0200328 get_and_verify_rctx(PHONE_DATAIN, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100329
330 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200331 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100332
333 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200334 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw),
Harald Weltec043e642016-02-24 23:26:55 +0100335 CEMU_DATA_F_FINAL | CEMU_DATA_F_PB_AND_TX);
336 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100337 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100338
339 /* simulate some clock stop */
340 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
341 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
342}
343
344static void
345test_tpdu_card2reader(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
346{
347 printf("\n==> transmitting APDU (HDR + PB + card-TX)\n");
348
349 /* emulate the reader sending a TPDU header */
350 rdr_send_tpdu_hdr(ch, hdr);
Harald Welte86d047b2016-02-25 00:26:17 +0100351 card_tx_verify_chars(ch, NULL, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100352
353 /* card emulator PC sends a response PB via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200354 host_to_device_data(ch, hdr+1, 1, CEMU_DATA_F_PB_AND_TX);
Harald Weltec043e642016-02-24 23:26:55 +0100355
356 /* card actually sends that PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100357 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100358
359 /* emulate more characters from card to reader */
Harald Welte8e7fca32017-05-07 16:14:33 +0200360 host_to_device_data(ch, body, body_len, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100361 /* obtain those bytes as they arrvive on the card */
Harald Welte86d047b2016-02-25 00:26:17 +0100362 card_tx_verify_chars(ch, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100363
364 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200365 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100366
367 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200368 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw), CEMU_DATA_F_FINAL);
Harald Weltec043e642016-02-24 23:26:55 +0100369
370 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100371 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100372
373 /* simulate some clock stop */
374 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
375 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
376}
377
Harald Welte4ba66d02016-02-25 19:38:56 +0100378const uint8_t pps[] = {
379 /* PPSS identifies the PPS request or response and is set to
380 * 'FF'. */
381 0xFF, // PPSS
382 /* In PPS0, each bit 5, 6 or 7 set to 1 indicates the presence
383 * of an optional byte PPS 1 , PPS 2 , PPS 3 ,
384 * respectively. Bits 4 to 1 encode a type T to propose a
385 * transmission protocol. Bit 8 is reserved for future
386 * use and shall be set to 0. */
387 0b00010000, // PPS0: PPS1 present
388 0x00, // PPS1 proposed Fi/Di value
389 0xFF ^ 0b00010000// PCK
390};
391
392static void
393test_ppss(struct card_handle *ch)
394{
395 reader_send_bytes(ch, pps, sizeof(pps));
396 get_and_verify_rctx_pps(pps, sizeof(pps));
397 card_tx_verify_chars(ch, pps, sizeof(pps));
398}
Harald Weltec043e642016-02-24 23:26:55 +0100399
Harald Welteeef6c2a2016-02-24 22:19:03 +0100400/* READ RECORD (offset 0, 10 bytes) */
401const uint8_t tpdu_hdr_read_rec[] = { 0xA0, 0xB2, 0x00, 0x00, 0x0A };
402const uint8_t tpdu_body_read_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
403
404/* WRITE RECORD */
405const uint8_t tpdu_hdr_write_rec[] = { 0xA0, 0xD2, 0x00, 0x00, 0x07 };
406const uint8_t tpdu_body_write_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
Harald Welte84ec2522015-11-14 23:03:50 +0100407
Harald Welte9d3e3822015-11-09 00:50:54 +0100408int main(int argc, char **argv)
409{
410 struct card_handle *ch;
Harald Welte84ec2522015-11-14 23:03:50 +0100411 unsigned int i;
Harald Welte9d3e3822015-11-09 00:50:54 +0100412
Harald Welte752bc7f2021-04-05 19:08:11 +0200413 ch = card_emu_init(0, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
Harald Welte9d3e3822015-11-09 00:50:54 +0100414 assert(ch);
415
Harald Welte8e7fca32017-05-07 16:14:33 +0200416 usb_buf_init();
417
Harald Welteb4362862015-11-14 19:02:33 +0100418 /* start up the card (VCC/RST, ATR) */
Harald Welte9d3e3822015-11-09 00:50:54 +0100419 io_start_card(ch);
Harald Welte86d047b2016-02-25 00:26:17 +0100420 card_tx_verify_chars(ch, NULL, 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100421
Harald Welte4ba66d02016-02-25 19:38:56 +0100422 test_ppss(ch);
423
Harald Welte84ec2522015-11-14 23:03:50 +0100424 for (i = 0; i < 2; i++) {
Harald Weltec043e642016-02-24 23:26:55 +0100425 test_tpdu_reader2card(ch, tpdu_hdr_write_rec, tpdu_body_write_rec, sizeof(tpdu_body_write_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100426
Harald Weltec043e642016-02-24 23:26:55 +0100427 test_tpdu_card2reader(ch, tpdu_hdr_read_rec, tpdu_body_read_rec, sizeof(tpdu_body_read_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100428 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100429
430 exit(0);
431}