blob: f7423cdf493a206c1bec10bdcb67ecef638abd26 [file] [log] [blame]
Harald Weltef30e22b2019-11-14 08:36:19 +01001module CCID_Tests {
2
Harald Welte1d9986a2019-11-28 14:47:22 +01003/* TTCN-3 tests for USB CCID (Chip Card Interface Device)
4 *
5 * (C) 2018-2019 by Harald Welte <laforge@gnumonks.org>
6 */
7
Harald Weltef30e22b2019-11-14 08:36:19 +01008import from General_Types all;
9import from Osmocom_Types all;
10import from Misc_Helpers all;
11
12import from USB_PortType all;
Harald Welte1d9986a2019-11-28 14:47:22 +010013import from USB_Component all;
Harald Weltef30e22b2019-11-14 08:36:19 +010014
15import from CCID_Types all;
16import from CCID_Templates all;
17import from CCID_Emulation all;
18
Harald Welte1d9986a2019-11-28 14:47:22 +010019modulepar {
Harald Welte94528c72020-07-30 22:11:08 +020020 USB_Device_Match mp_usb_dev_match := { vid_pid := { vid := '1d50'H, pid := '6141'H } };
Harald Welte1d9986a2019-11-28 14:47:22 +010021 integer mp_use_slot_count := 8;
22 boolean mp_test_power_off := true;
23 boolean mp_quirk_resetpar_returns_slotsts := false;
24}
Harald Weltef30e22b2019-11-14 08:36:19 +010025/* global test component; manages CCID device */
26type component Test_CT {
27 var CCID_Emulation_CT vc_CCID;
28 port USB_PT USB;
29 var Slot_CT vc_SLOT[NR_SLOTS];
30};
31
32/* per-slot test component; manages one slot */
33type component Slot_CT {
34 var uint8_t g_slot_nr;
35 port CCID_SLOT_PT CCID;
Harald Welteea8db4c2019-11-25 22:12:42 +010036 timer g_Tguard := 120.0;
Harald Weltef30e22b2019-11-14 08:36:19 +010037};
38
Harald Welte1d9986a2019-11-28 14:47:22 +010039/* maximum number of slots we are supporting in the test suite */
40private const integer NR_SLOTS := 16;
Harald Weltef30e22b2019-11-14 08:36:19 +010041
42/***********************************************************************
43 * helper infrastructure
44 ***********************************************************************/
45
Harald Welte1d9986a2019-11-28 14:47:22 +010046const octetstring c_UICC_SELECT_MF := '00a40004023f00'O;
47const octetstring c_SIM_SELECT_MF := 'a0a40004023f00'O;
48
Eric Wild7f5cfd42019-11-22 17:45:40 +010049/* Table 7 of ISO7816-3 */
50type enumerated ISO7816_Fi {
51 ISO7816_FI_372_4MHz ('0000'B),
52 ISO7816_FI_372_5MHz ('0001'B),
53 ISO7816_FI_558_6MHz ('0010'B),
54 ISO7816_FI_744_8MHz ('0011'B),
55 ISO7816_FI_1116_12MHz ('0100'B),
56 ISO7816_FI_1488_16MHz ('0101'B),
57 ISO7816_FI_1860_20MHz ('0110'B),
58
59 ISO7816_FI_512_5MHz ('1001'B),
60 ISO7816_FI_768_7MHz ('1010'B),
61 ISO7816_FI_1024_10MHz ('1011'B),
62 ISO7816_FI_1536_15MHz ('1100'B),
63 ISO7816_FI_2048_20MHz ('1101'B)
64};
65
66/* Table 8 of ISO7816-3 */
67type enumerated ISO7816_Di {
68 ISO7816_DI_1 ('0001'B),
69 ISO7816_DI_2 ('0010'B),
70 ISO7816_DI_4 ('0011'B),
71 ISO7816_DI_8 ('0100'B),
72 ISO7816_DI_16 ('0101'B),
73 ISO7816_DI_32 ('0110'B),
74 ISO7816_DI_64 ('0111'B),
75
76 ISO7816_DI_12 ('1000'B),
77 ISO7816_DI_20 ('1001'B)
78}
79
80private template (value) CCID_ProtocolData ts_ProtoDataT0(ISO7816_Fi fi, ISO7816_Di di,
81 uint8_t guard_time := 0,
82 uint8_t wait_int := 0) := {
83 T0 := {
84 Findex := enum2int(fi),
85 Dindex := enum2int(di),
86
87 bRFU := '000000'B,
88 inv_convention := false,
89 bRFU2 := '0'B,
90
91 bGuardTimeT0 := guard_time,
92 bWaitingIntegerT0 := wait_int,
93 bClockStop := STOPPING_NOT_ALLOWED
94 }
95};
96
Harald Weltef30e22b2019-11-14 08:36:19 +010097type function void_fn() runs on Slot_CT;
98
99/* altstep running on the per-slot test component */
100private altstep as_Tguard() runs on Slot_CT {
101 [] g_Tguard.timeout {
102 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
103 }
104}
105
Harald Welte1d9986a2019-11-28 14:47:22 +0100106private altstep as_ccid_any() runs on Slot_CT {
107 var CCID_PDU pdu;
108 [] CCID.receive(CCID_PDU:?) -> value pdu {
109 setverdict(fail, "Received unexpected CCID ", pdu);
110 self.stop;
111 }
112 [] CCID.receive {
113 setverdict(fail, "Received unexpected non-CCID");
114 self.stop;
115 }
116}
117
Harald Weltef30e22b2019-11-14 08:36:19 +0100118/* first function inside Slot_CT; wait for CCID_EVENT_UP + call testcase-specific function */
119private function f_handler_init(void_fn fn, integer slot_nr) runs on Slot_CT {
120 g_slot_nr := slot_nr;
121 CCID.receive(CCID_Emulation_Event:{up_down:=CCID_EVENT_UP});
122 g_Tguard.start;
123 activate(as_Tguard());
124
125 fn.apply();
126}
127
128/* start a single slot handler */
129private function f_start_handler(void_fn fn, integer slot_nr) runs on Test_CT
130{
131 var Slot_CT vc;
132
133 vc_SLOT[slot_nr] := Slot_CT.create("Slot" & int2str(slot_nr));
134 connect(vc_SLOT[slot_nr]:CCID, vc_CCID:SLOT[slot_nr]);
135 vc_SLOT[slot_nr].start(f_handler_init(fn, slot_nr));
136}
137
138private function f_wait_handlers_complete() runs on Test_CT {
139 var integer i;
140
141 for (i := 0; i < NR_SLOTS; i := i+1) {
142 if (vc_SLOT[i] != null) {
143 vc_SLOT[i].done;
144 }
145 }
146 setverdict(pass);
147}
148
149private function f_start_and_wait() runs on Test_CT {
150 /* start CCID_Emulation last, it will trigger all the per-slot components */
Harald Welte1d9986a2019-11-28 14:47:22 +0100151 var CCID_Emulation_Params cep := { usb_dev_match := mp_usb_dev_match };
152 vc_CCID.start(CCID_Emulation.main(cep));
Harald Weltef30e22b2019-11-14 08:36:19 +0100153 f_wait_handlers_complete();
154}
155
156private function f_init() runs on Test_CT {
157 var integer i;
158 vc_CCID := CCID_Emulation_CT.create("CCID");
159 map(vc_CCID:USB, system:USB);
160 for (i := 0; i < NR_SLOTS; i := i+1) {
161 vc_SLOT[i] := null;
162 }
163}
164
Harald Weltef30e22b2019-11-14 08:36:19 +0100165
Harald Welte1d9986a2019-11-28 14:47:22 +0100166/* transceive a CCID command (send 'tx' on OUT; expect 'rx' on IN) */
167private function f_ccid_xceive(template (value) CCID_PDU tx, template (present) CCID_PDU exp_rx)
168runs on Slot_CT return CCID_PDU {
Harald Weltef30e22b2019-11-14 08:36:19 +0100169 var CCID_PDU pdu;
170
Harald Welte1d9986a2019-11-28 14:47:22 +0100171 tx.hdr.bSlot := g_slot_nr;
172 exp_rx.hdr.bSlot := g_slot_nr;
173
174 CCID.send(tx);
Harald Weltef30e22b2019-11-14 08:36:19 +0100175 alt {
Harald Welte1d9986a2019-11-28 14:47:22 +0100176 [] CCID.receive(exp_rx) -> value pdu {
177 return pdu;
Harald Weltef30e22b2019-11-14 08:36:19 +0100178 }
Harald Welte1d9986a2019-11-28 14:47:22 +0100179 [] as_ccid_any();
Harald Weltef30e22b2019-11-14 08:36:19 +0100180 }
Harald Welte1d9986a2019-11-28 14:47:22 +0100181 return pdu;
182}
183
184private template (present) CCID_Header_IN tr_inact :=
185 tr_CCID_HeaderIN_OK(icc_status := (CCID_ICC_STATUS_PRES_INACT, CCID_ICC_STATUS_NO_ICC));
186
187private template (present) CCID_Header_IN tr_act :=
188 tr_CCID_HeaderIN_OK(icc_status := CCID_ICC_STATUS_PRES_ACT);
189
190/* Send IccPowerOn on OUT; expect DataBlock in retunr */
191private function f_ccid_power_on(CCID_PowerSelect psel := CCID_PWRSEL_AUTO,
192 template (present) CCID_Header_IN hdr_in := tr_act)
193runs on Slot_CT return CCID_PDU {
194 var CCID_PDU pdu;
195
196 pdu := f_ccid_xceive(ts_CCID_IccPowerOn(g_slot_nr, psel),
197 tr_CCID_DataBlock(g_slot_nr, hdr_in := hdr_in) );
198 return pdu;
199}
200
201/* Send IccPowerOn on OUT; expect SlotStatus in return */
202private function f_ccid_power_off(template (present) CCID_Header_IN hdr_in := tr_inact)
203runs on Slot_CT return CCID_PDU {
204 var CCID_PDU pdu;
205
206 pdu := f_ccid_xceive(ts_CCID_IccPowerOff(g_slot_nr),
207 tr_CCID_SlotStatus(slot := g_slot_nr, hdr_in := hdr_in) );
208 return pdu;
209}
210
211/* Send IccClockCommand on OUT; expect SlotStatus in return */
212private function f_ccid_clock_cmd(CCID_ClockCommand cmd,
213 template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
214runs on Slot_CT return CCID_PDU {
215 var CCID_PDU pdu;
216
217 pdu := f_ccid_xceive(ts_CCID_ClockCommand(g_slot_nr, cmd),
218 tr_CCID_SlotStatus(slot := g_slot_nr, hdr_in := hdr_in));
219 return pdu;
220}
221
222/* Send XfrBlock on OUT; expect DataBlock in return */
223private function f_ccid_xfr(octetstring tx, template octetstring rx) runs on Slot_CT return octetstring {
224 var CCID_PDU pdu;
225
226 pdu := f_ccid_xceive(ts_CCID_XfrBlock(g_slot_nr, tx, 0),
227 tr_CCID_DataBlock(g_slot_nr, ?, ?, rx) );
228 return pdu.u.DataBlock.abData;
229}
230
231/* Send SetParameters on OUT; expect Parameters on IN */
232private function f_ccid_set_par(template (value) CCID_ProtocolData par,
233 template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
234runs on Slot_CT return CCID_PDU {
235 var CCID_PDU pdu;
236
237 pdu := f_ccid_xceive(ts_CCID_SetParameters(g_slot_nr, par),
238 tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
239 return pdu;
240}
241
242/* Send GetParameters on OUT; expect Parameters on IN */
243private function f_ccid_get_par(template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
244runs on Slot_CT return CCID_PDU {
245 var CCID_PDU pdu;
246
247 pdu := f_ccid_xceive(ts_CCID_GetParameters(g_slot_nr),
248 tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
249 return pdu;
250}
251
252/* Send ResetParameters on OUT; expect Parameters on IN */
253private function f_ccid_reset_par(template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
254runs on Slot_CT return CCID_PDU {
255 var CCID_PDU pdu;
256
257 /* [at least] Omnikey seems to have failed to follow the CCID spec here :/ */
258 if (mp_quirk_resetpar_returns_slotsts) {
259 pdu := f_ccid_xceive(ts_CCID_ResetParameters(g_slot_nr),
260 tr_CCID_SlotStatus(g_slot_nr, hdr_in := hdr_in));
261 } else {
262 pdu := f_ccid_xceive(ts_CCID_ResetParameters(g_slot_nr),
263 tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
264 }
265 return pdu;
266}
267
268/* Send Escape on OUT; expect Escape on IN */
269private function f_ccid_escape(template (value) octetstring data,
270 template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
271runs on Slot_CT return CCID_PDU {
272 var CCID_PDU pdu;
273
274 pdu := f_ccid_xceive(ts_CCID_Escape(g_slot_nr, data),
275 tr_CCID_EscapeIN(g_slot_nr, hdr_in := hdr_in));
276 return pdu;
Harald Weltef30e22b2019-11-14 08:36:19 +0100277}
278
279
280/***********************************************************************
Harald Welte1d9986a2019-11-28 14:47:22 +0100281 * Test behavior regarding valid situations
Harald Weltef30e22b2019-11-14 08:36:19 +0100282 ***********************************************************************/
283
Harald Weltef30e22b2019-11-14 08:36:19 +0100284/* request 100 times the slot status */
285private function f_TC_getstatus() runs on Slot_CT
286{
287 var integer i;
288 for (i := 0; i < 100; i := i+1) {
289 CCID.send(ts_CCID_GetSlotStatus(g_slot_nr));
290 /* it would be fun to simply send more requests here, but the CCID
291 * spec doesn't permit more than one unresponded command [per slot] */
292 alt {
293 [] CCID.receive(tr_CCID_SlotStatus(g_slot_nr));
Harald Welte1d9986a2019-11-28 14:47:22 +0100294 [] as_ccid_any();
Harald Weltef30e22b2019-11-14 08:36:19 +0100295 }
296 }
297 setverdict(pass);
298}
299testcase TC_get_status() runs on Test_CT
300{
301 var integer i;
302
303 f_init();
304
Harald Welte1d9986a2019-11-28 14:47:22 +0100305 for (i := 0; i < mp_use_slot_count; i := i+1) {
Harald Weltef30e22b2019-11-14 08:36:19 +0100306 f_start_handler(refers(f_TC_getstatus), i);
307 }
308
309 f_start_and_wait();
310}
311
312
313private function f_TC_power_on() runs on Slot_CT
314{
Harald Welte1d9986a2019-11-28 14:47:22 +0100315 f_ccid_power_on();
Harald Weltef30e22b2019-11-14 08:36:19 +0100316}
317testcase TC_power_on() runs on Test_CT
318{
319 var integer i;
320
321 f_init();
322
Harald Welte1d9986a2019-11-28 14:47:22 +0100323 for (i := 0; i < mp_use_slot_count; i := i+1) {
Harald Weltef30e22b2019-11-14 08:36:19 +0100324 f_start_handler(refers(f_TC_power_on), i);
325 }
326
327 f_start_and_wait();
328}
329
Harald Welte1d9986a2019-11-28 14:47:22 +0100330private function f_TC_power_off() runs on Slot_CT
331{
332 f_ccid_power_on();
333 f_ccid_power_off();
334}
335testcase TC_power_off() runs on Test_CT
336{
337 var integer i;
338
339 f_init();
340
341 for (i := 0; i < mp_use_slot_count; i := i+1) {
342 f_start_handler(refers(f_TC_power_off), i);
343 }
344
345 f_start_and_wait();
346}
347
348
349/* repeat IccPowerOn on slot that's already active (next warm reset ATR) */
350private function f_TC_power_on_warm() runs on Slot_CT
351{
352 var integer i;
353
354 /* initial power on */
355 f_ccid_power_on();
356
357 /* additional power on */
358 for (i := 0; i < 20; i := i+1) {
359 f_ccid_power_on();
360 }
361}
362testcase TC_power_on_warm() runs on Test_CT
363{
364 var integer i;
365
366 f_init();
367
368 for (i := 0; i < mp_use_slot_count; i := i+1) {
369 f_start_handler(refers(f_TC_power_on_warm), i);
370 }
371
372 f_start_and_wait();
373}
374
375/* transfer 1000 APDUs by issuing SELECT MF */
Harald Weltef30e22b2019-11-14 08:36:19 +0100376private function f_TC_select_mf() runs on Slot_CT
377{
378 var integer i;
Harald Welte1d9986a2019-11-28 14:47:22 +0100379 f_ccid_power_on();
Eric Wild7f5cfd42019-11-22 17:45:40 +0100380 f_ccid_set_par(ts_ProtoDataT0(ISO7816_FI_512_5MHz, ISO7816_DI_32));
Harald Welte1d9986a2019-11-28 14:47:22 +0100381 for (i := 0; i < 1000; i := i+1) {
Harald Weltec6fde3f2020-07-30 22:09:55 +0200382 f_ccid_xfr(c_UICC_SELECT_MF, '??'O);
Harald Weltef30e22b2019-11-14 08:36:19 +0100383 }
384}
385testcase TC_select_mf() runs on Test_CT
386{
387 var integer i;
388
389 f_init();
390
Harald Welte1d9986a2019-11-28 14:47:22 +0100391 for (i := 0; i < mp_use_slot_count; i := i+1) {
Harald Weltef30e22b2019-11-14 08:36:19 +0100392 f_start_handler(refers(f_TC_select_mf), i);
393 }
394
395 f_start_and_wait();
396}
397
Harald Welte1d9986a2019-11-28 14:47:22 +0100398/* GetParametrs: verify contents */
399private function f_TC_get_params() runs on Slot_CT
400{
401 var CCID_PDU par;
402 f_ccid_power_on();
403 par := f_ccid_get_par();
404 log(par);
405}
406testcase TC_get_params() runs on Test_CT
407{
408 var integer i;
409
410 f_init();
411
412 for (i := 0; i < mp_use_slot_count; i := i+1) {
413 f_start_handler(refers(f_TC_get_params), i);
414 }
415 f_start_and_wait();
416}
417
418/* SetParameters: verify change */
419private function f_TC_set_params() runs on Slot_CT
420{
421 var CCID_PDU par;
422 f_ccid_power_on();
423
424 /* get current parameters */
425 par := f_ccid_get_par();
426
427 /* modify some of them */
428 var CCID_ProtocolData pd := par.u.Parameters.abProtocolData;
429 pd.T0.bGuardTimeT0 := 23;
430 pd.T0.bWaitingIntegerT0 := 42;
431 par := f_ccid_set_par(pd);
432
433 /* check if modifications were applied */
434 var template (present) CCID_ProtocolData tr_PD := {
435 T0 := {
436 Findex := ?,
437 Dindex := ?,
438 bRFU := ?,
439 inv_convention := ?,
440 bRFU2 := ?,
441 bGuardTimeT0 := 23,
442 bWaitingIntegerT0 := 42,
443 bClockStop := ?
444 }
445 };
446 if (match(par.u.Parameters.abProtocolData, tr_PD)) {
447 setverdict(pass);
448 } else {
449 setverdict(fail, "SetParameters didn't change GuardTime/WaitingInteger");
450 }
451}
452testcase TC_set_params() runs on Test_CT
453{
454 var integer i;
455
456 f_init();
457
458 for (i := 0; i < mp_use_slot_count; i := i+1) {
459 f_start_handler(refers(f_TC_set_params), i);
460 }
461 f_start_and_wait();
462}
463
464/* ResetParameters: verify change */
465private function f_TC_reset_params() runs on Slot_CT
466{
467 var CCID_PDU par;
468
469 f_TC_set_params();
470 par := f_ccid_reset_par();
471 if (mp_quirk_resetpar_returns_slotsts) {
472 par := f_ccid_get_par();
473 }
474 if (par.u.Parameters.abProtocolData.T0.bGuardTimeT0 == 23 or
475 par.u.Parameters.abProtocolData.T0.bWaitingIntegerT0 == 42) {
476 setverdict(fail, "ResetParameters didn't reset properly");
477 }
478}
479testcase TC_reset_params() runs on Test_CT
480{
481 var integer i;
482
483 f_init();
484
485 for (i := 0; i < mp_use_slot_count; i := i+1) {
486 f_start_handler(refers(f_TC_reset_params), i);
487 }
488 f_start_and_wait();
489}
490
491
492
493/* TODO */
494/* IccPowerOn: verify that CCID resets all parameters to default values */
495/* IccPowerOn: verify that bPowerSelect has no effect in active state */
496/* XfrBlock: length corner cases (Lc/Le max, ...) */
497/* IccClock: verify clock has stopped/restarted */
498/* Abort for command that already terminated */
499/* Abort for command that's still processing */
500
501
502/***********************************************************************
503 * Test behavior regarding invalid situations
504 ***********************************************************************/
505
506/* message for invalid slot number (more than we have) */
507private function f_TC_inval_slot() runs on Slot_CT {
508 CCID.send(ts_CCID_GetSlotStatus(g_slot_nr));
509 alt {
510 [] CCID.receive(tr_CCID_SlotStatus(hdr_in := tr_CCID_HeaderIN_FAIL(CCID_ERR_SLOT_NOT_EXIST))) {
511 setverdict(pass);
512 }
513 [] CCID.receive(tr_CCID_SlotStatus) {
514 setverdict(fail, "Unexpected SlotStatus");
515 mtc.stop;
516 }
517 [] as_ccid_any();
518 }
519}
520testcase TC_inval_slot() runs on Test_CT {
521 f_init();
522 f_start_handler(refers(f_TC_inval_slot), 15);
523 f_start_and_wait();
524}
525
526/* switch card off and then XfrBlock. Requires reader with IccPowerOff support */
527private function f_TC_xfer_off() runs on Slot_CT {
528 f_ccid_power_off();
529 CCID.send(ts_CCID_XfrBlock(g_slot_nr, c_SIM_SELECT_MF, 0));
530 alt {
531 [] CCID.receive(tr_CCID_DataBlock(slot:=g_slot_nr, hdr_in:=tr_CCID_HeaderIN_FAIL)) {
532 setverdict(pass);
533 }
534 [] CCID.receive(tr_CCID_DataBlock(slot:=g_slot_nr, hdr_in:=tr_CCID_HeaderIN_OK)) {
535 setverdict(fail, "Expected XfrBlock to fail");
536 mtc.stop;
537 }
538 [] as_ccid_any();
539 }
540}
541testcase TC_xfer_off() runs on Test_CT {
542 f_init();
543 f_start_handler(refers(f_TC_xfer_off), 0);
544 f_start_and_wait();
545}
546
547
548/* unsupported Mechanical */
549private function f_TC_unsupp_mechanical() runs on Slot_CT {
550 CCID.send(ts_CCID_Mechanical(g_slot_nr, CCID_MECH_FN_EJECT_CARD));
551 alt {
552 [] CCID.receive(tr_CCID_SlotStatus(hdr_in := tr_CCID_HeaderIN_FAIL(CCID_ERR_CMD_NOT_SUPPORTED))) {
553 setverdict(pass);
554 }
555 [] as_ccid_any();
556 }
557}
558testcase TC_unsupp_mechanical() runs on Test_CT {
559 f_init();
560 f_start_handler(refers(f_TC_unsupp_mechanical), 0);
561 f_start_and_wait();
562}
563
564/* unsupported Secure */
565private function f_TC_unsupp_secure() runs on Slot_CT {
566 CCID.send(ts_CCID_Secure(g_slot_nr, 0, 0, ''O));
567 alt {
568 [] CCID.receive(tr_CCID_DataBlock(hdr_in := tr_CCID_HeaderIN_FAIL(CCID_ERR_CMD_NOT_SUPPORTED))) {
569 setverdict(pass);
570 }
571 [] as_ccid_any();
572 }
573}
574testcase TC_unsupp_secure() runs on Test_CT {
575 f_init();
576 f_start_handler(refers(f_TC_unsupp_secure), 0);
577 f_start_and_wait();
578}
579
580
581/* TODO */
582/* truncated message */
583/* IccPowerOn with wrong voltage (> 0x04) */
584/* XfrBlock on empty slot */
585/* GetParameters on empty slot */
586/* SetParameters for bProtocolNum > 0x01 */
587/* SetParameters: invalid parameters */
588/* set unsupported frequency */
589/* set unsupported clock rate */
590/* XfrBlock: bWI in T=0? */
591/* XfrBlock: wLevelParameter not matching level? */
592/* Abort for command that was not even submitted yet*/
593/* dwMaxCCIDMessageLength */
Harald Weltef30e22b2019-11-14 08:36:19 +0100594
595
596control {
Harald Welte1d9986a2019-11-28 14:47:22 +0100597 /* valid transactions */
Harald Weltef30e22b2019-11-14 08:36:19 +0100598 execute( TC_get_status() );
599 execute( TC_power_on() );
Harald Welte1d9986a2019-11-28 14:47:22 +0100600 execute( TC_power_on_warm() );
601 if (mp_test_power_off) {
602 execute( TC_power_off() );
603 }
Harald Weltef30e22b2019-11-14 08:36:19 +0100604 execute( TC_select_mf() );
Harald Welte1d9986a2019-11-28 14:47:22 +0100605 execute( TC_get_params() );
606 execute( TC_set_params() );
607 execute( TC_reset_params() );
608
609 /* error handling */
610 execute( TC_inval_slot() );
611 if (mp_test_power_off) {
612 execute( TC_xfer_off() );
613 }
614 execute( TC_unsupp_mechanical() );
615 execute( TC_unsupp_secure() );
Harald Weltef30e22b2019-11-14 08:36:19 +0100616}
617
618
619
620
621}