blob: fe1739be2967601dc476a3ef31b388fe13b2cedf [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
16/* stub functions required by card_emu.c */
17
Harald Weltea1cd0f32017-02-27 14:29:07 +010018void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
19{
20}
21
Harald Welte9d3e3822015-11-09 00:50:54 +010022int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
23{
24 printf("uart_update_fidi(uart_chan=%u, fidi=%u)\n", uart_chan, fidi);
25 return 0;
26}
27
Harald Welte86d047b2016-02-25 00:26:17 +010028/* a buffer in which we store those bytes send by the UART towards the card
29 * reader, so we can verify in test cases what was actually written */
30static uint8_t tx_debug_buf[1024];
31static unsigned int tx_debug_buf_idx;
32
Harald Welte9d3e3822015-11-09 00:50:54 +010033int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
34{
Harald Welte6bf8c122016-02-24 21:04:08 +010035 printf("UART_TX(%02x)\n", byte);
Harald Welte86d047b2016-02-25 00:26:17 +010036 tx_debug_buf[tx_debug_buf_idx++] = byte;
Harald Welte9d3e3822015-11-09 00:50:54 +010037 return 1;
38}
39
Harald Welte86d047b2016-02-25 00:26:17 +010040static void reader_check_and_clear(const uint8_t *data, unsigned int len)
41{
42 assert(len == tx_debug_buf_idx);
43 assert(!memcmp(tx_debug_buf, data, len));
44 tx_debug_buf_idx = 0;
45}
46
Harald Welte9d3e3822015-11-09 00:50:54 +010047void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
48{
Harald Welteb4362862015-11-14 19:02:33 +010049 char *rts;
50 switch (rxtx) {
51 case 0:
52 rts = "OFF";
53 break;
54 case ENABLE_TX:
55 rts = "TX";
56 break;
57 case ENABLE_RX:
58 rts = "RX";
59 break;
60 default:
61 rts = "unknown";
62 break;
63 };
64
65 printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
Harald Welte9d3e3822015-11-09 00:50:54 +010066}
67
Kévin Redonebe672e2018-07-29 00:18:12 +020068void card_emu_uart_interrupt(uint8_t uart_chan)
69{
70 printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
71}
72
Harald Welte9d3e3822015-11-09 00:50:54 +010073void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
74{
75 printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
76}
77
78void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
79{
80 printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);
81}
82
83void tc_etu_init(uint8_t chan_nr, void *handle)
84{
Harald Welte6bf8c122016-02-24 21:04:08 +010085 printf("tc_etu_init(tc_chan=%u)\n", chan_nr);
Harald Welte9d3e3822015-11-09 00:50:54 +010086}
87
Harald Welte6bf8c122016-02-24 21:04:08 +010088void tc_etu_enable(uint8_t chan_nr)
89{
90 printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);
91}
Harald Welte9d3e3822015-11-09 00:50:54 +010092
Harald Welte6bf8c122016-02-24 21:04:08 +010093void tc_etu_disable(uint8_t chan_nr)
94{
95 printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);
96}
Harald Welte9d3e3822015-11-09 00:50:54 +010097
Harald Welte86d047b2016-02-25 00:26:17 +010098const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
Harald Welte9d3e3822015-11-09 00:50:54 +010099
100static int verify_atr(struct card_handle *ch)
101{
Harald Welte9d3e3822015-11-09 00:50:54 +0100102 unsigned int i;
103
Harald Welte6bf8c122016-02-24 21:04:08 +0100104 printf("receiving + verifying ATR:\n");
Harald Welte9d3e3822015-11-09 00:50:54 +0100105 for (i = 0; i < sizeof(atr); i++) {
Harald Welte6bf8c122016-02-24 21:04:08 +0100106 assert(card_emu_tx_byte(ch) == 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100107 }
Harald Welte6bf8c122016-02-24 21:04:08 +0100108 assert(card_emu_tx_byte(ch) == 0);
Harald Welte86d047b2016-02-25 00:26:17 +0100109 reader_check_and_clear(atr, sizeof(atr));
Harald Welte9d3e3822015-11-09 00:50:54 +0100110
111 return 1;
112}
113
114static void io_start_card(struct card_handle *ch)
115{
Harald Welte86d047b2016-02-25 00:26:17 +0100116 card_emu_set_atr(ch, atr, sizeof(atr));
117
Harald Welte9d3e3822015-11-09 00:50:54 +0100118 /* bring the card up from the dead */
119 card_emu_io_statechg(ch, CARD_IO_VCC, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100120 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100121 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100122 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100123 card_emu_io_statechg(ch, CARD_IO_RST, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100124 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100125
126 /* release from reset and verify th ATR */
127 card_emu_io_statechg(ch, CARD_IO_RST, 0);
Kévin Redonebe672e2018-07-29 00:18:12 +0200128 /* simulate waiting time before ATR expired */
129 tc_etu_wtime_expired(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100130 verify_atr(ch);
131}
132
Harald Welteeef6c2a2016-02-24 22:19:03 +0100133static void reader_send_bytes(struct card_handle *ch, const uint8_t *bytes, unsigned int len)
Harald Welte9d3e3822015-11-09 00:50:54 +0100134{
135 unsigned int i;
Harald Welte84ec2522015-11-14 23:03:50 +0100136 for (i = 0; i < len; i++) {
137 printf("UART_RX(%02x)\n", bytes[i]);
Harald Welte9d3e3822015-11-09 00:50:54 +0100138 card_emu_process_rx_byte(ch, bytes[i]);
Harald Welte84ec2522015-11-14 23:03:50 +0100139 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100140}
141
Harald Welte8e7fca32017-05-07 16:14:33 +0200142static void dump_rctx(struct msgb *msg)
Harald Welte9d3e3822015-11-09 00:50:54 +0100143{
Harald Welte25a9a802017-05-08 13:30:09 +0200144 struct simtrace_msg_hdr *mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100145 struct cardemu_usb_msg_rx_data *rxd;
146 int i;
Harald Welte8e7fca32017-05-07 16:14:33 +0200147#if 0
Harald Welte9d3e3822015-11-09 00:50:54 +0100148
149 printf("req_ctx(%p): state=%u, size=%u, tot_len=%u, idx=%u, data=%p\n",
150 rctx, rctx->state, rctx->size, rctx->tot_len, rctx->idx, rctx->data);
Harald Weltea1cd0f32017-02-27 14:29:07 +0100151 printf(" msg_type=%u, seq_nr=%u, msg_len=%u\n",
152 mh->msg_type, mh->seq_nr, mh->msg_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200153#endif
154 printf("%s\n", msgb_hexdump(msg));
Harald Welte9d3e3822015-11-09 00:50:54 +0100155
156 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200157 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
158 rxd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100159 printf(" flags=%x, data=", rxd->flags);
Harald Welted295b922016-03-18 21:01:36 +0100160 for (i = 0; i < rxd->data_len; i++)
Harald Welte9d3e3822015-11-09 00:50:54 +0100161 printf(" %02x", rxd->data[i]);
162 printf("\n");
163 break;
164 }
165}
166
Harald Welte8e7fca32017-05-07 16:14:33 +0200167static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int len)
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100168{
Harald Welte8e7fca32017-05-07 16:14:33 +0200169 struct llist_head *queue = usb_get_queue(ep);
170 struct msgb *msg;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100171 struct cardemu_usb_msg_tx_data *td;
172 struct cardemu_usb_msg_rx_data *rd;
Harald Welte25a9a802017-05-08 13:30:09 +0200173 struct simtrace_msg_hdr *mh;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100174
Harald Welte8e7fca32017-05-07 16:14:33 +0200175 assert(queue);
176 msg = msgb_dequeue(queue);
177 assert(msg);
178 dump_rctx(msg);
179 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200180 mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100181
182 /* verify the contents of the rctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200183 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200184 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
185 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200186 assert(rd->data_len == len);
187 assert(!memcmp(rd->data, data, len));
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100188 break;
189#if 0
190 case RCTX_S_UART_RX_PENDING:
Harald Welte25a9a802017-05-08 13:30:09 +0200191 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welted295b922016-03-18 21:01:36 +0100192 assert(rd->data_len == len);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100193 assert(!memcmp(rd->data, data, len));
194 break;
195#endif
196 default:
197 assert(0);
198 }
199
200 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200201 usb_buf_free(msg);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100202}
203
Harald Welte4ba66d02016-02-25 19:38:56 +0100204static void get_and_verify_rctx_pps(const uint8_t *data, unsigned int len)
205{
Harald Welte8e7fca32017-05-07 16:14:33 +0200206 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
207 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200208 struct simtrace_msg_hdr *mh;
Harald Welte4ba66d02016-02-25 19:38:56 +0100209 struct cardemu_usb_msg_pts_info *ptsi;
210
Harald Welte8e7fca32017-05-07 16:14:33 +0200211 assert(queue);
212 msg = msgb_dequeue(queue);
213 assert(msg);
214 dump_rctx(msg);
215 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200216 mh = (struct simtrace_msg_hdr *) msg->l1h;
217 ptsi = (struct cardemu_usb_msg_pts_info *) msg->l2h;
Harald Welte4ba66d02016-02-25 19:38:56 +0100218
Harald Welte4ba66d02016-02-25 19:38:56 +0100219 /* FIXME: verify */
Harald Welte25a9a802017-05-08 13:30:09 +0200220 assert(mh->msg_type == SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte4ba66d02016-02-25 19:38:56 +0100221 assert(!memcmp(ptsi->req, data, len));
222 assert(!memcmp(ptsi->resp, data, len));
223
224 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200225 usb_buf_free(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100226}
227
Harald Welteb4362862015-11-14 19:02:33 +0100228/* emulate a TPDU header being sent by the reader/phone */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100229static void rdr_send_tpdu_hdr(struct card_handle *ch, const uint8_t *tpdu_hdr)
Harald Welte9d3e3822015-11-09 00:50:54 +0100230{
Harald Welte8e7fca32017-05-07 16:14:33 +0200231 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
232
Harald Welte9d3e3822015-11-09 00:50:54 +0100233 /* we don't want a receive context to become available during
234 * the first four bytes */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100235 reader_send_bytes(ch, tpdu_hdr, 4);
Harald Welte8e7fca32017-05-07 16:14:33 +0200236 assert(llist_empty(queue));
Harald Welte9d3e3822015-11-09 00:50:54 +0100237
Harald Welteeef6c2a2016-02-24 22:19:03 +0100238 reader_send_bytes(ch, tpdu_hdr+4, 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100239 /* but then after the final byte of the TPDU header, we want a
240 * receive context to be available for USB transmission */
Harald Welte8e7fca32017-05-07 16:14:33 +0200241 get_and_verify_rctx(PHONE_DATAIN, tpdu_hdr, 5);
Harald Welteb4362862015-11-14 19:02:33 +0100242}
243
Harald Welte25a9a802017-05-08 13:30:09 +0200244/* emulate a SIMTRACE_MSGT_DT_CEMU_TX_DATA received from USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200245static void host_to_device_data(struct card_handle *ch, const uint8_t *data, uint16_t len,
246 unsigned int flags)
Harald Welteb4362862015-11-14 19:02:33 +0100247{
Harald Welte8e7fca32017-05-07 16:14:33 +0200248 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200249 struct simtrace_msg_hdr *mh;
Harald Welte84ec2522015-11-14 23:03:50 +0100250 struct cardemu_usb_msg_tx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200251 struct llist_head *queue;
Harald Welteb4362862015-11-14 19:02:33 +0100252
253 /* allocate a free req_ctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200254 msg = usb_buf_alloc(PHONE_DATAOUT);
255 assert(msg);
Harald Welte25a9a802017-05-08 13:30:09 +0200256 /* initialize the common header */
Harald Welte8e7fca32017-05-07 16:14:33 +0200257 msg->l1h = msg->head;
Harald Welte25a9a802017-05-08 13:30:09 +0200258 mh = (struct simtrace_msg_hdr *) msgb_put(msg, sizeof(*mh));
259 mh->msg_class = SIMTRACE_MSGC_CARDEM;
260 mh->msg_type = SIMTRACE_MSGT_DT_CEMU_TX_DATA;
Harald Welteb4362862015-11-14 19:02:33 +0100261
Harald Welte25a9a802017-05-08 13:30:09 +0200262 /* initialize the tx_data message */
263 msg->l2h = msgb_put(msg, sizeof(*rd) + len);
264 rd = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welteeef6c2a2016-02-24 22:19:03 +0100265 rd->flags = flags;
Harald Welteb4362862015-11-14 19:02:33 +0100266 /* copy data and set length */
Harald Welted295b922016-03-18 21:01:36 +0100267 rd->data_len = len;
Harald Welteb4362862015-11-14 19:02:33 +0100268 memcpy(rd->data, data, len);
Harald Welte25a9a802017-05-08 13:30:09 +0200269
270 mh->msg_len = sizeof(*mh) + sizeof(*rd) + len;
Harald Welteb4362862015-11-14 19:02:33 +0100271
272 /* hand the req_ctx to the UART transmit code */
Harald Welte8e7fca32017-05-07 16:14:33 +0200273 queue = card_emu_get_uart_tx_queue(ch);
274 assert(queue);
275 msgb_enqueue(queue, msg);
Harald Welteb4362862015-11-14 19:02:33 +0100276}
277
Harald Welteeef6c2a2016-02-24 22:19:03 +0100278/* card-transmit any pending characters */
Harald Welte86d047b2016-02-25 00:26:17 +0100279static int card_tx_verify_chars(struct card_handle *ch, const uint8_t *data, unsigned int data_len)
Harald Welteb4362862015-11-14 19:02:33 +0100280{
Harald Welteb4362862015-11-14 19:02:33 +0100281 int count = 0;
282
Harald Welte6bf8c122016-02-24 21:04:08 +0100283 while (card_emu_tx_byte(ch)) {
Harald Welteb4362862015-11-14 19:02:33 +0100284 count++;
285 }
Harald Welte86d047b2016-02-25 00:26:17 +0100286
287 assert(count == data_len);
288 reader_check_and_clear(data, data_len);
289
Harald Welteb4362862015-11-14 19:02:33 +0100290 return count;
Harald Welte9d3e3822015-11-09 00:50:54 +0100291}
292
Harald Welte84ec2522015-11-14 23:03:50 +0100293const uint8_t tpdu_hdr_sel_mf[] = { 0xA0, 0xA4, 0x00, 0x00, 0x00 };
Harald Welte61bb30e2015-11-14 23:44:14 +0100294const uint8_t tpdu_pb_sw[] = { 0x90, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100295
Harald Weltec043e642016-02-24 23:26:55 +0100296static void
297test_tpdu_reader2card(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
298{
Harald Weltec043e642016-02-24 23:26:55 +0100299 printf("\n==> transmitting APDU (HDR + PB + card-RX)\n");
300
301 /* emulate the reader sending a TPDU header */
302 rdr_send_tpdu_hdr(ch, hdr);
303 /* we shouldn't have any pending card-TX yet */
Harald Welte86d047b2016-02-25 00:26:17 +0100304 card_tx_verify_chars(ch, NULL, 0);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100305
Harald Weltec043e642016-02-24 23:26:55 +0100306 /* card emulator PC sends a singly byte PB response via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200307 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 +0100308 /* card actually sends that single PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100309 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100310
311 /* emulate more characters from reader to card */
312 reader_send_bytes(ch, body, body_len);
313
314 /* check if we have received them on the USB side */
Harald Welte8e7fca32017-05-07 16:14:33 +0200315 get_and_verify_rctx(PHONE_DATAIN, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100316
317 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200318 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100319
320 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200321 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw),
Harald Weltec043e642016-02-24 23:26:55 +0100322 CEMU_DATA_F_FINAL | CEMU_DATA_F_PB_AND_TX);
323 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100324 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100325
326 /* simulate some clock stop */
327 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
328 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
329}
330
331static void
332test_tpdu_card2reader(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
333{
334 printf("\n==> transmitting APDU (HDR + PB + card-TX)\n");
335
336 /* emulate the reader sending a TPDU header */
337 rdr_send_tpdu_hdr(ch, hdr);
Harald Welte86d047b2016-02-25 00:26:17 +0100338 card_tx_verify_chars(ch, NULL, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100339
340 /* card emulator PC sends a response PB via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200341 host_to_device_data(ch, hdr+1, 1, CEMU_DATA_F_PB_AND_TX);
Harald Weltec043e642016-02-24 23:26:55 +0100342
343 /* card actually sends that PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100344 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100345
346 /* emulate more characters from card to reader */
Harald Welte8e7fca32017-05-07 16:14:33 +0200347 host_to_device_data(ch, body, body_len, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100348 /* obtain those bytes as they arrvive on the card */
Harald Welte86d047b2016-02-25 00:26:17 +0100349 card_tx_verify_chars(ch, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100350
351 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200352 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100353
354 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200355 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw), CEMU_DATA_F_FINAL);
Harald Weltec043e642016-02-24 23:26:55 +0100356
357 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100358 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100359
360 /* simulate some clock stop */
361 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
362 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
363}
364
Harald Welte4ba66d02016-02-25 19:38:56 +0100365const uint8_t pps[] = {
366 /* PPSS identifies the PPS request or response and is set to
367 * 'FF'. */
368 0xFF, // PPSS
369 /* In PPS0, each bit 5, 6 or 7 set to 1 indicates the presence
370 * of an optional byte PPS 1 , PPS 2 , PPS 3 ,
371 * respectively. Bits 4 to 1 encode a type T to propose a
372 * transmission protocol. Bit 8 is reserved for future
373 * use and shall be set to 0. */
374 0b00010000, // PPS0: PPS1 present
375 0x00, // PPS1 proposed Fi/Di value
376 0xFF ^ 0b00010000// PCK
377};
378
379static void
380test_ppss(struct card_handle *ch)
381{
382 reader_send_bytes(ch, pps, sizeof(pps));
383 get_and_verify_rctx_pps(pps, sizeof(pps));
384 card_tx_verify_chars(ch, pps, sizeof(pps));
385}
Harald Weltec043e642016-02-24 23:26:55 +0100386
Harald Welteeef6c2a2016-02-24 22:19:03 +0100387/* READ RECORD (offset 0, 10 bytes) */
388const uint8_t tpdu_hdr_read_rec[] = { 0xA0, 0xB2, 0x00, 0x00, 0x0A };
389const uint8_t tpdu_body_read_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
390
391/* WRITE RECORD */
392const uint8_t tpdu_hdr_write_rec[] = { 0xA0, 0xD2, 0x00, 0x00, 0x07 };
393const uint8_t tpdu_body_write_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
Harald Welte84ec2522015-11-14 23:03:50 +0100394
Harald Welte9d3e3822015-11-09 00:50:54 +0100395int main(int argc, char **argv)
396{
397 struct card_handle *ch;
Harald Welte84ec2522015-11-14 23:03:50 +0100398 unsigned int i;
Harald Welte9d3e3822015-11-09 00:50:54 +0100399
Kévin Redon7233cf82019-11-14 19:37:32 +0100400 ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
Harald Welte9d3e3822015-11-09 00:50:54 +0100401 assert(ch);
402
Harald Welte8e7fca32017-05-07 16:14:33 +0200403 usb_buf_init();
404
Harald Welteb4362862015-11-14 19:02:33 +0100405 /* start up the card (VCC/RST, ATR) */
Harald Welte9d3e3822015-11-09 00:50:54 +0100406 io_start_card(ch);
Harald Welte86d047b2016-02-25 00:26:17 +0100407 card_tx_verify_chars(ch, NULL, 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100408
Harald Welte4ba66d02016-02-25 19:38:56 +0100409 test_ppss(ch);
410
Harald Welte84ec2522015-11-14 23:03:50 +0100411 for (i = 0; i < 2; i++) {
Harald Weltec043e642016-02-24 23:26:55 +0100412 test_tpdu_reader2card(ch, tpdu_hdr_write_rec, tpdu_body_write_rec, sizeof(tpdu_body_write_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100413
Harald Weltec043e642016-02-24 23:26:55 +0100414 test_tpdu_card2reader(ch, tpdu_hdr_read_rec, tpdu_body_read_rec, sizeof(tpdu_body_read_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100415 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100416
417 exit(0);
418}