blob: 3ea0678dea4d64af08c80c83340905b67414fcba [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
68void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
69{
70 printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
71}
72
73void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
74{
75 printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);
76}
77
78void tc_etu_init(uint8_t chan_nr, void *handle)
79{
Harald Welte6bf8c122016-02-24 21:04:08 +010080 printf("tc_etu_init(tc_chan=%u)\n", chan_nr);
Harald Welte9d3e3822015-11-09 00:50:54 +010081}
82
Harald Welte6bf8c122016-02-24 21:04:08 +010083void tc_etu_enable(uint8_t chan_nr)
84{
85 printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);
86}
Harald Welte9d3e3822015-11-09 00:50:54 +010087
Harald Welte6bf8c122016-02-24 21:04:08 +010088void tc_etu_disable(uint8_t chan_nr)
89{
90 printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);
91}
Harald Welte9d3e3822015-11-09 00:50:54 +010092
Harald Welte86d047b2016-02-25 00:26:17 +010093const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
Harald Welte9d3e3822015-11-09 00:50:54 +010094
95static int verify_atr(struct card_handle *ch)
96{
Harald Welte9d3e3822015-11-09 00:50:54 +010097 unsigned int i;
98
Harald Welte6bf8c122016-02-24 21:04:08 +010099 printf("receiving + verifying ATR:\n");
Harald Welte9d3e3822015-11-09 00:50:54 +0100100 for (i = 0; i < sizeof(atr); i++) {
Harald Welte6bf8c122016-02-24 21:04:08 +0100101 assert(card_emu_tx_byte(ch) == 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100102 }
Harald Welte6bf8c122016-02-24 21:04:08 +0100103 assert(card_emu_tx_byte(ch) == 0);
Harald Welte86d047b2016-02-25 00:26:17 +0100104 reader_check_and_clear(atr, sizeof(atr));
Harald Welte9d3e3822015-11-09 00:50:54 +0100105
106 return 1;
107}
108
109static void io_start_card(struct card_handle *ch)
110{
Harald Welte86d047b2016-02-25 00:26:17 +0100111 card_emu_set_atr(ch, atr, sizeof(atr));
112
Harald Welte9d3e3822015-11-09 00:50:54 +0100113 /* bring the card up from the dead */
114 card_emu_io_statechg(ch, CARD_IO_VCC, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100115 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100116 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100117 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100118 card_emu_io_statechg(ch, CARD_IO_RST, 1);
Harald Welte6bf8c122016-02-24 21:04:08 +0100119 assert(card_emu_tx_byte(ch) == 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100120
121 /* release from reset and verify th ATR */
122 card_emu_io_statechg(ch, CARD_IO_RST, 0);
123 verify_atr(ch);
124}
125
Harald Welteeef6c2a2016-02-24 22:19:03 +0100126static void reader_send_bytes(struct card_handle *ch, const uint8_t *bytes, unsigned int len)
Harald Welte9d3e3822015-11-09 00:50:54 +0100127{
128 unsigned int i;
Harald Welte84ec2522015-11-14 23:03:50 +0100129 for (i = 0; i < len; i++) {
130 printf("UART_RX(%02x)\n", bytes[i]);
Harald Welte9d3e3822015-11-09 00:50:54 +0100131 card_emu_process_rx_byte(ch, bytes[i]);
Harald Welte84ec2522015-11-14 23:03:50 +0100132 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100133}
134
Harald Welte8e7fca32017-05-07 16:14:33 +0200135static void dump_rctx(struct msgb *msg)
Harald Welte9d3e3822015-11-09 00:50:54 +0100136{
Harald Welte25a9a802017-05-08 13:30:09 +0200137 struct simtrace_msg_hdr *mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100138 struct cardemu_usb_msg_rx_data *rxd;
139 int i;
Harald Welte8e7fca32017-05-07 16:14:33 +0200140#if 0
Harald Welte9d3e3822015-11-09 00:50:54 +0100141
142 printf("req_ctx(%p): state=%u, size=%u, tot_len=%u, idx=%u, data=%p\n",
143 rctx, rctx->state, rctx->size, rctx->tot_len, rctx->idx, rctx->data);
Harald Weltea1cd0f32017-02-27 14:29:07 +0100144 printf(" msg_type=%u, seq_nr=%u, msg_len=%u\n",
145 mh->msg_type, mh->seq_nr, mh->msg_len);
Harald Welte8e7fca32017-05-07 16:14:33 +0200146#endif
147 printf("%s\n", msgb_hexdump(msg));
Harald Welte9d3e3822015-11-09 00:50:54 +0100148
149 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200150 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
151 rxd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100152 printf(" flags=%x, data=", rxd->flags);
Harald Welted295b922016-03-18 21:01:36 +0100153 for (i = 0; i < rxd->data_len; i++)
Harald Welte9d3e3822015-11-09 00:50:54 +0100154 printf(" %02x", rxd->data[i]);
155 printf("\n");
156 break;
157 }
158}
159
Harald Welte8e7fca32017-05-07 16:14:33 +0200160static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int len)
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100161{
Harald Welte8e7fca32017-05-07 16:14:33 +0200162 struct llist_head *queue = usb_get_queue(ep);
163 struct msgb *msg;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100164 struct cardemu_usb_msg_tx_data *td;
165 struct cardemu_usb_msg_rx_data *rd;
Harald Welte25a9a802017-05-08 13:30:09 +0200166 struct simtrace_msg_hdr *mh;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100167
Harald Welte8e7fca32017-05-07 16:14:33 +0200168 assert(queue);
169 msg = msgb_dequeue(queue);
170 assert(msg);
171 dump_rctx(msg);
172 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200173 mh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100174
175 /* verify the contents of the rctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200176 switch (mh->msg_type) {
Harald Welte25a9a802017-05-08 13:30:09 +0200177 case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
178 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200179 assert(rd->data_len == len);
180 assert(!memcmp(rd->data, data, len));
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100181 break;
182#if 0
183 case RCTX_S_UART_RX_PENDING:
Harald Welte25a9a802017-05-08 13:30:09 +0200184 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welted295b922016-03-18 21:01:36 +0100185 assert(rd->data_len == len);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100186 assert(!memcmp(rd->data, data, len));
187 break;
188#endif
189 default:
190 assert(0);
191 }
192
193 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200194 usb_buf_free(msg);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100195}
196
Harald Welte4ba66d02016-02-25 19:38:56 +0100197static void get_and_verify_rctx_pps(const uint8_t *data, unsigned int len)
198{
Harald Welte8e7fca32017-05-07 16:14:33 +0200199 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
200 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200201 struct simtrace_msg_hdr *mh;
Harald Welte4ba66d02016-02-25 19:38:56 +0100202 struct cardemu_usb_msg_pts_info *ptsi;
203
Harald Welte8e7fca32017-05-07 16:14:33 +0200204 assert(queue);
205 msg = msgb_dequeue(queue);
206 assert(msg);
207 dump_rctx(msg);
208 assert(msg->l1h);
Harald Welte25a9a802017-05-08 13:30:09 +0200209 mh = (struct simtrace_msg_hdr *) msg->l1h;
210 ptsi = (struct cardemu_usb_msg_pts_info *) msg->l2h;
Harald Welte4ba66d02016-02-25 19:38:56 +0100211
Harald Welte4ba66d02016-02-25 19:38:56 +0100212 /* FIXME: verify */
Harald Welte25a9a802017-05-08 13:30:09 +0200213 assert(mh->msg_type == SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte4ba66d02016-02-25 19:38:56 +0100214 assert(!memcmp(ptsi->req, data, len));
215 assert(!memcmp(ptsi->resp, data, len));
216
217 /* free the req_ctx, indicating it has fully arrived on the host */
Harald Welte8e7fca32017-05-07 16:14:33 +0200218 usb_buf_free(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100219}
220
Harald Welteb4362862015-11-14 19:02:33 +0100221/* emulate a TPDU header being sent by the reader/phone */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100222static void rdr_send_tpdu_hdr(struct card_handle *ch, const uint8_t *tpdu_hdr)
Harald Welte9d3e3822015-11-09 00:50:54 +0100223{
Harald Welte8e7fca32017-05-07 16:14:33 +0200224 struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
225
Harald Welte9d3e3822015-11-09 00:50:54 +0100226 /* we don't want a receive context to become available during
227 * the first four bytes */
Harald Welteeef6c2a2016-02-24 22:19:03 +0100228 reader_send_bytes(ch, tpdu_hdr, 4);
Harald Welte8e7fca32017-05-07 16:14:33 +0200229 assert(llist_empty(queue));
Harald Welte9d3e3822015-11-09 00:50:54 +0100230
Harald Welteeef6c2a2016-02-24 22:19:03 +0100231 reader_send_bytes(ch, tpdu_hdr+4, 1);
Harald Welte9d3e3822015-11-09 00:50:54 +0100232 /* but then after the final byte of the TPDU header, we want a
233 * receive context to be available for USB transmission */
Harald Welte8e7fca32017-05-07 16:14:33 +0200234 get_and_verify_rctx(PHONE_DATAIN, tpdu_hdr, 5);
Harald Welteb4362862015-11-14 19:02:33 +0100235}
236
Harald Welte25a9a802017-05-08 13:30:09 +0200237/* emulate a SIMTRACE_MSGT_DT_CEMU_TX_DATA received from USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200238static void host_to_device_data(struct card_handle *ch, const uint8_t *data, uint16_t len,
239 unsigned int flags)
Harald Welteb4362862015-11-14 19:02:33 +0100240{
Harald Welte8e7fca32017-05-07 16:14:33 +0200241 struct msgb *msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200242 struct simtrace_msg_hdr *mh;
Harald Welte84ec2522015-11-14 23:03:50 +0100243 struct cardemu_usb_msg_tx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200244 struct llist_head *queue;
Harald Welteb4362862015-11-14 19:02:33 +0100245
246 /* allocate a free req_ctx */
Harald Welte8e7fca32017-05-07 16:14:33 +0200247 msg = usb_buf_alloc(PHONE_DATAOUT);
248 assert(msg);
Harald Welte25a9a802017-05-08 13:30:09 +0200249 /* initialize the common header */
Harald Welte8e7fca32017-05-07 16:14:33 +0200250 msg->l1h = msg->head;
Harald Welte25a9a802017-05-08 13:30:09 +0200251 mh = (struct simtrace_msg_hdr *) msgb_put(msg, sizeof(*mh));
252 mh->msg_class = SIMTRACE_MSGC_CARDEM;
253 mh->msg_type = SIMTRACE_MSGT_DT_CEMU_TX_DATA;
Harald Welteb4362862015-11-14 19:02:33 +0100254
Harald Welte25a9a802017-05-08 13:30:09 +0200255 /* initialize the tx_data message */
256 msg->l2h = msgb_put(msg, sizeof(*rd) + len);
257 rd = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welteeef6c2a2016-02-24 22:19:03 +0100258 rd->flags = flags;
Harald Welteb4362862015-11-14 19:02:33 +0100259 /* copy data and set length */
Harald Welted295b922016-03-18 21:01:36 +0100260 rd->data_len = len;
Harald Welteb4362862015-11-14 19:02:33 +0100261 memcpy(rd->data, data, len);
Harald Welte25a9a802017-05-08 13:30:09 +0200262
263 mh->msg_len = sizeof(*mh) + sizeof(*rd) + len;
Harald Welteb4362862015-11-14 19:02:33 +0100264
265 /* hand the req_ctx to the UART transmit code */
Harald Welte8e7fca32017-05-07 16:14:33 +0200266 queue = card_emu_get_uart_tx_queue(ch);
267 assert(queue);
268 msgb_enqueue(queue, msg);
Harald Welteb4362862015-11-14 19:02:33 +0100269}
270
Harald Welteeef6c2a2016-02-24 22:19:03 +0100271/* card-transmit any pending characters */
Harald Welte86d047b2016-02-25 00:26:17 +0100272static int card_tx_verify_chars(struct card_handle *ch, const uint8_t *data, unsigned int data_len)
Harald Welteb4362862015-11-14 19:02:33 +0100273{
Harald Welteb4362862015-11-14 19:02:33 +0100274 int count = 0;
275
Harald Welte6bf8c122016-02-24 21:04:08 +0100276 while (card_emu_tx_byte(ch)) {
Harald Welteb4362862015-11-14 19:02:33 +0100277 count++;
278 }
Harald Welte86d047b2016-02-25 00:26:17 +0100279
280 assert(count == data_len);
281 reader_check_and_clear(data, data_len);
282
Harald Welteb4362862015-11-14 19:02:33 +0100283 return count;
Harald Welte9d3e3822015-11-09 00:50:54 +0100284}
285
Harald Welte84ec2522015-11-14 23:03:50 +0100286const uint8_t tpdu_hdr_sel_mf[] = { 0xA0, 0xA4, 0x00, 0x00, 0x00 };
Harald Welte61bb30e2015-11-14 23:44:14 +0100287const uint8_t tpdu_pb_sw[] = { 0x90, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +0100288
Harald Weltec043e642016-02-24 23:26:55 +0100289static void
290test_tpdu_reader2card(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
291{
Harald Weltec043e642016-02-24 23:26:55 +0100292 printf("\n==> transmitting APDU (HDR + PB + card-RX)\n");
293
294 /* emulate the reader sending a TPDU header */
295 rdr_send_tpdu_hdr(ch, hdr);
296 /* we shouldn't have any pending card-TX yet */
Harald Welte86d047b2016-02-25 00:26:17 +0100297 card_tx_verify_chars(ch, NULL, 0);
Harald Welte0ab6fcd2016-02-25 00:08:22 +0100298
Harald Weltec043e642016-02-24 23:26:55 +0100299 /* card emulator PC sends a singly byte PB response via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200300 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 +0100301 /* card actually sends that single PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100302 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100303
304 /* emulate more characters from reader to card */
305 reader_send_bytes(ch, body, body_len);
306
307 /* check if we have received them on the USB side */
Harald Welte8e7fca32017-05-07 16:14:33 +0200308 get_and_verify_rctx(PHONE_DATAIN, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100309
310 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200311 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100312
313 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200314 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw),
Harald Weltec043e642016-02-24 23:26:55 +0100315 CEMU_DATA_F_FINAL | CEMU_DATA_F_PB_AND_TX);
316 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100317 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100318
319 /* simulate some clock stop */
320 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
321 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
322}
323
324static void
325test_tpdu_card2reader(struct card_handle *ch, const uint8_t *hdr, const uint8_t *body, uint8_t body_len)
326{
327 printf("\n==> transmitting APDU (HDR + PB + card-TX)\n");
328
329 /* emulate the reader sending a TPDU header */
330 rdr_send_tpdu_hdr(ch, hdr);
Harald Welte86d047b2016-02-25 00:26:17 +0100331 card_tx_verify_chars(ch, NULL, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100332
333 /* card emulator PC sends a response PB via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200334 host_to_device_data(ch, hdr+1, 1, CEMU_DATA_F_PB_AND_TX);
Harald Weltec043e642016-02-24 23:26:55 +0100335
336 /* card actually sends that PB */
Harald Welte86d047b2016-02-25 00:26:17 +0100337 card_tx_verify_chars(ch, hdr+1, 1);
Harald Weltec043e642016-02-24 23:26:55 +0100338
339 /* emulate more characters from card to reader */
Harald Welte8e7fca32017-05-07 16:14:33 +0200340 host_to_device_data(ch, body, body_len, 0);
Harald Weltec043e642016-02-24 23:26:55 +0100341 /* obtain those bytes as they arrvive on the card */
Harald Welte86d047b2016-02-25 00:26:17 +0100342 card_tx_verify_chars(ch, body, body_len);
Harald Weltec043e642016-02-24 23:26:55 +0100343
344 /* ensure there is no extra data received on usb */
Harald Welte8e7fca32017-05-07 16:14:33 +0200345 assert(llist_empty(usb_get_queue(PHONE_DATAOUT)));
Harald Weltec043e642016-02-24 23:26:55 +0100346
347 /* card emulator sends SW via USB */
Harald Welte8e7fca32017-05-07 16:14:33 +0200348 host_to_device_data(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw), CEMU_DATA_F_FINAL);
Harald Weltec043e642016-02-24 23:26:55 +0100349
350 /* obtain any pending tx chars */
Harald Welte86d047b2016-02-25 00:26:17 +0100351 card_tx_verify_chars(ch, tpdu_pb_sw, sizeof(tpdu_pb_sw));
Harald Weltec043e642016-02-24 23:26:55 +0100352
353 /* simulate some clock stop */
354 card_emu_io_statechg(ch, CARD_IO_CLK, 0);
355 card_emu_io_statechg(ch, CARD_IO_CLK, 1);
356}
357
Harald Welte4ba66d02016-02-25 19:38:56 +0100358const uint8_t pps[] = {
359 /* PPSS identifies the PPS request or response and is set to
360 * 'FF'. */
361 0xFF, // PPSS
362 /* In PPS0, each bit 5, 6 or 7 set to 1 indicates the presence
363 * of an optional byte PPS 1 , PPS 2 , PPS 3 ,
364 * respectively. Bits 4 to 1 encode a type T to propose a
365 * transmission protocol. Bit 8 is reserved for future
366 * use and shall be set to 0. */
367 0b00010000, // PPS0: PPS1 present
368 0x00, // PPS1 proposed Fi/Di value
369 0xFF ^ 0b00010000// PCK
370};
371
372static void
373test_ppss(struct card_handle *ch)
374{
375 reader_send_bytes(ch, pps, sizeof(pps));
376 get_and_verify_rctx_pps(pps, sizeof(pps));
377 card_tx_verify_chars(ch, pps, sizeof(pps));
378}
Harald Weltec043e642016-02-24 23:26:55 +0100379
Harald Welteeef6c2a2016-02-24 22:19:03 +0100380/* READ RECORD (offset 0, 10 bytes) */
381const uint8_t tpdu_hdr_read_rec[] = { 0xA0, 0xB2, 0x00, 0x00, 0x0A };
382const uint8_t tpdu_body_read_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
383
384/* WRITE RECORD */
385const uint8_t tpdu_hdr_write_rec[] = { 0xA0, 0xD2, 0x00, 0x00, 0x07 };
386const uint8_t tpdu_body_write_rec[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
Harald Welte84ec2522015-11-14 23:03:50 +0100387
Harald Welte9d3e3822015-11-09 00:50:54 +0100388int main(int argc, char **argv)
389{
390 struct card_handle *ch;
Harald Welte84ec2522015-11-14 23:03:50 +0100391 unsigned int i;
Harald Welte9d3e3822015-11-09 00:50:54 +0100392
Harald Welte8e7fca32017-05-07 16:14:33 +0200393 ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT);
Harald Welte9d3e3822015-11-09 00:50:54 +0100394 assert(ch);
395
Harald Welte8e7fca32017-05-07 16:14:33 +0200396 usb_buf_init();
397
Harald Welteb4362862015-11-14 19:02:33 +0100398 /* start up the card (VCC/RST, ATR) */
Harald Welte9d3e3822015-11-09 00:50:54 +0100399 io_start_card(ch);
Harald Welte86d047b2016-02-25 00:26:17 +0100400 card_tx_verify_chars(ch, NULL, 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100401
Harald Welte4ba66d02016-02-25 19:38:56 +0100402 test_ppss(ch);
403
Harald Welte84ec2522015-11-14 23:03:50 +0100404 for (i = 0; i < 2; i++) {
Harald Weltec043e642016-02-24 23:26:55 +0100405 test_tpdu_reader2card(ch, tpdu_hdr_write_rec, tpdu_body_write_rec, sizeof(tpdu_body_write_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100406
Harald Weltec043e642016-02-24 23:26:55 +0100407 test_tpdu_card2reader(ch, tpdu_hdr_read_rec, tpdu_body_read_rec, sizeof(tpdu_body_read_rec));
Harald Welte84ec2522015-11-14 23:03:50 +0100408 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100409
410 exit(0);
411}