1*a61ed2ceSHans Rosenfeld /*
2*a61ed2ceSHans Rosenfeld  * This file and its contents are supplied under the terms of the
3*a61ed2ceSHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
4*a61ed2ceSHans Rosenfeld  * You may only use this file in accordance with the terms of version
5*a61ed2ceSHans Rosenfeld  * 1.0 of the CDDL.
6*a61ed2ceSHans Rosenfeld  *
7*a61ed2ceSHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
8*a61ed2ceSHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
9*a61ed2ceSHans Rosenfeld  * http://www.illumos.org/license/CDDL.
10*a61ed2ceSHans Rosenfeld  */
11*a61ed2ceSHans Rosenfeld 
12*a61ed2ceSHans Rosenfeld /*
13*a61ed2ceSHans Rosenfeld  * Copyright 2019, Joyent, Inc.
14*a61ed2ceSHans Rosenfeld  */
15*a61ed2ceSHans Rosenfeld 
16*a61ed2ceSHans Rosenfeld /*
17*a61ed2ceSHans Rosenfeld  * Verify that we can parse various forms of ATR data and detect invalid data.
18*a61ed2ceSHans Rosenfeld  */
19*a61ed2ceSHans Rosenfeld 
20*a61ed2ceSHans Rosenfeld #include <err.h>
21*a61ed2ceSHans Rosenfeld #include <stdlib.h>
22*a61ed2ceSHans Rosenfeld 
23*a61ed2ceSHans Rosenfeld #include <atr.h>
24*a61ed2ceSHans Rosenfeld 
25*a61ed2ceSHans Rosenfeld typedef struct atr_vals {
26*a61ed2ceSHans Rosenfeld } atr_vals_t;
27*a61ed2ceSHans Rosenfeld 
28*a61ed2ceSHans Rosenfeld typedef struct atr_test {
29*a61ed2ceSHans Rosenfeld 	const char *ar_test;
30*a61ed2ceSHans Rosenfeld 	uint8_t ar_len;
31*a61ed2ceSHans Rosenfeld 	uint8_t ar_buf[64];
32*a61ed2ceSHans Rosenfeld 	atr_parsecode_t ar_retval;
33*a61ed2ceSHans Rosenfeld 	/* Everything after this is data from the ATR */
34*a61ed2ceSHans Rosenfeld 	atr_protocol_t ar_sup;
35*a61ed2ceSHans Rosenfeld 	atr_protocol_t ar_def;
36*a61ed2ceSHans Rosenfeld 	boolean_t ar_neg;
37*a61ed2ceSHans Rosenfeld 	uint8_t ar_fi;
38*a61ed2ceSHans Rosenfeld 	uint8_t ar_di;
39*a61ed2ceSHans Rosenfeld 	atr_convention_t ar_conv;
40*a61ed2ceSHans Rosenfeld 	uint8_t ar_guard;
41*a61ed2ceSHans Rosenfeld 	atr_clock_stop_t ar_stop;
42*a61ed2ceSHans Rosenfeld 	/* These will be checked based on sup prot */
43*a61ed2ceSHans Rosenfeld 	uint8_t ar_t0_wi;
44*a61ed2ceSHans Rosenfeld 	atr_t1_checksum_t  ar_t1_cksum;
45*a61ed2ceSHans Rosenfeld 	uint8_t ar_t1_bwi;
46*a61ed2ceSHans Rosenfeld 	uint8_t ar_t1_cwi;
47*a61ed2ceSHans Rosenfeld 	uint8_t ar_t1_ifsc;
48*a61ed2ceSHans Rosenfeld } atr_test_t;
49*a61ed2ceSHans Rosenfeld 
50*a61ed2ceSHans Rosenfeld atr_test_t atr_tests[] = {
51*a61ed2ceSHans Rosenfeld 	{ "zero-length data", 0, { 0 }, ATR_CODE_TOO_SHORT },
52*a61ed2ceSHans Rosenfeld 	{ "No T0", 1, { 0x3f }, ATR_CODE_TOO_SHORT },
53*a61ed2ceSHans Rosenfeld 	{ "Too much data", 34, { 0 }, ATR_CODE_TOO_LONG },
54*a61ed2ceSHans Rosenfeld 	{ "Overrun T0 (1)", 2, { 0x3b, 0x10 }, ATR_CODE_OVERRUN },
55*a61ed2ceSHans Rosenfeld 	{ "Overrun T0 (2)", 2, { 0x3b, 0x80 }, ATR_CODE_OVERRUN },
56*a61ed2ceSHans Rosenfeld 	{ "Overrun T0 (3)", 2, { 0x3b, 0x01 }, ATR_CODE_OVERRUN },
57*a61ed2ceSHans Rosenfeld 	{ "Overrun T0 (4)", 2, { 0x3b, 0x11 }, ATR_CODE_OVERRUN },
58*a61ed2ceSHans Rosenfeld 	{ "Overrun T0 (5)", 2, { 0x3b, 0xff }, ATR_CODE_OVERRUN },
59*a61ed2ceSHans Rosenfeld 	{ "Overrun TD1", 3, { 0x3b, 0x80, 0x10 }, ATR_CODE_OVERRUN },
60*a61ed2ceSHans Rosenfeld 	{ "Overrun TD2", 4, { 0x3b, 0x80, 0x80, 0x10 }, ATR_CODE_OVERRUN },
61*a61ed2ceSHans Rosenfeld 	{ "Overrun TD", 33, { 0x3b, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
62*a61ed2ceSHans Rosenfeld 	    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
63*a61ed2ceSHans Rosenfeld 	    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
64*a61ed2ceSHans Rosenfeld 	    0x80, 0x80, 0x80 }, ATR_CODE_OVERRUN },
65*a61ed2ceSHans Rosenfeld 	{ "T0 w/ T=15 and no cksum", 5, { 0x3b, 0x80, 0x80, 0x1f, 0x00 },
66*a61ed2ceSHans Rosenfeld 	    ATR_CODE_OVERRUN },
67*a61ed2ceSHans Rosenfeld 	{ "Bad TS (1)", 2, { 0x3a, 0x00 }, ATR_CODE_INVALID_TS },
68*a61ed2ceSHans Rosenfeld 	{ "Bad TS (2)", 2, { 0xff, 0x00 }, ATR_CODE_INVALID_TS },
69*a61ed2ceSHans Rosenfeld 	{ "T0 w/ T=15 and bad cksum", 6, { 0x3b, 0x80, 0x80, 0x1f, 0x00, 0x00 },
70*a61ed2ceSHans Rosenfeld 	    ATR_CODE_CHECKSUM_ERROR },
71*a61ed2ceSHans Rosenfeld 	{ "T0 w/ T=15 and bad cksum (make sure no TS)", 6,
72*a61ed2ceSHans Rosenfeld 	    { 0x3b, 0x80, 0x80, 0x1f, 0x00, 0x24 },
73*a61ed2ceSHans Rosenfeld 	    ATR_CODE_CHECKSUM_ERROR },
74*a61ed2ceSHans Rosenfeld 	{ "T=15 in TD1", 4, { 0x3b, 0x80, 0x0f, 0x8f }, ATR_CODE_INVALID_TD1 },
75*a61ed2ceSHans Rosenfeld 	{
76*a61ed2ceSHans Rosenfeld 		.ar_test = "Minimal T0 Direct",
77*a61ed2ceSHans Rosenfeld 		.ar_len = 2,
78*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x00 },
79*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
80*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
81*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
82*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
83*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
84*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
85*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
86*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
87*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
88*a61ed2ceSHans Rosenfeld 	}, {
89*a61ed2ceSHans Rosenfeld 		.ar_test = "Minimal T0 Inverse",
90*a61ed2ceSHans Rosenfeld 		.ar_len = 2,
91*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3f, 0x00 },
92*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
93*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
94*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
95*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
96*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
97*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_INVERSE,
98*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
99*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
100*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
101*a61ed2ceSHans Rosenfeld 	}, {
102*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Fi/Di (1)",
103*a61ed2ceSHans Rosenfeld 		.ar_len = 3,
104*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x10, 0x24 },
105*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
106*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
107*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
108*a61ed2ceSHans Rosenfeld 		.ar_fi = 2,
109*a61ed2ceSHans Rosenfeld 		.ar_di = 4,
110*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
111*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
112*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
113*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
114*a61ed2ceSHans Rosenfeld 	}, {
115*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Fi/Di (2)",
116*a61ed2ceSHans Rosenfeld 		.ar_len = 3,
117*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x10, 0x93 },
118*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
119*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
120*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
121*a61ed2ceSHans Rosenfeld 		.ar_fi = 9,
122*a61ed2ceSHans Rosenfeld 		.ar_di = 3,
123*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
124*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
125*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
126*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
127*a61ed2ceSHans Rosenfeld 	}, {
128*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Ignore deprecated TB1",
129*a61ed2ceSHans Rosenfeld 		.ar_len = 3,
130*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x20, 0x42 },
131*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
132*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
133*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
134*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
135*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
136*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
137*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
138*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
139*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
140*a61ed2ceSHans Rosenfeld 	}, {
141*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Ignore deprecated TB2",
142*a61ed2ceSHans Rosenfeld 		.ar_len = 4,
143*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x20, 0x42 },
144*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
145*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
146*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
147*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
148*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
149*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
150*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
151*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
152*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
153*a61ed2ceSHans Rosenfeld 	}, {
154*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Ignore deprecated TB1/TB2",
155*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
156*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0xa0, 0x55, 0x20, 0x42 },
157*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
158*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
159*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
160*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
161*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
162*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
163*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
164*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
165*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
166*a61ed2ceSHans Rosenfeld 	}, {
167*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 Encode TC1",
168*a61ed2ceSHans Rosenfeld 		.ar_len = 3,
169*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x40, 0x23 },
170*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
171*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
172*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
173*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
174*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
175*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
176*a61ed2ceSHans Rosenfeld 		.ar_guard = 0x23,
177*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
178*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
179*a61ed2ceSHans Rosenfeld 	}, {
180*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 TA2 says neg",
181*a61ed2ceSHans Rosenfeld 		.ar_len = 4,
182*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x10, 0x00 },
183*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
184*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
185*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
186*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
187*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
188*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
189*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
190*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
191*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
192*a61ed2ceSHans Rosenfeld 	}, {
193*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 TA2 says not neg",
194*a61ed2ceSHans Rosenfeld 		.ar_len = 4,
195*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x10, 0x80 },
196*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
197*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
198*a61ed2ceSHans Rosenfeld 		.ar_neg = B_FALSE,
199*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
200*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
201*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
202*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
203*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
204*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
205*a61ed2ceSHans Rosenfeld 	}, {
206*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 TA2 says not neg, honor Fi/Di",
207*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
208*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x90, 0x24, 0x10, 0x80 },
209*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
210*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
211*a61ed2ceSHans Rosenfeld 		.ar_neg = B_FALSE,
212*a61ed2ceSHans Rosenfeld 		.ar_fi = 2,
213*a61ed2ceSHans Rosenfeld 		.ar_di = 4,
214*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
215*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
216*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
217*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
218*a61ed2ceSHans Rosenfeld 	}, {
219*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 TA2 says not neg, don't honor Fi/Di",
220*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
221*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x90, 0x24, 0x10, 0x90 },
222*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
223*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
224*a61ed2ceSHans Rosenfeld 		.ar_neg = B_FALSE,
225*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
226*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
227*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
228*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
229*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
230*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
231*a61ed2ceSHans Rosenfeld 	}, {
232*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 TC2 set",
233*a61ed2ceSHans Rosenfeld 		.ar_len = 4,
234*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x40, 0x35 },
235*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
236*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
237*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
238*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
239*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
240*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
241*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
242*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
243*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 0x35,
244*a61ed2ceSHans Rosenfeld 	}, {
245*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 T15 empty (requires checksum)",
246*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
247*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x80, 0x0f, 0x0f },
248*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
249*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
250*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
251*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
252*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
253*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
254*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
255*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
256*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
257*a61ed2ceSHans Rosenfeld 	}, {
258*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 T15 Clock Stop (1)",
259*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
260*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x07, 0x18 },
261*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
262*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
263*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
264*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
265*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
266*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
267*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
268*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
269*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
270*a61ed2ceSHans Rosenfeld 	}, {
271*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 T15 Clock Stop (2)",
272*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
273*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x47, 0x58 },
274*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
275*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
276*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
277*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
278*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
279*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
280*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
281*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_LOW,
282*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
283*a61ed2ceSHans Rosenfeld 	}, {
284*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 T15 Clock Stop (3)",
285*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
286*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x87, 0x98 },
287*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
288*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
289*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
290*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
291*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
292*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
293*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
294*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_HI,
295*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
296*a61ed2ceSHans Rosenfeld 	}, {
297*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 T15 Clock Stop (4)",
298*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
299*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0xc7, 0xd8 },
300*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
301*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
302*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
303*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
304*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
305*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
306*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
307*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_BOTH,
308*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
309*a61ed2ceSHans Rosenfeld 	}, {
310*a61ed2ceSHans Rosenfeld 		.ar_test = "T0 with random prots",
311*a61ed2ceSHans Rosenfeld 		.ar_len = 7,
312*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x84, 0x85, 0x88, 0x0f, 0x06 },
313*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0,
314*a61ed2ceSHans Rosenfeld 		/*
315*a61ed2ceSHans Rosenfeld 		 * This comes from the fact that TD1 is T=4 and that isn't
316*a61ed2ceSHans Rosenfeld 		 * supported in the system.
317*a61ed2ceSHans Rosenfeld 		 */
318*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_NONE,
319*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
320*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
321*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
322*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
323*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
324*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
325*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
326*a61ed2ceSHans Rosenfeld 	}, {
327*a61ed2ceSHans Rosenfeld 		.ar_test = "Actual ATR (1, Yubikey4)",
328*a61ed2ceSHans Rosenfeld 		.ar_len = 18,
329*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0xf8, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe,
330*a61ed2ceSHans Rosenfeld 		    0x15, 0x59, 0x75, 0x62, 0x69, 0x6b, 0x65, 0x79, 0x34,
331*a61ed2ceSHans Rosenfeld 		    0xd4 },
332*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
333*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
334*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
335*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
336*a61ed2ceSHans Rosenfeld 		.ar_di = 3,
337*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
338*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
339*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
340*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
341*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 1,
342*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 5,
343*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 254
344*a61ed2ceSHans Rosenfeld 	}, {
345*a61ed2ceSHans Rosenfeld 		.ar_test = "Actual ATR (2)",
346*a61ed2ceSHans Rosenfeld 		.ar_len = 19,
347*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0xf9, 0x18, 0x00, 0x00, 0x81, 0x31, 0xfe,
348*a61ed2ceSHans Rosenfeld 		    0x45, 0x4a, 0x32, 0x44, 0x30, 0x38, 0x31, 0x5f, 0x50, 0x56,
349*a61ed2ceSHans Rosenfeld 		    0xb6 },
350*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
351*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
352*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
353*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
354*a61ed2ceSHans Rosenfeld 		.ar_di = 8,
355*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
356*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
357*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
358*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
359*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
360*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 5,
361*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 254
362*a61ed2ceSHans Rosenfeld 	}, {
363*a61ed2ceSHans Rosenfeld 		.ar_test = "Actual ATR (3)",
364*a61ed2ceSHans Rosenfeld 		.ar_len = 22,
365*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0xfc, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80,
366*a61ed2ceSHans Rosenfeld 		    0x45, 0x90, 0x67, 0x46, 0x4a, 0x00, 0x64, 0x16, 0x6, 0xf2,
367*a61ed2ceSHans Rosenfeld 		    0x72, 0x7e, 0x00, 0xe0 },
368*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
369*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
370*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
371*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
372*a61ed2ceSHans Rosenfeld 		.ar_di = 8,
373*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
374*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
375*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
376*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
377*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
378*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 5,
379*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 128
380*a61ed2ceSHans Rosenfeld 	}, {
381*a61ed2ceSHans Rosenfeld 		.ar_test = "Minimal T=1",
382*a61ed2ceSHans Rosenfeld 		.ar_len = 4,
383*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x01, 0x81 },
384*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
385*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
386*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
387*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
388*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
389*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
390*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
391*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
392*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
393*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
394*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
395*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
396*a61ed2ceSHans Rosenfeld 	}, {
397*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1 Fi/Di",
398*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
399*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x90, 0x34, 0x01, 0xa5 },
400*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
401*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
402*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
403*a61ed2ceSHans Rosenfeld 		.ar_fi = 3,
404*a61ed2ceSHans Rosenfeld 		.ar_di = 4,
405*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
406*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
407*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
408*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
409*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
410*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
411*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
412*a61ed2ceSHans Rosenfeld 	}, {
413*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1 TA2 says neg, T=1 def",
414*a61ed2ceSHans Rosenfeld 		.ar_len = 5,
415*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x11, 0x11, 0x80 },
416*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
417*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
418*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
419*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
420*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
421*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
422*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
423*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
424*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
425*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
426*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
427*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
428*a61ed2ceSHans Rosenfeld 	}, {
429*a61ed2ceSHans Rosenfeld 		.ar_test = "T=0, T=1 TA2 says neg, T=0 def",
430*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
431*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x90, 0x10, 0x01, 0x01 },
432*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0 | ATR_P_T1,
433*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
434*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
435*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
436*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
437*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
438*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
439*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
440*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
441*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
442*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
443*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
444*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
445*a61ed2ceSHans Rosenfeld 	}, {
446*a61ed2ceSHans Rosenfeld 		.ar_test = "T=0, T=1 TA2 says neg, T=1 def",
447*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
448*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x90, 0x11, 0x01, 0x00 },
449*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0 | ATR_P_T1,
450*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
451*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
452*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
453*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
454*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
455*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
456*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
457*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
458*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
459*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
460*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
461*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
462*a61ed2ceSHans Rosenfeld 	}, {
463*a61ed2ceSHans Rosenfeld 		.ar_test = "T=0, T=1 TA2 says not neg, T=0 def",
464*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
465*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x90, 0x90, 0x01, 0x81 },
466*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0 | ATR_P_T1,
467*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T0,
468*a61ed2ceSHans Rosenfeld 		.ar_neg = B_FALSE,
469*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
470*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
471*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
472*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
473*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
474*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
475*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
476*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
477*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
478*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
479*a61ed2ceSHans Rosenfeld 	}, {
480*a61ed2ceSHans Rosenfeld 		.ar_test = "T=0, T=1 TA2 says not neg, T=1 def",
481*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
482*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x90, 0x81, 0x01, 0x90 },
483*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T0 | ATR_P_T1,
484*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
485*a61ed2ceSHans Rosenfeld 		.ar_neg = B_FALSE,
486*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
487*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
488*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
489*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
490*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
491*a61ed2ceSHans Rosenfeld 		.ar_t0_wi = 10,
492*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
493*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
494*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
495*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
496*a61ed2ceSHans Rosenfeld 	}, {
497*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1, BWI/CWI",
498*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
499*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x81, 0x21, 0x59, 0x79 },
500*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
501*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
502*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
503*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
504*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
505*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
506*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
507*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
508*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
509*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 5,
510*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 9,
511*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
512*a61ed2ceSHans Rosenfeld 	}, {
513*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1, IFSC",
514*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
515*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x81, 0x11, 0x49, 0x59 },
516*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
517*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
518*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
519*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
520*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
521*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
522*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
523*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
524*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
525*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
526*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
527*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 73
528*a61ed2ceSHans Rosenfeld 	}, {
529*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1, Checksum (LRC)",
530*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
531*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x81, 0x41, 0x00, 0x40 },
532*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
533*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
534*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
535*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
536*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
537*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
538*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
539*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
540*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
541*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
542*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
543*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
544*a61ed2ceSHans Rosenfeld 	}, {
545*a61ed2ceSHans Rosenfeld 		.ar_test = "T=1, Checksum (CRC)",
546*a61ed2ceSHans Rosenfeld 		.ar_len = 6,
547*a61ed2ceSHans Rosenfeld 		.ar_buf = { 0x3b, 0x80, 0x81, 0x41, 0x01, 0x41 },
548*a61ed2ceSHans Rosenfeld 		.ar_sup = ATR_P_T1,
549*a61ed2ceSHans Rosenfeld 		.ar_def = ATR_P_T1,
550*a61ed2ceSHans Rosenfeld 		.ar_neg = B_TRUE,
551*a61ed2ceSHans Rosenfeld 		.ar_fi = 1,
552*a61ed2ceSHans Rosenfeld 		.ar_di = 1,
553*a61ed2ceSHans Rosenfeld 		.ar_conv = ATR_CONVENTION_DIRECT,
554*a61ed2ceSHans Rosenfeld 		.ar_guard = 0,
555*a61ed2ceSHans Rosenfeld 		.ar_stop = ATR_CLOCK_STOP_NONE,
556*a61ed2ceSHans Rosenfeld 		.ar_t1_cksum = ATR_T1_CHECKSUM_CRC,
557*a61ed2ceSHans Rosenfeld 		.ar_t1_bwi = 4,
558*a61ed2ceSHans Rosenfeld 		.ar_t1_cwi = 13,
559*a61ed2ceSHans Rosenfeld 		.ar_t1_ifsc = 32
560*a61ed2ceSHans Rosenfeld 	}
561*a61ed2ceSHans Rosenfeld };
562*a61ed2ceSHans Rosenfeld 
563*a61ed2ceSHans Rosenfeld static void
atr_parse_failed(atr_test_t * test,const char * fmt,...)564*a61ed2ceSHans Rosenfeld atr_parse_failed(atr_test_t *test, const char *fmt, ...)
565*a61ed2ceSHans Rosenfeld {
566*a61ed2ceSHans Rosenfeld 	va_list ap;
567*a61ed2ceSHans Rosenfeld 
568*a61ed2ceSHans Rosenfeld 	va_start(ap, fmt);
569*a61ed2ceSHans Rosenfeld 	(void) fprintf(stderr, "Test \"%s\" failed: ", test->ar_test);
570*a61ed2ceSHans Rosenfeld 	(void) vfprintf(stderr, fmt, ap);
571*a61ed2ceSHans Rosenfeld 	(void) fprintf(stderr, "\n");
572*a61ed2ceSHans Rosenfeld 	va_end(ap);
573*a61ed2ceSHans Rosenfeld }
574*a61ed2ceSHans Rosenfeld 
575*a61ed2ceSHans Rosenfeld static uint_t
atr_parse_one(atr_data_t * data,atr_test_t * test)576*a61ed2ceSHans Rosenfeld atr_parse_one(atr_data_t *data, atr_test_t *test)
577*a61ed2ceSHans Rosenfeld {
578*a61ed2ceSHans Rosenfeld 	uint_t err = 0;
579*a61ed2ceSHans Rosenfeld 	atr_parsecode_t ret;
580*a61ed2ceSHans Rosenfeld 	atr_protocol_t sup, def;
581*a61ed2ceSHans Rosenfeld 	boolean_t neg;
582*a61ed2ceSHans Rosenfeld 	uint8_t fi, di, guard;
583*a61ed2ceSHans Rosenfeld 	atr_convention_t conv;
584*a61ed2ceSHans Rosenfeld 	atr_clock_stop_t stop;
585*a61ed2ceSHans Rosenfeld 
586*a61ed2ceSHans Rosenfeld 	ret = atr_parse(test->ar_buf, test->ar_len, data);
587*a61ed2ceSHans Rosenfeld 	if (ret != test->ar_retval) {
588*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "found unexpected return "
589*a61ed2ceSHans Rosenfeld 		    "value: %u (%s), expected: %u", ret, atr_strerror(ret),
590*a61ed2ceSHans Rosenfeld 		    test->ar_retval);
591*a61ed2ceSHans Rosenfeld 		return (1);
592*a61ed2ceSHans Rosenfeld 	}
593*a61ed2ceSHans Rosenfeld 
594*a61ed2ceSHans Rosenfeld 	/* Don't test anything else if it's not OK */
595*a61ed2ceSHans Rosenfeld 	if (ret != ATR_CODE_OK)
596*a61ed2ceSHans Rosenfeld 		return (0);
597*a61ed2ceSHans Rosenfeld 
598*a61ed2ceSHans Rosenfeld 	sup = atr_supported_protocols(data);
599*a61ed2ceSHans Rosenfeld 	def = atr_default_protocol(data);
600*a61ed2ceSHans Rosenfeld 	neg = atr_params_negotiable(data);
601*a61ed2ceSHans Rosenfeld 	fi = atr_fi_index(data);
602*a61ed2ceSHans Rosenfeld 	di = atr_di_index(data);
603*a61ed2ceSHans Rosenfeld 	conv = atr_convention(data);
604*a61ed2ceSHans Rosenfeld 	guard = atr_extra_guardtime(data);
605*a61ed2ceSHans Rosenfeld 	stop = atr_clock_stop(data);
606*a61ed2ceSHans Rosenfeld 
607*a61ed2ceSHans Rosenfeld 	if (sup != test->ar_sup) {
608*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched supported "
609*a61ed2ceSHans Rosenfeld 		    "protocols: %u, expected: %u", sup, test->ar_sup);
610*a61ed2ceSHans Rosenfeld 		err++;
611*a61ed2ceSHans Rosenfeld 	}
612*a61ed2ceSHans Rosenfeld 
613*a61ed2ceSHans Rosenfeld 	if (def != test->ar_def) {
614*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched default "
615*a61ed2ceSHans Rosenfeld 		    "protocols: %u, expected: %u", def, test->ar_def);
616*a61ed2ceSHans Rosenfeld 		err++;
617*a61ed2ceSHans Rosenfeld 	}
618*a61ed2ceSHans Rosenfeld 
619*a61ed2ceSHans Rosenfeld 	if (neg != test->ar_neg) {
620*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched negotiable bit: "
621*a61ed2ceSHans Rosenfeld 		    "%u, expected %u", neg, test->ar_neg);
622*a61ed2ceSHans Rosenfeld 		err++;
623*a61ed2ceSHans Rosenfeld 	}
624*a61ed2ceSHans Rosenfeld 
625*a61ed2ceSHans Rosenfeld 	if (fi != test->ar_fi) {
626*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched fi index: "
627*a61ed2ceSHans Rosenfeld 		    "%u, expected: %u", fi, test->ar_fi);
628*a61ed2ceSHans Rosenfeld 		err++;
629*a61ed2ceSHans Rosenfeld 	}
630*a61ed2ceSHans Rosenfeld 
631*a61ed2ceSHans Rosenfeld 	if (di != test->ar_di) {
632*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched di index: "
633*a61ed2ceSHans Rosenfeld 		    "%u, expected: %u", di, test->ar_di);
634*a61ed2ceSHans Rosenfeld 		err++;
635*a61ed2ceSHans Rosenfeld 	}
636*a61ed2ceSHans Rosenfeld 
637*a61ed2ceSHans Rosenfeld 	if (conv != test->ar_conv) {
638*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched TS convention: "
639*a61ed2ceSHans Rosenfeld 		    "%u, expected: %u", conv, test->ar_conv);
640*a61ed2ceSHans Rosenfeld 		err++;
641*a61ed2ceSHans Rosenfeld 	}
642*a61ed2ceSHans Rosenfeld 
643*a61ed2ceSHans Rosenfeld 	if (guard != test->ar_guard) {
644*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched extra guardtime: "
645*a61ed2ceSHans Rosenfeld 		    "%u, expected: %u", guard, test->ar_guard);
646*a61ed2ceSHans Rosenfeld 		err++;
647*a61ed2ceSHans Rosenfeld 	}
648*a61ed2ceSHans Rosenfeld 
649*a61ed2ceSHans Rosenfeld 	if (stop != test->ar_stop) {
650*a61ed2ceSHans Rosenfeld 		atr_parse_failed(test, "Found mismatched clock stop: "
651*a61ed2ceSHans Rosenfeld 		    "%u, expected: %u", stop, test->ar_stop);
652*a61ed2ceSHans Rosenfeld 		err++;
653*a61ed2ceSHans Rosenfeld 	}
654*a61ed2ceSHans Rosenfeld 
655*a61ed2ceSHans Rosenfeld 	if ((sup & ATR_P_T0) != 0) {
656*a61ed2ceSHans Rosenfeld 		uint8_t wi;
657*a61ed2ceSHans Rosenfeld 
658*a61ed2ceSHans Rosenfeld 		wi = atr_t0_wi(data);
659*a61ed2ceSHans Rosenfeld 		if (wi != test->ar_t0_wi) {
660*a61ed2ceSHans Rosenfeld 			atr_parse_failed(test, "Found mismatched T0 wi: "
661*a61ed2ceSHans Rosenfeld 			    "%u, expected: %u", wi, test->ar_t0_wi);
662*a61ed2ceSHans Rosenfeld 			err++;
663*a61ed2ceSHans Rosenfeld 		}
664*a61ed2ceSHans Rosenfeld 	}
665*a61ed2ceSHans Rosenfeld 
666*a61ed2ceSHans Rosenfeld 	if ((sup & ATR_P_T1) != 0) {
667*a61ed2ceSHans Rosenfeld 		atr_t1_checksum_t cksum;
668*a61ed2ceSHans Rosenfeld 		uint8_t bwi, cwi, ifsc;
669*a61ed2ceSHans Rosenfeld 
670*a61ed2ceSHans Rosenfeld 		cksum = atr_t1_checksum(data);
671*a61ed2ceSHans Rosenfeld 		bwi = atr_t1_bwi(data);
672*a61ed2ceSHans Rosenfeld 		cwi = atr_t1_cwi(data);
673*a61ed2ceSHans Rosenfeld 		ifsc = atr_t1_ifsc(data);
674*a61ed2ceSHans Rosenfeld 
675*a61ed2ceSHans Rosenfeld 		if (cksum != test->ar_t1_cksum) {
676*a61ed2ceSHans Rosenfeld 			atr_parse_failed(test, "Found mistmatched T1 checksum: "
677*a61ed2ceSHans Rosenfeld 			    "%u, expected: %u", cksum, test->ar_t1_cksum);
678*a61ed2ceSHans Rosenfeld 			err++;
679*a61ed2ceSHans Rosenfeld 		}
680*a61ed2ceSHans Rosenfeld 
681*a61ed2ceSHans Rosenfeld 		if (bwi != test->ar_t1_bwi) {
682*a61ed2ceSHans Rosenfeld 			atr_parse_failed(test, "Found mistmatched T1 bwi: "
683*a61ed2ceSHans Rosenfeld 			    "%u, expected: %u", bwi, test->ar_t1_bwi);
684*a61ed2ceSHans Rosenfeld 			err++;
685*a61ed2ceSHans Rosenfeld 		}
686*a61ed2ceSHans Rosenfeld 
687*a61ed2ceSHans Rosenfeld 		if (cwi != test->ar_t1_cwi) {
688*a61ed2ceSHans Rosenfeld 			atr_parse_failed(test, "Found mistmatched T1 cwi: "
689*a61ed2ceSHans Rosenfeld 			    "%u, expected: %u", cwi, test->ar_t1_cwi);
690*a61ed2ceSHans Rosenfeld 			err++;
691*a61ed2ceSHans Rosenfeld 		}
692*a61ed2ceSHans Rosenfeld 
693*a61ed2ceSHans Rosenfeld 		if (ifsc != test->ar_t1_ifsc) {
694*a61ed2ceSHans Rosenfeld 			atr_parse_failed(test, "Found mistmatched T1 ifsc: "
695*a61ed2ceSHans Rosenfeld 			    "%u, expected: %u", ifsc, test->ar_t1_ifsc);
696*a61ed2ceSHans Rosenfeld 			err++;
697*a61ed2ceSHans Rosenfeld 		}
698*a61ed2ceSHans Rosenfeld 	}
699*a61ed2ceSHans Rosenfeld 
700*a61ed2ceSHans Rosenfeld 	if (err > 0) {
701*a61ed2ceSHans Rosenfeld 		atr_data_dump(data, stderr);
702*a61ed2ceSHans Rosenfeld 		return (1);
703*a61ed2ceSHans Rosenfeld 	}
704*a61ed2ceSHans Rosenfeld 
705*a61ed2ceSHans Rosenfeld 	return (0);
706*a61ed2ceSHans Rosenfeld }
707*a61ed2ceSHans Rosenfeld 
708*a61ed2ceSHans Rosenfeld int
main(void)709*a61ed2ceSHans Rosenfeld main(void)
710*a61ed2ceSHans Rosenfeld {
711*a61ed2ceSHans Rosenfeld 	uint_t i;
712*a61ed2ceSHans Rosenfeld 	uint_t errs = 0;
713*a61ed2ceSHans Rosenfeld 	atr_data_t *data;
714*a61ed2ceSHans Rosenfeld 
715*a61ed2ceSHans Rosenfeld 	data = atr_data_alloc();
716*a61ed2ceSHans Rosenfeld 	if (data == NULL) {
717*a61ed2ceSHans Rosenfeld 		errx(EXIT_FAILURE, "failed to allocate atr_data_t");
718*a61ed2ceSHans Rosenfeld 	}
719*a61ed2ceSHans Rosenfeld 
720*a61ed2ceSHans Rosenfeld 	for (i = 0; i < sizeof (atr_tests) / sizeof (atr_test_t); i++) {
721*a61ed2ceSHans Rosenfeld 		atr_data_reset(data);
722*a61ed2ceSHans Rosenfeld 		errs += atr_parse_one(data, &atr_tests[i]);
723*a61ed2ceSHans Rosenfeld 	}
724*a61ed2ceSHans Rosenfeld 
725*a61ed2ceSHans Rosenfeld 	atr_data_free(data);
726*a61ed2ceSHans Rosenfeld 
727*a61ed2ceSHans Rosenfeld 	if (errs != 0) {
728*a61ed2ceSHans Rosenfeld 		warnx("%d test(s) failed", errs);
729*a61ed2ceSHans Rosenfeld 	}
730*a61ed2ceSHans Rosenfeld 	return (errs != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
731*a61ed2ceSHans Rosenfeld }
732