blob: 2a1d6827f84583bd3a5b28a4efd823a83aac3d52 [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 Welted401b122019-10-11 10:35:33 +020016/***********************************************************************
17 * stub functions required by card_emu.c
18 ***********************************************************************/
Harald Welte9d3e3822015-11-09 00:50:54 +010019
Harald Weltea1cd0f32017-02-27 14:29:07 +010020void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
21{
22}
23
Harald Welte9d3e3822015-11-09 00:50:54 +010024int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
25{
26 printf("uart_update_fidi(uart_chan=%u, fidi=%u)\n", uart_chan, fidi);
27 return 0;
28}
29
Harald Welte86d047b2016-02-25 00:26:17 +010030/* a buffer in which we store those bytes send by the UART towards the card
31 * reader, so we can verify in test cases what was actually written */
32static uint8_t tx_debug_buf[1024];
33static unsigned int tx_debug_buf_idx;
34
Harald Welted401b122019-10-11 10:35:33 +020035/* the card emulator wants to send some data to the host [reader] */
Harald Welte9d3e3822015-11-09 00:50:54 +010036int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
37{
Harald Welte6bf8c122016-02-24 21:04:08 +010038 printf("UART_TX(%02x)\n", byte);
Harald Welte86d047b2016-02-25 00:26:17 +010039 tx_debug_buf[tx_debug_buf_idx++] = byte;
Harald Welte9d3e3822015-11-09 00:50:54 +010040 return 1;
41}
42
43void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
44{
Harald Welteb4362862015-11-14 19:02:33 +010045 char *rts;
46 switch (rxtx) {
47 case 0:
48 rts = "OFF";
49 break;
50 case ENABLE_TX:
51 rts = "TX";
52 break;
53 case ENABLE_RX:
54 rts = "RX";
55 break;
56 default:
57 rts = "unknown";
58 break;
59 };
60
61 printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
Harald Welte9d3e3822015-11-09 00:50:54 +010062}
63
Kévin Redonebe672e2018-07-29 00:18:12 +020064void card_emu_uart_interrupt(uint8_t uart_chan)
65{
66 printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
67}
68
Harald Welte9d3e3822015-11-09 00:50:54 +010069void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
70{
71 printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
72}
73
74void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
75{
76 printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);
77}
78
79void tc_etu_init(uint8_t chan_nr, void *handle)
80{
Harald Welte6bf8c122016-02-24 21:04:08 +010081 printf("tc_etu_init(tc_chan=%u)\n", chan_nr);
Harald Welte9d3e3822015-11-09 00:50:54 +010082}
83
Harald Welte6bf8c122016-02-24 21:04:08 +010084void tc_etu_enable(uint8_t chan_nr)
85{
86 printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);
87}
Harald Welte9d3e3822015-11-09 00:50:54 +010088
Harald Welte6bf8c122016-02-24 21:04:08 +010089void tc_etu_disable(uint8_t chan_nr)
90{
91 printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);
92}
Harald Welte9d3e3822015-11-09 00:50:54 +010093
Harald Welted401b122019-10-11 10:35:33 +020094
95
96/***********************************************************************
97 * test helper functions
98 ***********************************************************************/
99
100
101static void reader_check_and_clear(const uint8_t *data, unsigned int len)
102{
103 assert(len == tx_debug_buf_idx);
104 assert(!memcmp(tx_debug_buf, data, len));
105 tx_debug_buf_idx = 0;
106}
107
108static const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100109
110static int verify_atr(struct card_handle *ch)
111{
Harald Welte9d3e3822015-11-09 00:50:54 +0100112 unsigned int i;
113
Harald Welte6bf8c122016-02-24 21:04:08 +0100114 printf("receiving + verifying ATR:\n");
Harald Welte9d3e3822015-11-09 00:50:54 +0100115 for (i = 0; i < sizeof(atr); i++) {
Harald Welte6bf8c122016-02-24 21:04:08 +0100116 assert(card_emu_tx_byte(ch) == 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100117 }
Harald Welte6bf8c122016-02-24 21:04:08 +0100118 assert(card_emu_tx_byte(ch) == 0);
Harald Welte86d047b2016-02-25 00:26:17 +0100119 reader_check_and_clear(atr, sizeof(atr));
Harald Welte9d3e3822015-11-09 00:50:54 +0100120
121 return 1;
122}
123
124static void io_start_card(struct card_handle *ch)
125{
Harald Welte86d047b2016-02-25 00:26:17 +0100126 card_emu_set_atr(ch, atr, sizeof(atr));
127
Harald Welte9d3e3822015-11-09 00:50:54 +0100128 /* bring the card up from the dead */
129 card_emu_io_statechg(ch, CARD_IO_VCC, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100130 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100131 card_emu_io_statechg(ch, CARD_IO_CLK, 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_RST, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100134 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100135
136 /* release from reset and verify th ATR */
137 card_emu_io_statechg(ch, CARD_IO_RST, 0);
Kévin Redonebe672e2018-07-29 00:18:12 +0200138 /* simulate waiting time before ATR expired */
139 tc_etu_wtime_expired(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100140 verify_atr(ch);
141}
142
Harald Welted401b122019-10-11 10:35:33 +0200143/* emulate the host/reader sending some bytes to the [emulated] card */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100144static void reader_send_bytes(struct card_handle *ch, const uint8_t *bytes, unsigned int len)
Harald Welte9d3e3822015-11-09 00:50:54 +0100145{
146 unsigned int i;
Harald Welte84ec2522015-11-14 23:03:50 +0100147 for (i = 0; i < len; i++) {
148 printf("UART_RX(%02x)\n", bytes[i]);
Harald Welte9d3e3822015-11-09 00:50:54 +0100149 card_emu_process_rx_byte(ch, bytes[i]);
Harald Welte84ec2522015-11-14 23:03:50 +0100150 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100151}
152
Harald Welte8e7fca32017-05-07 16:14:33 +0200153static void dump_rctx(struct msgb *msg)
Harald Welte9d3e3822015-11-09 00:50:54 +0100154{
Harald Welte25a9a802017-05-08 13:30:09 +0200155 struct simtrace_msg_hdr *mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100156 struct cardemu_usb_msg_rx_data *rxd;
157 int i;
Harald Welte8e7fca32017-05-07 16:14:33 +0200158#if 0
Harald Welte9d3e3822015-11-09 00:50:54 +0100159
160 printf("req_ctx(%p): state=%u, size=%u, tot_len=%u, idx=%u, data=%p\n",
161 rctx, rctx->state, rctx->size, rctx->tot_len, rctx->idx, rctx->data);
Harald Weltea1cd0f32017-02-27 14:29:07 +0100162 printf(" msg_type=%u, seq_nr=%u, msg_len=%u\n",
163 mh->msg_type, mh->seq_nr, mh->msg_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200164#endif
165 printf("%s\n", msgb_hexdump(msg));
Harald Welte9d3e3822015-11-09 00:50:54 +0100166
167 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200168 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
169 rxd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100170 printf(" flags=%x, data=", rxd->flags);
Harald Welted295b922016-03-18 21:01:36 +0100171 for (i = 0; i < rxd->data_len; i++)
Harald Welte9d3e3822015-11-09 00:50:54 +0100172 printf(" %02x", rxd->data[i]);
173 printf("\n");
174 break;
175 }
176}
177
Harald Welte8e7fca32017-05-07 16:14:33 +0200178static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int len)
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100179{
Harald Weltef4a625b2019-12-14 19:07:57 +0100180 struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
Harald Welte8e7fca32017-05-07 16:14:33 +0200181 struct msgb *msg;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100182 struct cardemu_usb_msg_tx_data *td;
183 struct cardemu_usb_msg_rx_data *rd;
Harald Welte25a9a802017-05-08 13:30:09 +0200184 struct simtrace_msg_hdr *mh;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100185
Harald Weltef4a625b2019-12-14 19:07:57 +0100186 assert(bep);
187 msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200188 assert(msg);
189 dump_rctx(msg);
190 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200191 mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100192
193 /* verify the contents of the rctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200194 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200195 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
196 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200197 assert(rd->data_len == len);
198 assert(!memcmp(rd->data, data, len));
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100199 break;
200#if 0
201 case RCTX_S_UART_RX_PENDING:
Harald Welte25a9a802017-05-08 13:30:09 +0200202 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welted295b922016-03-18 21:01:36 +0100203 assert(rd->data_len == len);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100204 assert(!memcmp(rd->data, data, len));
205 break;
206#endif
207 default:
208 assert(0);
209 }
210
211 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200212 usb_buf_free(msg);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100213}
214
Harald Welte4ba66d02016-02-25 19:38:56 +0100215static void get_and_verify_rctx_pps(const uint8_t *data, unsigned int len)
216{
Harald Weltef4a625b2019-12-14 19:07:57 +0100217 struct usb_buffered_ep *bep = usb_get_buf_ep(PHONE_DATAIN);
Harald Welte8e7fca32017-05-07 16:14:33 +0200218 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200219 struct simtrace_msg_hdr *mh;
Harald Welte4ba66d02016-02-25 19:38:56 +0100220 struct cardemu_usb_msg_pts_info *ptsi;
221
Harald Weltef4a625b2019-12-14 19:07:57 +0100222 assert(bep);
223 msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200224 assert(msg);
225 dump_rctx(msg);
226 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200227 mh = (struct simtrace_msg_hdr *) msg->l1h;
228 ptsi = (struct cardemu_usb_msg_pts_info *) msg->l2h;
Harald Welte4ba66d02016-02-25 19:38:56 +0100229
Harald Welte4ba66d02016-02-25 19:38:56 +0100230 /* FIXME: verify */
Harald Welte25a9a802017-05-08 13:30:09 +0200231 assert(mh->msg_type == SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte4ba66d02016-02-25 19:38:56 +0100232 assert(!memcmp(ptsi->req, data, len));
233 assert(!memcmp(ptsi->resp, data, len));
234
235 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200236 usb_buf_free(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100237}
238
Harald Welteb4362862015-11-14 19:02:33 +0100239/* emulate a TPDU header being sent by the reader/phone */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100240static void rdr_send_tpdu_hdr(struct card_handle *ch, const uint8_t *tpdu_hdr)
Harald Welte9d3e3822015-11-09 00:50:54 +0100241{
Harald Welte8e7fca32017-05-07 16:14:33 +0200242 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
243
Harald Welte9d3e3822015-11-09 00:50:54 +0100244 /* we don't want a receive context to become available during
245 * the first four bytes */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100246 reader_send_bytes(ch, tpdu_hdr, 4);
Harald Welte8e7fca32017-05-07 16:14:33 +0200247 assert(llist_empty(queue));
Harald Welte9d3e3822015-11-09 00:50:54 +0100248
Harald Welteeef6c2a2016-02-24 22:19:03 +0100249 reader_send_bytes(ch, tpdu_hdr+4, 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100250 /* but then after the final byte of the TPDU header, we want a
251 * receive context to be available for USB transmission */
Harald Welte8e7fca32017-05-07 16:14:33 +0200252 get_and_verify_rctx(PHONE_DATAIN, tpdu_hdr, 5);
Harald Welteb4362862015-11-14 19:02:33 +0100253}
254
Harald Welte25a9a802017-05-08 13:30:09 +0200255/* emulate a SIMTRACE_MSGT_DT_CEMU_TX_DATA received from USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200256static void host_to_device_data(struct card_handle *ch, const uint8_t *data, uint16_t len,
257 unsigned int flags)
Harald Welteb4362862015-11-14 19:02:33 +0100258{
Harald Welte8e7fca32017-05-07 16:14:33 +0200259 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200260 struct simtrace_msg_hdr *mh;
Harald Welte84ec2522015-11-14 23:03:50 +0100261 struct cardemu_usb_msg_tx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200262 struct llist_head *queue;
Harald Welteb4362862015-11-14 19:02:33 +0100263
264 /* allocate a free req_ctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200265 msg = usb_buf_alloc(PHONE_DATAOUT);
266 assert(msg);
Harald Welte25a9a802017-05-08 13:30:09 +0200267 /* initialize the common header */
Harald Welte8e7fca32017-05-07 16:14:33 +0200268 msg->l1h = msg->head;
Harald Welte25a9a802017-05-08 13:30:09 +0200269 mh = (struct simtrace_msg_hdr *) msgb_put(msg, sizeof(*mh));
270 mh->msg_class = SIMTRACE_MSGC_CARDEM;
271 mh->msg_type = SIMTRACE_MSGT_DT_CEMU_TX_DATA;
Harald Welteb4362862015-11-14 19:02:33 +0100272
Harald Welte25a9a802017-05-08 13:30:09 +0200273 /* initialize the tx_data message */
274 msg->l2h = msgb_put(msg, sizeof(*rd) + len);
275 rd = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welteeef6c2a2016-02-24 22:19:03 +0100276 rd->flags = flags;
Harald Welteb4362862015-11-14 19:02:33 +0100277 /* copy data and set length */
Harald Welted295b922016-03-18 21:01:36 +0100278 rd->data_len = len;
Harald Welteb4362862015-11-14 19:02:33 +0100279 memcpy(rd->data, data, len);
Harald Welte25a9a802017-05-08 13:30:09 +0200280
281 mh->msg_len = sizeof(*mh) + sizeof(*rd) + len;
Harald Welteb4362862015-11-14 19:02:33 +0100282
283 /* hand the req_ctx to the UART transmit code */
Harald Welte8e7fca32017-05-07 16:14:33 +0200284 queue = card_emu_get_uart_tx_queue(ch);
285 assert(queue);
286 msgb_enqueue(queue, msg);
Harald Welteb4362862015-11-14 19:02:33 +0100287}
288
Harald Welteeef6c2a2016-02-24 22:19:03 +0100289/* card-transmit any pending characters */
Harald Welte86d047b2016-02-25 00:26:17 +0100290static int card_tx_verify_chars(struct card_handle *ch, const uint8_t *data, unsigned int data_len)
Harald Welteb4362862015-11-14 19:02:33 +0100291{
Harald Welteb4362862015-11-14 19:02:33 +0100292 int count = 0;
293
Harald Welte6bf8c122016-02-24 21:04:08 +0100294 while (card_emu_tx_byte(ch)) {
Harald Welteb4362862015-11-14 19:02:33 +0100295 count++;
296 }
Harald Welte86d047b2016-02-25 00:26:17 +0100297
298 assert(count == data_len);
299 reader_check_and_clear(data, data_len);
300
Harald Welteb4362862015-11-14 19:02:33 +0100301 return count;
Harald Welte9d3e3822015-11-09 00:50:54 +0100302}
303
Harald Welte84ec2522015-11-14 23:03:50 +0100304const uint8_t tpdu_hdr_sel_mf[] = { 0xA0, 0xA4, 0x00, 0x00, 0x00 };
Harald Welte61bb30e2015-11-14 23:44:14 +0100305const uint8_t tpdu_pb_sw[] = { 0x90, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100306
Harald Weltec043e642016-02-24 23:26:55 +0100307static void
308test_tpdu_reader2card(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
309{
Harald Weltec043e642016-02-24 23:26:55 +0100310 printf("\n==> transmitting APDU (HDR + PB + card-RX)\n");
311
312 /* emulate the reader sending a TPDU header */
313 rdr_send_tpdu_hdr(ch, hdr);
314 /* we shouldn't have any pending card-TX yet */
Harald Welte86d047b2016-02-25 00:26:17 +0100315 card_tx_verify_chars(ch, NULL, 0);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100316
Harald Weltec043e642016-02-24 23:26:55 +0100317 /* card emulator PC sends a singly byte PB response via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200318 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 +0100319 /* card actually sends that single PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100320 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100321
322 /* emulate more characters from reader to card */
323 reader_send_bytes(ch, body, body_len);
324
325 /* check if we have received them on the USB side */
Harald Welte8e7fca32017-05-07 16:14:33 +0200326 get_and_verify_rctx(PHONE_DATAIN, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100327
328 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200329 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100330
331 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200332 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw),
Harald Weltec043e642016-02-24 23:26:55 +0100333 CEMU_DATA_F_FINAL | CEMU_DATA_F_PB_AND_TX);
334 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100335 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100336
337 /* simulate some clock stop */
338 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
339 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
340}
341
342static void
343test_tpdu_card2reader(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
344{
345 printf("\n==> transmitting APDU (HDR + PB + card-TX)\n");
346
347 /* emulate the reader sending a TPDU header */
348 rdr_send_tpdu_hdr(ch, hdr);
Harald Welte86d047b2016-02-25 00:26:17 +0100349 card_tx_verify_chars(ch, NULL, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100350
351 /* card emulator PC sends a response PB via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200352 host_to_device_data(ch, hdr+1, 1, CEMU_DATA_F_PB_AND_TX);
Harald Weltec043e642016-02-24 23:26:55 +0100353
354 /* card actually sends that PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100355 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100356
357 /* emulate more characters from card to reader */
Harald Welte8e7fca32017-05-07 16:14:33 +0200358 host_to_device_data(ch, body, body_len, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100359 /* obtain those bytes as they arrvive on the card */
Harald Welte86d047b2016-02-25 00:26:17 +0100360 card_tx_verify_chars(ch, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100361
362 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200363 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100364
365 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200366 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw), CEMU_DATA_F_FINAL);
Harald Weltec043e642016-02-24 23:26:55 +0100367
368 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100369 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100370
371 /* simulate some clock stop */
372 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
373 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
374}
375
Harald Welte4ba66d02016-02-25 19:38:56 +0100376const uint8_t pps[] = {
377 /* PPSS identifies the PPS request or response and is set to
378 * 'FF'. */
379 0xFF, // PPSS
380 /* In PPS0, each bit 5, 6 or 7 set to 1 indicates the presence
381 * of an optional byte PPS 1 , PPS 2 , PPS 3 ,
382 * respectively. Bits 4 to 1 encode a type T to propose a
383 * transmission protocol. Bit 8 is reserved for future
384 * use and shall be set to 0. */
385 0b00010000, // PPS0: PPS1 present
386 0x00, // PPS1 proposed Fi/Di value
387 0xFF ^ 0b00010000// PCK
388};
389
390static void
391test_ppss(struct card_handle *ch)
392{
393 reader_send_bytes(ch, pps, sizeof(pps));
394 get_and_verify_rctx_pps(pps, sizeof(pps));
395 card_tx_verify_chars(ch, pps, sizeof(pps));
396}
Harald Weltec043e642016-02-24 23:26:55 +0100397
Harald Welteeef6c2a2016-02-24 22:19:03 +0100398/* READ RECORD (offset 0, 10 bytes) */
399const uint8_t tpdu_hdr_read_rec[] = { 0xA0, 0xB2, 0x00, 0x00, 0x0A };
400const uint8_t tpdu_body_read_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
401
402/* WRITE RECORD */
403const uint8_t tpdu_hdr_write_rec[] = { 0xA0, 0xD2, 0x00, 0x00, 0x07 };
404const uint8_t tpdu_body_write_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
Harald Welte84ec2522015-11-14 23:03:50 +0100405
Harald Welte9d3e3822015-11-09 00:50:54 +0100406int main(int argc, char **argv)
407{
408 struct card_handle *ch;
Harald Welte84ec2522015-11-14 23:03:50 +0100409 unsigned int i;
Harald Welte9d3e3822015-11-09 00:50:54 +0100410
Kévin Redon7233cf82019-11-14 19:37:32 +0100411 ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
Harald Welte9d3e3822015-11-09 00:50:54 +0100412 assert(ch);
413
Harald Welte8e7fca32017-05-07 16:14:33 +0200414 usb_buf_init();
415
Harald Welteb4362862015-11-14 19:02:33 +0100416 /* start up the card (VCC/RST, ATR) */
Harald Welte9d3e3822015-11-09 00:50:54 +0100417 io_start_card(ch);
Harald Welte86d047b2016-02-25 00:26:17 +0100418 card_tx_verify_chars(ch, NULL, 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100419
Harald Welte4ba66d02016-02-25 19:38:56 +0100420 test_ppss(ch);
421
Harald Welte84ec2522015-11-14 23:03:50 +0100422 for (i = 0; i < 2; i++) {
Harald Weltec043e642016-02-24 23:26:55 +0100423 test_tpdu_reader2card(ch, tpdu_hdr_write_rec, tpdu_body_write_rec, sizeof(tpdu_body_write_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100424
Harald Weltec043e642016-02-24 23:26:55 +0100425 test_tpdu_card2reader(ch, tpdu_hdr_read_rec, tpdu_body_read_rec, sizeof(tpdu_body_read_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100426 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100427
428 exit(0);
429}