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 * ATR parsing routines shared between userland (ccidadm) and the kernel (CCID
18*a61ed2ceSHans Rosenfeld * driver)
19*a61ed2ceSHans Rosenfeld */
20*a61ed2ceSHans Rosenfeld
21*a61ed2ceSHans Rosenfeld #include "atr.h"
22*a61ed2ceSHans Rosenfeld #include <sys/debug.h>
23*a61ed2ceSHans Rosenfeld #include <sys/sysmacros.h>
24*a61ed2ceSHans Rosenfeld
25*a61ed2ceSHans Rosenfeld #ifdef _KERNEL
26*a61ed2ceSHans Rosenfeld #include <sys/inttypes.h>
27*a61ed2ceSHans Rosenfeld #include <sys/sunddi.h>
28*a61ed2ceSHans Rosenfeld #include <sys/kmem.h>
29*a61ed2ceSHans Rosenfeld #else
30*a61ed2ceSHans Rosenfeld #include <inttypes.h>
31*a61ed2ceSHans Rosenfeld #include <strings.h>
32*a61ed2ceSHans Rosenfeld #include <stdlib.h>
33*a61ed2ceSHans Rosenfeld #include <stdio.h>
34*a61ed2ceSHans Rosenfeld #include <ctype.h>
35*a61ed2ceSHans Rosenfeld #endif
36*a61ed2ceSHans Rosenfeld
37*a61ed2ceSHans Rosenfeld /*
38*a61ed2ceSHans Rosenfeld * The ATR must have at least 2 bytes and then may have up to 33 bytes. The
39*a61ed2ceSHans Rosenfeld * first byte is always TS and the second required byte is T0.
40*a61ed2ceSHans Rosenfeld */
41*a61ed2ceSHans Rosenfeld #define ATR_TS_IDX 0
42*a61ed2ceSHans Rosenfeld #define ATR_T0_IDX 1
43*a61ed2ceSHans Rosenfeld
44*a61ed2ceSHans Rosenfeld /*
45*a61ed2ceSHans Rosenfeld * There are two valid values for TS. It must either be 0x3F or 0x3B. This is
46*a61ed2ceSHans Rosenfeld * required per ISO/IEC 7816-3:2006 section 8.1.
47*a61ed2ceSHans Rosenfeld */
48*a61ed2ceSHans Rosenfeld #define ATR_TS_INVERSE 0x3F
49*a61ed2ceSHans Rosenfeld #define ATR_TS_DIRECT 0x3B
50*a61ed2ceSHans Rosenfeld
51*a61ed2ceSHans Rosenfeld /*
52*a61ed2ceSHans Rosenfeld * After TS, each word is used to indicate a combination of protocol and the
53*a61ed2ceSHans Rosenfeld * number of bits defined for that protocol. The lower nibble is treated as the
54*a61ed2ceSHans Rosenfeld * protocol. The upper nibble is treated to indicate which of four defined words
55*a61ed2ceSHans Rosenfeld * are present. These are usually referred to as TA, TB, TC, and TD. TD is
56*a61ed2ceSHans Rosenfeld * always used to indicate the next protocol and the number of bytes present for
57*a61ed2ceSHans Rosenfeld * that. T0 works in a similar way, except that it defines the number of
58*a61ed2ceSHans Rosenfeld * historical bytes present in its protocol section and then it refers to a set
59*a61ed2ceSHans Rosenfeld * of pre-defined global bytes that may be present.
60*a61ed2ceSHans Rosenfeld */
61*a61ed2ceSHans Rosenfeld #define ATR_TD_PROT(x) ((x) & 0x0f)
62*a61ed2ceSHans Rosenfeld #define ATR_TD_NBITS(x) (((x) & 0xf0) >> 4)
63*a61ed2ceSHans Rosenfeld #define ATR_TA_MASK 0x1
64*a61ed2ceSHans Rosenfeld #define ATR_TB_MASK 0x2
65*a61ed2ceSHans Rosenfeld #define ATR_TC_MASK 0x4
66*a61ed2ceSHans Rosenfeld #define ATR_TD_MASK 0x8
67*a61ed2ceSHans Rosenfeld
68*a61ed2ceSHans Rosenfeld #define ATR_TA1_FTABLE(x) (((x) & 0xf0) >> 4)
69*a61ed2ceSHans Rosenfeld #define ATR_TA1_DITABLE(x) ((x) & 0x0f)
70*a61ed2ceSHans Rosenfeld
71*a61ed2ceSHans Rosenfeld #define ATR_TA2_CANCHANGE(x) (((x) & 0x80) == 0)
72*a61ed2ceSHans Rosenfeld #define ATR_TA2_HONORTA1(x) (((x) & 0x10) == 0)
73*a61ed2ceSHans Rosenfeld #define ATR_TA2_PROTOCOL(x) ((x) & 0x0f)
74*a61ed2ceSHans Rosenfeld
75*a61ed2ceSHans Rosenfeld /*
76*a61ed2ceSHans Rosenfeld * When the checksum is required in the ATR, each byte must XOR to zero.
77*a61ed2ceSHans Rosenfeld */
78*a61ed2ceSHans Rosenfeld #define ATR_CKSUM_TARGET 0
79*a61ed2ceSHans Rosenfeld
80*a61ed2ceSHans Rosenfeld /*
81*a61ed2ceSHans Rosenfeld * Maximum number of historic ATR bytes. This is limited by the fact that it's a
82*a61ed2ceSHans Rosenfeld * 4-bit nibble.
83*a61ed2ceSHans Rosenfeld */
84*a61ed2ceSHans Rosenfeld #define ATR_HISTORICAL_MAX 15
85*a61ed2ceSHans Rosenfeld
86*a61ed2ceSHans Rosenfeld /*
87*a61ed2ceSHans Rosenfeld * The maximum number of TA, TB, TC, and TD levels that can be encountered in a
88*a61ed2ceSHans Rosenfeld * given structure. In the best case, there are 30 bytes available (TS, T0, and
89*a61ed2ceSHans Rosenfeld * TCK use the others). Given that each one of these needs 4 bytes to be
90*a61ed2ceSHans Rosenfeld * represented, the maximum number of layers that can fit is seven.
91*a61ed2ceSHans Rosenfeld */
92*a61ed2ceSHans Rosenfeld #define ATR_TI_MAX 7
93*a61ed2ceSHans Rosenfeld
94*a61ed2ceSHans Rosenfeld /*
95*a61ed2ceSHans Rosenfeld * Defined protocol values. See ISO/IEC 7816-3:2006 8.2.3 for this list.
96*a61ed2ceSHans Rosenfeld * Reserved values are noted but not defined.
97*a61ed2ceSHans Rosenfeld */
98*a61ed2ceSHans Rosenfeld #define ATR_PROTOCOL_T0 0
99*a61ed2ceSHans Rosenfeld #define ATR_PROTOCOL_T1 1
100*a61ed2ceSHans Rosenfeld
101*a61ed2ceSHans Rosenfeld #define ATR_T1_TB0_CWI(x) ((x) & 0x0f)
102*a61ed2ceSHans Rosenfeld #define ATR_T1_TB0_BWI(x) (((x) & 0xf0) >> 4)
103*a61ed2ceSHans Rosenfeld #define ATR_T1_TC0_CRC(x) (((x) & 0x01) != 0)
104*a61ed2ceSHans Rosenfeld
105*a61ed2ceSHans Rosenfeld /*
106*a61ed2ceSHans Rosenfeld * T=2 and T=3 are reserved for future full-duplex operation.
107*a61ed2ceSHans Rosenfeld * T=4 is reserved for enhanced half-duplex character transmission.
108*a61ed2ceSHans Rosenfeld * T=5-13 are reserved for future use by ISO/IEC JTC 1/SC 17.
109*a61ed2ceSHans Rosenfeld * T=14 is for protocols not standardized by ISO/IEC JTC 1/SC 17.
110*a61ed2ceSHans Rosenfeld */
111*a61ed2ceSHans Rosenfeld #define ATR_PROTOCOL_T15 15
112*a61ed2ceSHans Rosenfeld
113*a61ed2ceSHans Rosenfeld #define ATR_T15_TA0_CLOCK(x) (((x) & 0xc0) >> 6)
114*a61ed2ceSHans Rosenfeld #define ATR_T15_TA0_VOLTAGE(x) ((x) & 0x3f)
115*a61ed2ceSHans Rosenfeld
116*a61ed2ceSHans Rosenfeld #define ATR_T15_TB0_SPU_STANDARD(x) (((x & 0x80)) != 0)
117*a61ed2ceSHans Rosenfeld
118*a61ed2ceSHans Rosenfeld /*
119*a61ed2ceSHans Rosenfeld * Various definitions for the configuration of historical data. This comes from
120*a61ed2ceSHans Rosenfeld * ISO/IEC 7816-4:2013 Section 12.1.1.
121*a61ed2ceSHans Rosenfeld */
122*a61ed2ceSHans Rosenfeld
123*a61ed2ceSHans Rosenfeld /*
124*a61ed2ceSHans Rosenfeld * The first historical byte is used to indicate the encoding of the data. Only
125*a61ed2ceSHans Rosenfeld * values 0x00, 0x80-0x8f are defined. All others are proprietary. 0x81-0x8f are
126*a61ed2ceSHans Rosenfeld * reserved for future use.
127*a61ed2ceSHans Rosenfeld */
128*a61ed2ceSHans Rosenfeld #define ATR_HIST_CAT_MAND_STATUS 0x00
129*a61ed2ceSHans Rosenfeld #define ATR_HIST_CAT_TLV_STATUS 0x80
130*a61ed2ceSHans Rosenfeld #define ATR_HIST_CAT_RFU_MIN 0x81
131*a61ed2ceSHans Rosenfeld #define ATR_HIST_CAT_RFU_MAX 0x8f
132*a61ed2ceSHans Rosenfeld
133*a61ed2ceSHans Rosenfeld /*
134*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 8.3.
135*a61ed2ceSHans Rosenfeld *
136*a61ed2ceSHans Rosenfeld * The default value for Fi is 372 which is table entry 1. The default value for
137*a61ed2ceSHans Rosenfeld * Di is 1, which is table entry 1.
138*a61ed2ceSHans Rosenfeld */
139*a61ed2ceSHans Rosenfeld #define ATR_FI_DEFAULT_INDEX 1
140*a61ed2ceSHans Rosenfeld #define ATR_DI_DEFAULT_INDEX 1
141*a61ed2ceSHans Rosenfeld #define ATR_EXTRA_GUARDTIME_DEFAULT 0
142*a61ed2ceSHans Rosenfeld
143*a61ed2ceSHans Rosenfeld /*
144*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 10.2.
145*a61ed2ceSHans Rosenfeld */
146*a61ed2ceSHans Rosenfeld #define ATR_T0_WI_DEFAULT 10
147*a61ed2ceSHans Rosenfeld
148*a61ed2ceSHans Rosenfeld /*
149*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 11.4.3.
150*a61ed2ceSHans Rosenfeld */
151*a61ed2ceSHans Rosenfeld #define ATR_T1_CWI_DEFAULT 13
152*a61ed2ceSHans Rosenfeld
153*a61ed2ceSHans Rosenfeld /*
154*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 11.4.3.
155*a61ed2ceSHans Rosenfeld */
156*a61ed2ceSHans Rosenfeld #define ATR_T1_BWI_DEFAULT 4
157*a61ed2ceSHans Rosenfeld
158*a61ed2ceSHans Rosenfeld /*
159*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 11.4.2.
160*a61ed2ceSHans Rosenfeld */
161*a61ed2ceSHans Rosenfeld #define ATR_T1_IFSC_DEFAULT 32
162*a61ed2ceSHans Rosenfeld
163*a61ed2ceSHans Rosenfeld /*
164*a61ed2ceSHans Rosenfeld * From ISO/IEC 7816-3:2006 Section 11.4.4
165*a61ed2ceSHans Rosenfeld */
166*a61ed2ceSHans Rosenfeld #define ATR_T1_CHECKSUM_DEFAULT ATR_T1_CHECKSUM_LRC
167*a61ed2ceSHans Rosenfeld
168*a61ed2ceSHans Rosenfeld /*
169*a61ed2ceSHans Rosenfeld * Definitions for PPS construction. These are derived from ISO/IEC 7816-3:2006
170*a61ed2ceSHans Rosenfeld * section 9, Protocol and parameters selection.
171*a61ed2ceSHans Rosenfeld */
172*a61ed2ceSHans Rosenfeld #define PPS_LEN_MIN 3 /* PPSS, PPS0, PCK */
173*a61ed2ceSHans Rosenfeld #define PPS_LEN_MAX PPS_BUFFER_MAX
174*a61ed2ceSHans Rosenfeld #define PPS_PPSS_INDEX 0
175*a61ed2ceSHans Rosenfeld #define PPS_PPSS_VAL 0xff
176*a61ed2ceSHans Rosenfeld #define PPS_PPS0_INDEX 0x01
177*a61ed2ceSHans Rosenfeld #define PPS_PPS0_PROT(x) ((x) & 0x0f)
178*a61ed2ceSHans Rosenfeld #define PPS_PPS0_PPS1 (1 << 4)
179*a61ed2ceSHans Rosenfeld #define PPS_PPS0_PPS2 (1 << 5)
180*a61ed2ceSHans Rosenfeld #define PPS_PPS0_PPS3 (1 << 6)
181*a61ed2ceSHans Rosenfeld #define PPS_PPS1_SETVAL(f, d) ((((f) & 0x0f) << 4) | ((d) & 0x0f))
182*a61ed2ceSHans Rosenfeld
183*a61ed2ceSHans Rosenfeld /*
184*a61ed2ceSHans Rosenfeld * This enum and subsequent structure is used to represent a single level of
185*a61ed2ceSHans Rosenfeld * 'T'. This includes the possibility for all three values to be set and records
186*a61ed2ceSHans Rosenfeld * the protocol.
187*a61ed2ceSHans Rosenfeld */
188*a61ed2ceSHans Rosenfeld typedef enum atr_ti_flags {
189*a61ed2ceSHans Rosenfeld ATR_TI_HAVE_TA = 1 << 0,
190*a61ed2ceSHans Rosenfeld ATR_TI_HAVE_TB = 1 << 1,
191*a61ed2ceSHans Rosenfeld ATR_TI_HAVE_TC = 1 << 2,
192*a61ed2ceSHans Rosenfeld ATR_TI_HAVE_TD = 1 << 3
193*a61ed2ceSHans Rosenfeld } atr_ti_flags_t;
194*a61ed2ceSHans Rosenfeld
195*a61ed2ceSHans Rosenfeld typedef struct atr_ti {
196*a61ed2ceSHans Rosenfeld uint8_t atrti_protocol;
197*a61ed2ceSHans Rosenfeld uint8_t atrti_ti_val;
198*a61ed2ceSHans Rosenfeld uint8_t atrti_td_idx;
199*a61ed2ceSHans Rosenfeld atr_ti_flags_t atrti_flags;
200*a61ed2ceSHans Rosenfeld uint8_t atrti_ta;
201*a61ed2ceSHans Rosenfeld uint8_t atrti_tb;
202*a61ed2ceSHans Rosenfeld uint8_t atrti_tc;
203*a61ed2ceSHans Rosenfeld uint8_t atrti_td;
204*a61ed2ceSHans Rosenfeld } atr_ti_t;
205*a61ed2ceSHans Rosenfeld
206*a61ed2ceSHans Rosenfeld typedef enum atr_flags {
207*a61ed2ceSHans Rosenfeld ATR_F_USES_DIRECT = 1 << 0,
208*a61ed2ceSHans Rosenfeld ATR_F_USES_INVERSE = 1 << 1,
209*a61ed2ceSHans Rosenfeld ATR_F_HAS_CHECKSUM = 1 << 2,
210*a61ed2ceSHans Rosenfeld ATR_F_VALID = 1 << 3
211*a61ed2ceSHans Rosenfeld } atr_flags_t;
212*a61ed2ceSHans Rosenfeld
213*a61ed2ceSHans Rosenfeld
214*a61ed2ceSHans Rosenfeld struct atr_data {
215*a61ed2ceSHans Rosenfeld atr_flags_t atr_flags;
216*a61ed2ceSHans Rosenfeld uint8_t atr_nti;
217*a61ed2ceSHans Rosenfeld atr_ti_t atr_ti[ATR_TI_MAX];
218*a61ed2ceSHans Rosenfeld uint8_t atr_nhistoric;
219*a61ed2ceSHans Rosenfeld uint8_t atr_historic[ATR_HISTORICAL_MAX];
220*a61ed2ceSHans Rosenfeld uint8_t atr_cksum;
221*a61ed2ceSHans Rosenfeld uint8_t atr_raw[ATR_LEN_MAX];
222*a61ed2ceSHans Rosenfeld uint8_t atr_nraw;
223*a61ed2ceSHans Rosenfeld };
224*a61ed2ceSHans Rosenfeld
225*a61ed2ceSHans Rosenfeld /*
226*a61ed2ceSHans Rosenfeld * These tables maps the bit values for Fi from 7816-3:2006 section 8.3 Table 7.
227*a61ed2ceSHans Rosenfeld */
228*a61ed2ceSHans Rosenfeld static uint_t atr_fi_valtable[16] = {
229*a61ed2ceSHans Rosenfeld 372, /* 0000 */
230*a61ed2ceSHans Rosenfeld 372, /* 0001 */
231*a61ed2ceSHans Rosenfeld 558, /* 0010 */
232*a61ed2ceSHans Rosenfeld 744, /* 0011 */
233*a61ed2ceSHans Rosenfeld 1116, /* 0100 */
234*a61ed2ceSHans Rosenfeld 1488, /* 0101 */
235*a61ed2ceSHans Rosenfeld 1860, /* 0110 */
236*a61ed2ceSHans Rosenfeld 0, /* 0111 */
237*a61ed2ceSHans Rosenfeld 0, /* 1000 */
238*a61ed2ceSHans Rosenfeld 512, /* 1001 */
239*a61ed2ceSHans Rosenfeld 768, /* 1010 */
240*a61ed2ceSHans Rosenfeld 1024, /* 1011 */
241*a61ed2ceSHans Rosenfeld 1536, /* 1100 */
242*a61ed2ceSHans Rosenfeld 2048, /* 1101 */
243*a61ed2ceSHans Rosenfeld 0, /* 1110 */
244*a61ed2ceSHans Rosenfeld 0 /* 1111 */
245*a61ed2ceSHans Rosenfeld };
246*a61ed2ceSHans Rosenfeld
247*a61ed2ceSHans Rosenfeld static const char *atr_fi_table[16] = {
248*a61ed2ceSHans Rosenfeld "372", /* 0000 */
249*a61ed2ceSHans Rosenfeld "372", /* 0001 */
250*a61ed2ceSHans Rosenfeld "558", /* 0010 */
251*a61ed2ceSHans Rosenfeld "744", /* 0011 */
252*a61ed2ceSHans Rosenfeld "1116", /* 0100 */
253*a61ed2ceSHans Rosenfeld "1488", /* 0101 */
254*a61ed2ceSHans Rosenfeld "1860", /* 0110 */
255*a61ed2ceSHans Rosenfeld "RFU", /* 0111 */
256*a61ed2ceSHans Rosenfeld "RFU", /* 1000 */
257*a61ed2ceSHans Rosenfeld "512", /* 1001 */
258*a61ed2ceSHans Rosenfeld "768", /* 1010 */
259*a61ed2ceSHans Rosenfeld "1024", /* 1011 */
260*a61ed2ceSHans Rosenfeld "1536", /* 1100 */
261*a61ed2ceSHans Rosenfeld "2048", /* 1101 */
262*a61ed2ceSHans Rosenfeld "RFU", /* 1110 */
263*a61ed2ceSHans Rosenfeld "RFU", /* 1111 */
264*a61ed2ceSHans Rosenfeld };
265*a61ed2ceSHans Rosenfeld
266*a61ed2ceSHans Rosenfeld /*
267*a61ed2ceSHans Rosenfeld * This table maps the bit values for f(max) from 7816-3:2006 section 8.3
268*a61ed2ceSHans Rosenfeld * Table 7.
269*a61ed2ceSHans Rosenfeld */
270*a61ed2ceSHans Rosenfeld static const char *atr_fmax_table[16] = {
271*a61ed2ceSHans Rosenfeld "4", /* 0000 */
272*a61ed2ceSHans Rosenfeld "5", /* 0001 */
273*a61ed2ceSHans Rosenfeld "6", /* 0010 */
274*a61ed2ceSHans Rosenfeld "8", /* 0011 */
275*a61ed2ceSHans Rosenfeld "12", /* 0100 */
276*a61ed2ceSHans Rosenfeld "16", /* 0101 */
277*a61ed2ceSHans Rosenfeld "20", /* 0110 */
278*a61ed2ceSHans Rosenfeld "-", /* 0111 */
279*a61ed2ceSHans Rosenfeld "-", /* 1000 */
280*a61ed2ceSHans Rosenfeld "5", /* 1001 */
281*a61ed2ceSHans Rosenfeld "7.5", /* 1010 */
282*a61ed2ceSHans Rosenfeld "10", /* 1011 */
283*a61ed2ceSHans Rosenfeld "15", /* 1100 */
284*a61ed2ceSHans Rosenfeld "20", /* 1101 */
285*a61ed2ceSHans Rosenfeld "-", /* 1110 */
286*a61ed2ceSHans Rosenfeld "-", /* 1111 */
287*a61ed2ceSHans Rosenfeld };
288*a61ed2ceSHans Rosenfeld
289*a61ed2ceSHans Rosenfeld /*
290*a61ed2ceSHans Rosenfeld * This table maps the bit values for Di from 7816-3:2006 section 8.3 Table 8.
291*a61ed2ceSHans Rosenfeld */
292*a61ed2ceSHans Rosenfeld static uint_t atr_di_valtable[16] = {
293*a61ed2ceSHans Rosenfeld 0, /* 0000 */
294*a61ed2ceSHans Rosenfeld 1, /* 0001 */
295*a61ed2ceSHans Rosenfeld 2, /* 0010 */
296*a61ed2ceSHans Rosenfeld 4, /* 0011 */
297*a61ed2ceSHans Rosenfeld 8, /* 0100 */
298*a61ed2ceSHans Rosenfeld 16, /* 0101 */
299*a61ed2ceSHans Rosenfeld 32, /* 0110 */
300*a61ed2ceSHans Rosenfeld 64, /* 0111 */
301*a61ed2ceSHans Rosenfeld 12, /* 1000 */
302*a61ed2ceSHans Rosenfeld 20, /* 1001 */
303*a61ed2ceSHans Rosenfeld 0, /* 1010 */
304*a61ed2ceSHans Rosenfeld 0, /* 1011 */
305*a61ed2ceSHans Rosenfeld 0, /* 1100 */
306*a61ed2ceSHans Rosenfeld 0, /* 1101 */
307*a61ed2ceSHans Rosenfeld 0, /* 1110 */
308*a61ed2ceSHans Rosenfeld 0 /* 1111 */
309*a61ed2ceSHans Rosenfeld };
310*a61ed2ceSHans Rosenfeld
311*a61ed2ceSHans Rosenfeld static const char *atr_di_table[16] = {
312*a61ed2ceSHans Rosenfeld "RFU", /* 0000 */
313*a61ed2ceSHans Rosenfeld "1", /* 0001 */
314*a61ed2ceSHans Rosenfeld "2", /* 0010 */
315*a61ed2ceSHans Rosenfeld "4", /* 0011 */
316*a61ed2ceSHans Rosenfeld "8", /* 0100 */
317*a61ed2ceSHans Rosenfeld "16", /* 0101 */
318*a61ed2ceSHans Rosenfeld "32", /* 0110 */
319*a61ed2ceSHans Rosenfeld "64", /* 0111 */
320*a61ed2ceSHans Rosenfeld "12", /* 1000 */
321*a61ed2ceSHans Rosenfeld "20", /* 1001 */
322*a61ed2ceSHans Rosenfeld "RFU", /* 1010 */
323*a61ed2ceSHans Rosenfeld "RFU", /* 1011 */
324*a61ed2ceSHans Rosenfeld "RFU", /* 1100 */
325*a61ed2ceSHans Rosenfeld "RFU", /* 1101 */
326*a61ed2ceSHans Rosenfeld "RFU", /* 1110 */
327*a61ed2ceSHans Rosenfeld "RFU", /* 1111 */
328*a61ed2ceSHans Rosenfeld };
329*a61ed2ceSHans Rosenfeld
330*a61ed2ceSHans Rosenfeld /*
331*a61ed2ceSHans Rosenfeld * This table maps the bit values for the clock stop indicator from 7816-3:2006
332*a61ed2ceSHans Rosenfeld * section 8.3 Table 9.
333*a61ed2ceSHans Rosenfeld */
334*a61ed2ceSHans Rosenfeld static const char *atr_clock_table[4] = {
335*a61ed2ceSHans Rosenfeld "disallowed", /* 00 */
336*a61ed2ceSHans Rosenfeld "signal low", /* 01 */
337*a61ed2ceSHans Rosenfeld "signal high", /* 10 */
338*a61ed2ceSHans Rosenfeld "signal low or high" /* 11 */
339*a61ed2ceSHans Rosenfeld };
340*a61ed2ceSHans Rosenfeld
341*a61ed2ceSHans Rosenfeld uint_t
atr_fi_index_to_value(uint8_t val)342*a61ed2ceSHans Rosenfeld atr_fi_index_to_value(uint8_t val)
343*a61ed2ceSHans Rosenfeld {
344*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_fi_valtable)) {
345*a61ed2ceSHans Rosenfeld return (0);
346*a61ed2ceSHans Rosenfeld }
347*a61ed2ceSHans Rosenfeld
348*a61ed2ceSHans Rosenfeld return (atr_fi_valtable[val]);
349*a61ed2ceSHans Rosenfeld }
350*a61ed2ceSHans Rosenfeld
351*a61ed2ceSHans Rosenfeld const char *
atr_fi_index_to_string(uint8_t val)352*a61ed2ceSHans Rosenfeld atr_fi_index_to_string(uint8_t val)
353*a61ed2ceSHans Rosenfeld {
354*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_fi_table)) {
355*a61ed2ceSHans Rosenfeld return ("<invalid>");
356*a61ed2ceSHans Rosenfeld }
357*a61ed2ceSHans Rosenfeld
358*a61ed2ceSHans Rosenfeld return (atr_fi_table[val]);
359*a61ed2ceSHans Rosenfeld }
360*a61ed2ceSHans Rosenfeld
361*a61ed2ceSHans Rosenfeld const char *
atr_fmax_index_to_string(uint8_t val)362*a61ed2ceSHans Rosenfeld atr_fmax_index_to_string(uint8_t val)
363*a61ed2ceSHans Rosenfeld {
364*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_fmax_table)) {
365*a61ed2ceSHans Rosenfeld return ("<invalid>");
366*a61ed2ceSHans Rosenfeld }
367*a61ed2ceSHans Rosenfeld
368*a61ed2ceSHans Rosenfeld return (atr_fmax_table[val]);
369*a61ed2ceSHans Rosenfeld }
370*a61ed2ceSHans Rosenfeld
371*a61ed2ceSHans Rosenfeld uint_t
atr_di_index_to_value(uint8_t val)372*a61ed2ceSHans Rosenfeld atr_di_index_to_value(uint8_t val)
373*a61ed2ceSHans Rosenfeld {
374*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_di_valtable)) {
375*a61ed2ceSHans Rosenfeld return (0);
376*a61ed2ceSHans Rosenfeld }
377*a61ed2ceSHans Rosenfeld
378*a61ed2ceSHans Rosenfeld return (atr_di_valtable[val]);
379*a61ed2ceSHans Rosenfeld }
380*a61ed2ceSHans Rosenfeld const char *
atr_di_index_to_string(uint8_t val)381*a61ed2ceSHans Rosenfeld atr_di_index_to_string(uint8_t val)
382*a61ed2ceSHans Rosenfeld {
383*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_di_table)) {
384*a61ed2ceSHans Rosenfeld return ("<invalid>");
385*a61ed2ceSHans Rosenfeld }
386*a61ed2ceSHans Rosenfeld
387*a61ed2ceSHans Rosenfeld return (atr_di_table[val]);
388*a61ed2ceSHans Rosenfeld }
389*a61ed2ceSHans Rosenfeld
390*a61ed2ceSHans Rosenfeld const char *
atr_clock_stop_to_string(atr_clock_stop_t val)391*a61ed2ceSHans Rosenfeld atr_clock_stop_to_string(atr_clock_stop_t val)
392*a61ed2ceSHans Rosenfeld {
393*a61ed2ceSHans Rosenfeld if (val >= ARRAY_SIZE(atr_clock_table)) {
394*a61ed2ceSHans Rosenfeld return ("<invalid>");
395*a61ed2ceSHans Rosenfeld }
396*a61ed2ceSHans Rosenfeld
397*a61ed2ceSHans Rosenfeld return (atr_clock_table[val]);
398*a61ed2ceSHans Rosenfeld }
399*a61ed2ceSHans Rosenfeld
400*a61ed2ceSHans Rosenfeld const char *
atr_protocol_to_string(atr_protocol_t prot)401*a61ed2ceSHans Rosenfeld atr_protocol_to_string(atr_protocol_t prot)
402*a61ed2ceSHans Rosenfeld {
403*a61ed2ceSHans Rosenfeld if (prot == ATR_P_NONE) {
404*a61ed2ceSHans Rosenfeld return ("none");
405*a61ed2ceSHans Rosenfeld }
406*a61ed2ceSHans Rosenfeld
407*a61ed2ceSHans Rosenfeld if ((prot & ATR_P_T0) == ATR_P_T0) {
408*a61ed2ceSHans Rosenfeld return ("T=0");
409*a61ed2ceSHans Rosenfeld } else if ((prot & ATR_P_T1) == ATR_P_T1) {
410*a61ed2ceSHans Rosenfeld return ("T=1");
411*a61ed2ceSHans Rosenfeld } else {
412*a61ed2ceSHans Rosenfeld return ("T=0, T=1");
413*a61ed2ceSHans Rosenfeld }
414*a61ed2ceSHans Rosenfeld }
415*a61ed2ceSHans Rosenfeld
416*a61ed2ceSHans Rosenfeld const char *
atr_convention_to_string(atr_convention_t conv)417*a61ed2ceSHans Rosenfeld atr_convention_to_string(atr_convention_t conv)
418*a61ed2ceSHans Rosenfeld {
419*a61ed2ceSHans Rosenfeld if (conv == ATR_CONVENTION_DIRECT) {
420*a61ed2ceSHans Rosenfeld return ("direct");
421*a61ed2ceSHans Rosenfeld } else if (conv == ATR_CONVENTION_INVERSE) {
422*a61ed2ceSHans Rosenfeld return ("inverse");
423*a61ed2ceSHans Rosenfeld } else {
424*a61ed2ceSHans Rosenfeld return ("<invalid convention>");
425*a61ed2ceSHans Rosenfeld }
426*a61ed2ceSHans Rosenfeld }
427*a61ed2ceSHans Rosenfeld
428*a61ed2ceSHans Rosenfeld const char *
atr_strerror(atr_parsecode_t code)429*a61ed2ceSHans Rosenfeld atr_strerror(atr_parsecode_t code)
430*a61ed2ceSHans Rosenfeld {
431*a61ed2ceSHans Rosenfeld switch (code) {
432*a61ed2ceSHans Rosenfeld case ATR_CODE_OK:
433*a61ed2ceSHans Rosenfeld return ("ATR parsed successfully");
434*a61ed2ceSHans Rosenfeld case ATR_CODE_TOO_SHORT:
435*a61ed2ceSHans Rosenfeld return ("Specified buffer too short");
436*a61ed2ceSHans Rosenfeld case ATR_CODE_TOO_LONG:
437*a61ed2ceSHans Rosenfeld return ("Specified buffer too long");
438*a61ed2ceSHans Rosenfeld case ATR_CODE_INVALID_TS:
439*a61ed2ceSHans Rosenfeld return ("ATR has invalid TS byte value");
440*a61ed2ceSHans Rosenfeld case ATR_CODE_OVERRUN:
441*a61ed2ceSHans Rosenfeld return ("ATR data requires more bytes than provided");
442*a61ed2ceSHans Rosenfeld case ATR_CODE_UNDERRUN:
443*a61ed2ceSHans Rosenfeld return ("ATR data did not use all provided bytes");
444*a61ed2ceSHans Rosenfeld case ATR_CODE_CHECKSUM_ERROR:
445*a61ed2ceSHans Rosenfeld return ("ATR data did not checksum correctly");
446*a61ed2ceSHans Rosenfeld case ATR_CODE_INVALID_TD1:
447*a61ed2ceSHans Rosenfeld return ("ATR data has invalid protocol in TD1");
448*a61ed2ceSHans Rosenfeld default:
449*a61ed2ceSHans Rosenfeld return ("Unknown Parse Code");
450*a61ed2ceSHans Rosenfeld }
451*a61ed2ceSHans Rosenfeld }
452*a61ed2ceSHans Rosenfeld
453*a61ed2ceSHans Rosenfeld static uint_t
atr_count_cbits(uint8_t x)454*a61ed2ceSHans Rosenfeld atr_count_cbits(uint8_t x)
455*a61ed2ceSHans Rosenfeld {
456*a61ed2ceSHans Rosenfeld uint_t ret = 0;
457*a61ed2ceSHans Rosenfeld
458*a61ed2ceSHans Rosenfeld if (x & ATR_TA_MASK)
459*a61ed2ceSHans Rosenfeld ret++;
460*a61ed2ceSHans Rosenfeld if (x & ATR_TB_MASK)
461*a61ed2ceSHans Rosenfeld ret++;
462*a61ed2ceSHans Rosenfeld if (x & ATR_TC_MASK)
463*a61ed2ceSHans Rosenfeld ret++;
464*a61ed2ceSHans Rosenfeld if (x & ATR_TD_MASK)
465*a61ed2ceSHans Rosenfeld ret++;
466*a61ed2ceSHans Rosenfeld return (ret);
467*a61ed2ceSHans Rosenfeld }
468*a61ed2ceSHans Rosenfeld
469*a61ed2ceSHans Rosenfeld /*
470*a61ed2ceSHans Rosenfeld * Parse out ATR values. Focus on only parsing it and not interpreting it.
471*a61ed2ceSHans Rosenfeld * Interpretation should be done in other functions that can walk over the data
472*a61ed2ceSHans Rosenfeld * and be more protocol-aware.
473*a61ed2ceSHans Rosenfeld */
474*a61ed2ceSHans Rosenfeld atr_parsecode_t
atr_parse(const uint8_t * buf,size_t len,atr_data_t * data)475*a61ed2ceSHans Rosenfeld atr_parse(const uint8_t *buf, size_t len, atr_data_t *data)
476*a61ed2ceSHans Rosenfeld {
477*a61ed2ceSHans Rosenfeld uint_t nhist, cbits, ncbits, idx, Ti, prot;
478*a61ed2ceSHans Rosenfeld uint_t ncksum = 0;
479*a61ed2ceSHans Rosenfeld atr_ti_t *atp;
480*a61ed2ceSHans Rosenfeld
481*a61ed2ceSHans Rosenfeld /*
482*a61ed2ceSHans Rosenfeld * Zero out data in case someone's come back around for another loop on
483*a61ed2ceSHans Rosenfeld * the same data.
484*a61ed2ceSHans Rosenfeld */
485*a61ed2ceSHans Rosenfeld bzero(data, sizeof (atr_data_t));
486*a61ed2ceSHans Rosenfeld
487*a61ed2ceSHans Rosenfeld if (len < ATR_LEN_MIN) {
488*a61ed2ceSHans Rosenfeld return (ATR_CODE_TOO_SHORT);
489*a61ed2ceSHans Rosenfeld }
490*a61ed2ceSHans Rosenfeld
491*a61ed2ceSHans Rosenfeld if (len > ATR_LEN_MAX) {
492*a61ed2ceSHans Rosenfeld return (ATR_CODE_TOO_LONG);
493*a61ed2ceSHans Rosenfeld }
494*a61ed2ceSHans Rosenfeld
495*a61ed2ceSHans Rosenfeld if (buf[ATR_TS_IDX] != ATR_TS_INVERSE &&
496*a61ed2ceSHans Rosenfeld buf[ATR_TS_IDX] != ATR_TS_DIRECT) {
497*a61ed2ceSHans Rosenfeld return (ATR_CODE_INVALID_TS);
498*a61ed2ceSHans Rosenfeld }
499*a61ed2ceSHans Rosenfeld
500*a61ed2ceSHans Rosenfeld bcopy(buf, data->atr_raw, len);
501*a61ed2ceSHans Rosenfeld data->atr_nraw = len;
502*a61ed2ceSHans Rosenfeld
503*a61ed2ceSHans Rosenfeld if (buf[ATR_TS_IDX] == ATR_TS_DIRECT) {
504*a61ed2ceSHans Rosenfeld data->atr_flags |= ATR_F_USES_DIRECT;
505*a61ed2ceSHans Rosenfeld } else {
506*a61ed2ceSHans Rosenfeld data->atr_flags |= ATR_F_USES_INVERSE;
507*a61ed2ceSHans Rosenfeld }
508*a61ed2ceSHans Rosenfeld
509*a61ed2ceSHans Rosenfeld /*
510*a61ed2ceSHans Rosenfeld * The protocol of T0 is the number of historical bits present.
511*a61ed2ceSHans Rosenfeld */
512*a61ed2ceSHans Rosenfeld nhist = ATR_TD_PROT(buf[ATR_T0_IDX]);
513*a61ed2ceSHans Rosenfeld cbits = ATR_TD_NBITS(buf[ATR_T0_IDX]);
514*a61ed2ceSHans Rosenfeld idx = ATR_T0_IDX + 1;
515*a61ed2ceSHans Rosenfeld ncbits = atr_count_cbits(cbits);
516*a61ed2ceSHans Rosenfeld
517*a61ed2ceSHans Rosenfeld /*
518*a61ed2ceSHans Rosenfeld * Ti is used to track the current iteration of T[A,B,C,D] that we are
519*a61ed2ceSHans Rosenfeld * on, as the ISO/IEC standard suggests. The way that values are
520*a61ed2ceSHans Rosenfeld * interpreted depends on the value of Ti.
521*a61ed2ceSHans Rosenfeld *
522*a61ed2ceSHans Rosenfeld * When Ti is one, TA, TB, and TC represent global properties. TD's
523*a61ed2ceSHans Rosenfeld * protocol represents the preferred protocol.
524*a61ed2ceSHans Rosenfeld *
525*a61ed2ceSHans Rosenfeld * When Ti is two, TA, TB, and TC also represent global properties.
526*a61ed2ceSHans Rosenfeld * However, TC only has meaning if the protocol is T=0.
527*a61ed2ceSHans Rosenfeld *
528*a61ed2ceSHans Rosenfeld * When Ti is 15, it indicates more global properties.
529*a61ed2ceSHans Rosenfeld *
530*a61ed2ceSHans Rosenfeld * For all other values of Ti, the meaning depends on the protocol in
531*a61ed2ceSHans Rosenfeld * question and they are all properties specific to that protocol.
532*a61ed2ceSHans Rosenfeld */
533*a61ed2ceSHans Rosenfeld Ti = 1;
534*a61ed2ceSHans Rosenfeld /*
535*a61ed2ceSHans Rosenfeld * Initialize prot to an invalid protocol to help us deal with the
536*a61ed2ceSHans Rosenfeld * normal workflow and make sure that we don't mistakenly do anything.
537*a61ed2ceSHans Rosenfeld */
538*a61ed2ceSHans Rosenfeld prot = UINT32_MAX;
539*a61ed2ceSHans Rosenfeld for (;;) {
540*a61ed2ceSHans Rosenfeld atp = &data->atr_ti[data->atr_nti];
541*a61ed2ceSHans Rosenfeld data->atr_nti++;
542*a61ed2ceSHans Rosenfeld ASSERT3U(data->atr_nti, <=, ATR_TI_MAX);
543*a61ed2ceSHans Rosenfeld
544*a61ed2ceSHans Rosenfeld /*
545*a61ed2ceSHans Rosenfeld * Make sure that we have enough space to read all the cbits.
546*a61ed2ceSHans Rosenfeld * idx points to the first cbit, which could also potentially be
547*a61ed2ceSHans Rosenfeld * over the length of the buffer. This is why we subtract one
548*a61ed2ceSHans Rosenfeld * from idx when doing the calculation.
549*a61ed2ceSHans Rosenfeld */
550*a61ed2ceSHans Rosenfeld if (idx - 1 + ncbits >= len) {
551*a61ed2ceSHans Rosenfeld return (ATR_CODE_OVERRUN);
552*a61ed2ceSHans Rosenfeld }
553*a61ed2ceSHans Rosenfeld
554*a61ed2ceSHans Rosenfeld ASSERT3U(Ti, !=, 0);
555*a61ed2ceSHans Rosenfeld
556*a61ed2ceSHans Rosenfeld /*
557*a61ed2ceSHans Rosenfeld * At the moment we opt to ignore reserved protocols.
558*a61ed2ceSHans Rosenfeld */
559*a61ed2ceSHans Rosenfeld atp->atrti_protocol = prot;
560*a61ed2ceSHans Rosenfeld atp->atrti_ti_val = Ti;
561*a61ed2ceSHans Rosenfeld atp->atrti_td_idx = idx - 1;
562*a61ed2ceSHans Rosenfeld
563*a61ed2ceSHans Rosenfeld if (cbits & ATR_TA_MASK) {
564*a61ed2ceSHans Rosenfeld atp->atrti_flags |= ATR_TI_HAVE_TA;
565*a61ed2ceSHans Rosenfeld atp->atrti_ta = buf[idx];
566*a61ed2ceSHans Rosenfeld idx++;
567*a61ed2ceSHans Rosenfeld }
568*a61ed2ceSHans Rosenfeld
569*a61ed2ceSHans Rosenfeld if (cbits & ATR_TB_MASK) {
570*a61ed2ceSHans Rosenfeld atp->atrti_flags |= ATR_TI_HAVE_TB;
571*a61ed2ceSHans Rosenfeld atp->atrti_tb = buf[idx];
572*a61ed2ceSHans Rosenfeld idx++;
573*a61ed2ceSHans Rosenfeld }
574*a61ed2ceSHans Rosenfeld
575*a61ed2ceSHans Rosenfeld if (cbits & ATR_TC_MASK) {
576*a61ed2ceSHans Rosenfeld atp->atrti_flags |= ATR_TI_HAVE_TC;
577*a61ed2ceSHans Rosenfeld atp->atrti_tc = buf[idx];
578*a61ed2ceSHans Rosenfeld idx++;
579*a61ed2ceSHans Rosenfeld }
580*a61ed2ceSHans Rosenfeld
581*a61ed2ceSHans Rosenfeld if (cbits & ATR_TD_MASK) {
582*a61ed2ceSHans Rosenfeld atp->atrti_flags |= ATR_TI_HAVE_TD;
583*a61ed2ceSHans Rosenfeld atp->atrti_td = buf[idx];
584*a61ed2ceSHans Rosenfeld cbits = ATR_TD_NBITS(buf[idx]);
585*a61ed2ceSHans Rosenfeld prot = ATR_TD_PROT(buf[idx]);
586*a61ed2ceSHans Rosenfeld ncbits = atr_count_cbits(cbits);
587*a61ed2ceSHans Rosenfeld if (prot != 0)
588*a61ed2ceSHans Rosenfeld ncksum = 1;
589*a61ed2ceSHans Rosenfeld
590*a61ed2ceSHans Rosenfeld /*
591*a61ed2ceSHans Rosenfeld * T=15 is not allowed in TD1 per 8.2.3.
592*a61ed2ceSHans Rosenfeld */
593*a61ed2ceSHans Rosenfeld if (Ti == 1 && prot == 0xf)
594*a61ed2ceSHans Rosenfeld return (ATR_CODE_INVALID_TD1);
595*a61ed2ceSHans Rosenfeld
596*a61ed2ceSHans Rosenfeld idx++;
597*a61ed2ceSHans Rosenfeld /*
598*a61ed2ceSHans Rosenfeld * Encountering TD means that once we take the next loop
599*a61ed2ceSHans Rosenfeld * and we need to increment Ti.
600*a61ed2ceSHans Rosenfeld */
601*a61ed2ceSHans Rosenfeld Ti++;
602*a61ed2ceSHans Rosenfeld } else {
603*a61ed2ceSHans Rosenfeld break;
604*a61ed2ceSHans Rosenfeld }
605*a61ed2ceSHans Rosenfeld }
606*a61ed2ceSHans Rosenfeld
607*a61ed2ceSHans Rosenfeld /*
608*a61ed2ceSHans Rosenfeld * We've parsed all of the cbits. At this point, we should take into
609*a61ed2ceSHans Rosenfeld * account all of the historical bits and potentially the checksum.
610*a61ed2ceSHans Rosenfeld */
611*a61ed2ceSHans Rosenfeld if (idx - 1 + nhist + ncksum >= len) {
612*a61ed2ceSHans Rosenfeld return (ATR_CODE_OVERRUN);
613*a61ed2ceSHans Rosenfeld }
614*a61ed2ceSHans Rosenfeld
615*a61ed2ceSHans Rosenfeld if (idx + nhist + ncksum != len) {
616*a61ed2ceSHans Rosenfeld return (ATR_CODE_UNDERRUN);
617*a61ed2ceSHans Rosenfeld }
618*a61ed2ceSHans Rosenfeld
619*a61ed2ceSHans Rosenfeld if (nhist > 0) {
620*a61ed2ceSHans Rosenfeld data->atr_nhistoric = nhist;
621*a61ed2ceSHans Rosenfeld bcopy(&buf[idx], data->atr_historic, nhist);
622*a61ed2ceSHans Rosenfeld }
623*a61ed2ceSHans Rosenfeld
624*a61ed2ceSHans Rosenfeld if (ncksum > 0) {
625*a61ed2ceSHans Rosenfeld size_t i;
626*a61ed2ceSHans Rosenfeld uint8_t val;
627*a61ed2ceSHans Rosenfeld
628*a61ed2ceSHans Rosenfeld /*
629*a61ed2ceSHans Rosenfeld * Per ISO/IEC 7816-3:2006 Section 8.2.5 the checksum is all
630*a61ed2ceSHans Rosenfeld * bytes excluding TS. Therefore, we must start at byte 1.
631*a61ed2ceSHans Rosenfeld */
632*a61ed2ceSHans Rosenfeld for (val = 0, i = 1; i < len; i++) {
633*a61ed2ceSHans Rosenfeld val ^= buf[i];
634*a61ed2ceSHans Rosenfeld }
635*a61ed2ceSHans Rosenfeld
636*a61ed2ceSHans Rosenfeld if (val != ATR_CKSUM_TARGET) {
637*a61ed2ceSHans Rosenfeld return (ATR_CODE_CHECKSUM_ERROR);
638*a61ed2ceSHans Rosenfeld }
639*a61ed2ceSHans Rosenfeld data->atr_flags |= ATR_F_HAS_CHECKSUM;
640*a61ed2ceSHans Rosenfeld data->atr_cksum = buf[len - 1];
641*a61ed2ceSHans Rosenfeld }
642*a61ed2ceSHans Rosenfeld
643*a61ed2ceSHans Rosenfeld data->atr_flags |= ATR_F_VALID;
644*a61ed2ceSHans Rosenfeld return (ATR_CODE_OK);
645*a61ed2ceSHans Rosenfeld }
646*a61ed2ceSHans Rosenfeld
647*a61ed2ceSHans Rosenfeld uint8_t
atr_fi_default_index(void)648*a61ed2ceSHans Rosenfeld atr_fi_default_index(void)
649*a61ed2ceSHans Rosenfeld {
650*a61ed2ceSHans Rosenfeld return (ATR_FI_DEFAULT_INDEX);
651*a61ed2ceSHans Rosenfeld }
652*a61ed2ceSHans Rosenfeld
653*a61ed2ceSHans Rosenfeld uint8_t
atr_di_default_index(void)654*a61ed2ceSHans Rosenfeld atr_di_default_index(void)
655*a61ed2ceSHans Rosenfeld {
656*a61ed2ceSHans Rosenfeld return (ATR_DI_DEFAULT_INDEX);
657*a61ed2ceSHans Rosenfeld }
658*a61ed2ceSHans Rosenfeld
659*a61ed2ceSHans Rosenfeld /*
660*a61ed2ceSHans Rosenfeld * Parse the data to determine which protocols are supported in this atr data.
661*a61ed2ceSHans Rosenfeld * Based on this, users can come and ask us to fill in protocol information.
662*a61ed2ceSHans Rosenfeld */
663*a61ed2ceSHans Rosenfeld atr_protocol_t
atr_supported_protocols(atr_data_t * data)664*a61ed2ceSHans Rosenfeld atr_supported_protocols(atr_data_t *data)
665*a61ed2ceSHans Rosenfeld {
666*a61ed2ceSHans Rosenfeld uint_t i;
667*a61ed2ceSHans Rosenfeld atr_protocol_t prot;
668*a61ed2ceSHans Rosenfeld
669*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
670*a61ed2ceSHans Rosenfeld return (ATR_P_NONE);
671*a61ed2ceSHans Rosenfeld
672*a61ed2ceSHans Rosenfeld /*
673*a61ed2ceSHans Rosenfeld * Based on 8.2.3 of ISO/IEC 7816-3:2006, if TD1 is present, then that
674*a61ed2ceSHans Rosenfeld * indicates the first protocol. However, if it is not present, then
675*a61ed2ceSHans Rosenfeld * that implies that T=0 is the only supported protocol. Otherwise, all
676*a61ed2ceSHans Rosenfeld * protocols are referenced in ascending order. The first entry in
677*a61ed2ceSHans Rosenfeld * atr_ti refers to data from T0, so the protocol in the second entry
678*a61ed2ceSHans Rosenfeld * would have the TD1 data.
679*a61ed2ceSHans Rosenfeld */
680*a61ed2ceSHans Rosenfeld if (data->atr_nti < 2) {
681*a61ed2ceSHans Rosenfeld return (ATR_P_T0);
682*a61ed2ceSHans Rosenfeld }
683*a61ed2ceSHans Rosenfeld
684*a61ed2ceSHans Rosenfeld prot = ATR_P_NONE;
685*a61ed2ceSHans Rosenfeld for (i = 0; i < data->atr_nti; i++) {
686*a61ed2ceSHans Rosenfeld switch (data->atr_ti[i].atrti_protocol) {
687*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T0:
688*a61ed2ceSHans Rosenfeld prot |= ATR_P_T0;
689*a61ed2ceSHans Rosenfeld break;
690*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T1:
691*a61ed2ceSHans Rosenfeld prot |= ATR_P_T1;
692*a61ed2ceSHans Rosenfeld break;
693*a61ed2ceSHans Rosenfeld default:
694*a61ed2ceSHans Rosenfeld /*
695*a61ed2ceSHans Rosenfeld * T=15 is not a protocol, and all other protocol values
696*a61ed2ceSHans Rosenfeld * are currently reserved for future use.
697*a61ed2ceSHans Rosenfeld */
698*a61ed2ceSHans Rosenfeld continue;
699*a61ed2ceSHans Rosenfeld }
700*a61ed2ceSHans Rosenfeld }
701*a61ed2ceSHans Rosenfeld
702*a61ed2ceSHans Rosenfeld /*
703*a61ed2ceSHans Rosenfeld * It's possible we've found nothing specific in the above loop (for
704*a61ed2ceSHans Rosenfeld * example, only T=15 global bits were found). In that case, the card
705*a61ed2ceSHans Rosenfeld * defaults to T=0.
706*a61ed2ceSHans Rosenfeld */
707*a61ed2ceSHans Rosenfeld if (prot == ATR_P_NONE)
708*a61ed2ceSHans Rosenfeld prot = ATR_P_T0;
709*a61ed2ceSHans Rosenfeld
710*a61ed2ceSHans Rosenfeld return (prot);
711*a61ed2ceSHans Rosenfeld }
712*a61ed2ceSHans Rosenfeld
713*a61ed2ceSHans Rosenfeld boolean_t
atr_params_negotiable(atr_data_t * data)714*a61ed2ceSHans Rosenfeld atr_params_negotiable(atr_data_t *data)
715*a61ed2ceSHans Rosenfeld {
716*a61ed2ceSHans Rosenfeld /* If for some reason we're called with invalid data, assume it's not */
717*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
718*a61ed2ceSHans Rosenfeld return (B_FALSE);
719*a61ed2ceSHans Rosenfeld
720*a61ed2ceSHans Rosenfeld
721*a61ed2ceSHans Rosenfeld /*
722*a61ed2ceSHans Rosenfeld * Whether or not we're negotiable is in the second global page, so atr
723*a61ed2ceSHans Rosenfeld * index 1. If TA2 is missing, then the card always is negotiable.
724*a61ed2ceSHans Rosenfeld */
725*a61ed2ceSHans Rosenfeld if (data->atr_nti < 2 ||
726*a61ed2ceSHans Rosenfeld (data->atr_ti[1].atrti_flags & ATR_TI_HAVE_TA) == 0) {
727*a61ed2ceSHans Rosenfeld return (B_TRUE);
728*a61ed2ceSHans Rosenfeld }
729*a61ed2ceSHans Rosenfeld
730*a61ed2ceSHans Rosenfeld if (ATR_TA2_CANCHANGE(data->atr_ti[1].atrti_ta)) {
731*a61ed2ceSHans Rosenfeld return (B_TRUE);
732*a61ed2ceSHans Rosenfeld }
733*a61ed2ceSHans Rosenfeld
734*a61ed2ceSHans Rosenfeld return (B_FALSE);
735*a61ed2ceSHans Rosenfeld }
736*a61ed2ceSHans Rosenfeld
737*a61ed2ceSHans Rosenfeld atr_protocol_t
atr_default_protocol(atr_data_t * data)738*a61ed2ceSHans Rosenfeld atr_default_protocol(atr_data_t *data)
739*a61ed2ceSHans Rosenfeld {
740*a61ed2ceSHans Rosenfeld uint8_t prot;
741*a61ed2ceSHans Rosenfeld
742*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
743*a61ed2ceSHans Rosenfeld return (ATR_P_NONE);
744*a61ed2ceSHans Rosenfeld /*
745*a61ed2ceSHans Rosenfeld * If we don't have an TA2 byte, then the system defaults to T=0.
746*a61ed2ceSHans Rosenfeld */
747*a61ed2ceSHans Rosenfeld if (data->atr_nti < 2) {
748*a61ed2ceSHans Rosenfeld return (ATR_P_T0);
749*a61ed2ceSHans Rosenfeld }
750*a61ed2ceSHans Rosenfeld
751*a61ed2ceSHans Rosenfeld /*
752*a61ed2ceSHans Rosenfeld * If TA2 is present, then it encodes the default protocol. Otherwise,
753*a61ed2ceSHans Rosenfeld * we have to grab the protocol value from TD1, which is called the
754*a61ed2ceSHans Rosenfeld * 'first offered protocol'.
755*a61ed2ceSHans Rosenfeld */
756*a61ed2ceSHans Rosenfeld if ((data->atr_ti[1].atrti_flags & ATR_TI_HAVE_TA) != 0) {
757*a61ed2ceSHans Rosenfeld prot = ATR_TA2_PROTOCOL(data->atr_ti[1].atrti_ta);
758*a61ed2ceSHans Rosenfeld } else {
759*a61ed2ceSHans Rosenfeld prot = data->atr_ti[1].atrti_protocol;
760*a61ed2ceSHans Rosenfeld }
761*a61ed2ceSHans Rosenfeld
762*a61ed2ceSHans Rosenfeld switch (prot) {
763*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T0:
764*a61ed2ceSHans Rosenfeld return (ATR_P_T0);
765*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T1:
766*a61ed2ceSHans Rosenfeld return (ATR_P_T1);
767*a61ed2ceSHans Rosenfeld default:
768*a61ed2ceSHans Rosenfeld return (ATR_P_NONE);
769*a61ed2ceSHans Rosenfeld }
770*a61ed2ceSHans Rosenfeld }
771*a61ed2ceSHans Rosenfeld
772*a61ed2ceSHans Rosenfeld uint8_t
atr_fi_index(atr_data_t * data)773*a61ed2ceSHans Rosenfeld atr_fi_index(atr_data_t *data)
774*a61ed2ceSHans Rosenfeld {
775*a61ed2ceSHans Rosenfeld if (data->atr_nti < 1) {
776*a61ed2ceSHans Rosenfeld return (ATR_FI_DEFAULT_INDEX);
777*a61ed2ceSHans Rosenfeld }
778*a61ed2ceSHans Rosenfeld
779*a61ed2ceSHans Rosenfeld /*
780*a61ed2ceSHans Rosenfeld * If TA is specified, it is present in TA1. TA2 may override its
781*a61ed2ceSHans Rosenfeld * presence, so if it is here, check that first to determine whether or
782*a61ed2ceSHans Rosenfeld * not we should check TA1.
783*a61ed2ceSHans Rosenfeld */
784*a61ed2ceSHans Rosenfeld if (data->atr_nti >= 2 &&
785*a61ed2ceSHans Rosenfeld (data->atr_ti[1].atrti_flags & ATR_TI_HAVE_TA) != 0) {
786*a61ed2ceSHans Rosenfeld if (!ATR_TA2_HONORTA1(data->atr_ti[1].atrti_ta)) {
787*a61ed2ceSHans Rosenfeld return (ATR_FI_DEFAULT_INDEX);
788*a61ed2ceSHans Rosenfeld }
789*a61ed2ceSHans Rosenfeld }
790*a61ed2ceSHans Rosenfeld
791*a61ed2ceSHans Rosenfeld if ((data->atr_ti[0].atrti_flags & ATR_TI_HAVE_TA) != 0) {
792*a61ed2ceSHans Rosenfeld return (ATR_TA1_FTABLE(data->atr_ti[0].atrti_ta));
793*a61ed2ceSHans Rosenfeld }
794*a61ed2ceSHans Rosenfeld
795*a61ed2ceSHans Rosenfeld return (ATR_FI_DEFAULT_INDEX);
796*a61ed2ceSHans Rosenfeld }
797*a61ed2ceSHans Rosenfeld
798*a61ed2ceSHans Rosenfeld uint8_t
atr_di_index(atr_data_t * data)799*a61ed2ceSHans Rosenfeld atr_di_index(atr_data_t *data)
800*a61ed2ceSHans Rosenfeld {
801*a61ed2ceSHans Rosenfeld if (data->atr_nti < 1) {
802*a61ed2ceSHans Rosenfeld return (ATR_DI_DEFAULT_INDEX);
803*a61ed2ceSHans Rosenfeld }
804*a61ed2ceSHans Rosenfeld
805*a61ed2ceSHans Rosenfeld /*
806*a61ed2ceSHans Rosenfeld * If TA is specified, it is present in TA1. TA2 may override its
807*a61ed2ceSHans Rosenfeld * presence, so if it is here, check that first to determine whether or
808*a61ed2ceSHans Rosenfeld * not we should check TA1.
809*a61ed2ceSHans Rosenfeld */
810*a61ed2ceSHans Rosenfeld if (data->atr_nti >= 2 &&
811*a61ed2ceSHans Rosenfeld (data->atr_ti[1].atrti_flags & ATR_TI_HAVE_TA) != 0) {
812*a61ed2ceSHans Rosenfeld if (!ATR_TA2_HONORTA1(data->atr_ti[1].atrti_ta)) {
813*a61ed2ceSHans Rosenfeld return (ATR_DI_DEFAULT_INDEX);
814*a61ed2ceSHans Rosenfeld }
815*a61ed2ceSHans Rosenfeld }
816*a61ed2ceSHans Rosenfeld
817*a61ed2ceSHans Rosenfeld if ((data->atr_ti[0].atrti_flags & ATR_TI_HAVE_TA) != 0) {
818*a61ed2ceSHans Rosenfeld return (ATR_TA1_DITABLE(data->atr_ti[0].atrti_ta));
819*a61ed2ceSHans Rosenfeld }
820*a61ed2ceSHans Rosenfeld
821*a61ed2ceSHans Rosenfeld return (ATR_DI_DEFAULT_INDEX);
822*a61ed2ceSHans Rosenfeld }
823*a61ed2ceSHans Rosenfeld
824*a61ed2ceSHans Rosenfeld atr_convention_t
atr_convention(atr_data_t * data)825*a61ed2ceSHans Rosenfeld atr_convention(atr_data_t *data)
826*a61ed2ceSHans Rosenfeld {
827*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_USES_DIRECT) != 0) {
828*a61ed2ceSHans Rosenfeld return (ATR_CONVENTION_DIRECT);
829*a61ed2ceSHans Rosenfeld }
830*a61ed2ceSHans Rosenfeld return (ATR_CONVENTION_INVERSE);
831*a61ed2ceSHans Rosenfeld }
832*a61ed2ceSHans Rosenfeld
833*a61ed2ceSHans Rosenfeld uint8_t
atr_extra_guardtime(atr_data_t * data)834*a61ed2ceSHans Rosenfeld atr_extra_guardtime(atr_data_t *data)
835*a61ed2ceSHans Rosenfeld {
836*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
837*a61ed2ceSHans Rosenfeld return (ATR_EXTRA_GUARDTIME_DEFAULT);
838*a61ed2ceSHans Rosenfeld
839*a61ed2ceSHans Rosenfeld if (data->atr_nti >= 1 &&
840*a61ed2ceSHans Rosenfeld (data->atr_ti[0].atrti_flags & ATR_TI_HAVE_TC) != 0) {
841*a61ed2ceSHans Rosenfeld return (data->atr_ti[0].atrti_tc);
842*a61ed2ceSHans Rosenfeld }
843*a61ed2ceSHans Rosenfeld
844*a61ed2ceSHans Rosenfeld return (ATR_EXTRA_GUARDTIME_DEFAULT);
845*a61ed2ceSHans Rosenfeld }
846*a61ed2ceSHans Rosenfeld
847*a61ed2ceSHans Rosenfeld uint8_t
atr_t0_wi(atr_data_t * data)848*a61ed2ceSHans Rosenfeld atr_t0_wi(atr_data_t *data)
849*a61ed2ceSHans Rosenfeld {
850*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
851*a61ed2ceSHans Rosenfeld return (ATR_T0_WI_DEFAULT);
852*a61ed2ceSHans Rosenfeld
853*a61ed2ceSHans Rosenfeld /*
854*a61ed2ceSHans Rosenfeld * This is stored in the optional global byte in TC2; however, it only
855*a61ed2ceSHans Rosenfeld * applies to T=0.
856*a61ed2ceSHans Rosenfeld */
857*a61ed2ceSHans Rosenfeld if (data->atr_nti >= 2 &&
858*a61ed2ceSHans Rosenfeld data->atr_ti[1].atrti_protocol == ATR_PROTOCOL_T0 &&
859*a61ed2ceSHans Rosenfeld (data->atr_ti[1].atrti_flags & ATR_TI_HAVE_TC) != 0) {
860*a61ed2ceSHans Rosenfeld return (data->atr_ti[1].atrti_tc);
861*a61ed2ceSHans Rosenfeld }
862*a61ed2ceSHans Rosenfeld
863*a61ed2ceSHans Rosenfeld return (ATR_T0_WI_DEFAULT);
864*a61ed2ceSHans Rosenfeld }
865*a61ed2ceSHans Rosenfeld
866*a61ed2ceSHans Rosenfeld uint8_t
atr_t1_cwi(atr_data_t * data)867*a61ed2ceSHans Rosenfeld atr_t1_cwi(atr_data_t *data)
868*a61ed2ceSHans Rosenfeld {
869*a61ed2ceSHans Rosenfeld uint8_t i;
870*a61ed2ceSHans Rosenfeld
871*a61ed2ceSHans Rosenfeld if (data->atr_nti <= 2) {
872*a61ed2ceSHans Rosenfeld return (ATR_T1_CWI_DEFAULT);
873*a61ed2ceSHans Rosenfeld }
874*a61ed2ceSHans Rosenfeld
875*a61ed2ceSHans Rosenfeld for (i = 2; i < data->atr_nti; i++) {
876*a61ed2ceSHans Rosenfeld if (data->atr_ti[i].atrti_protocol == ATR_PROTOCOL_T1) {
877*a61ed2ceSHans Rosenfeld if ((data->atr_ti[i].atrti_flags & ATR_TI_HAVE_TB) !=
878*a61ed2ceSHans Rosenfeld 0) {
879*a61ed2ceSHans Rosenfeld uint8_t tb = data->atr_ti[i].atrti_tb;
880*a61ed2ceSHans Rosenfeld return (ATR_T1_TB0_CWI(tb));
881*a61ed2ceSHans Rosenfeld }
882*a61ed2ceSHans Rosenfeld
883*a61ed2ceSHans Rosenfeld return (ATR_T1_CWI_DEFAULT);
884*a61ed2ceSHans Rosenfeld }
885*a61ed2ceSHans Rosenfeld }
886*a61ed2ceSHans Rosenfeld
887*a61ed2ceSHans Rosenfeld return (ATR_T1_CWI_DEFAULT);
888*a61ed2ceSHans Rosenfeld }
889*a61ed2ceSHans Rosenfeld
890*a61ed2ceSHans Rosenfeld atr_clock_stop_t
atr_clock_stop(atr_data_t * data)891*a61ed2ceSHans Rosenfeld atr_clock_stop(atr_data_t *data)
892*a61ed2ceSHans Rosenfeld {
893*a61ed2ceSHans Rosenfeld uint8_t i;
894*a61ed2ceSHans Rosenfeld
895*a61ed2ceSHans Rosenfeld for (i = 0; i < data->atr_nti; i++) {
896*a61ed2ceSHans Rosenfeld if (data->atr_ti[i].atrti_protocol == ATR_PROTOCOL_T15) {
897*a61ed2ceSHans Rosenfeld if ((data->atr_ti[i].atrti_flags & ATR_TI_HAVE_TA) !=
898*a61ed2ceSHans Rosenfeld 0) {
899*a61ed2ceSHans Rosenfeld uint8_t ta = data->atr_ti[i].atrti_ta;
900*a61ed2ceSHans Rosenfeld return (ATR_T15_TA0_CLOCK(ta));
901*a61ed2ceSHans Rosenfeld }
902*a61ed2ceSHans Rosenfeld
903*a61ed2ceSHans Rosenfeld return (ATR_CLOCK_STOP_NONE);
904*a61ed2ceSHans Rosenfeld }
905*a61ed2ceSHans Rosenfeld }
906*a61ed2ceSHans Rosenfeld
907*a61ed2ceSHans Rosenfeld return (ATR_CLOCK_STOP_NONE);
908*a61ed2ceSHans Rosenfeld }
909*a61ed2ceSHans Rosenfeld
910*a61ed2ceSHans Rosenfeld atr_t1_checksum_t
atr_t1_checksum(atr_data_t * data)911*a61ed2ceSHans Rosenfeld atr_t1_checksum(atr_data_t *data)
912*a61ed2ceSHans Rosenfeld {
913*a61ed2ceSHans Rosenfeld uint8_t i;
914*a61ed2ceSHans Rosenfeld
915*a61ed2ceSHans Rosenfeld if (data->atr_nti <= 2) {
916*a61ed2ceSHans Rosenfeld return (ATR_T1_CHECKSUM_DEFAULT);
917*a61ed2ceSHans Rosenfeld }
918*a61ed2ceSHans Rosenfeld
919*a61ed2ceSHans Rosenfeld for (i = 2; i < data->atr_nti; i++) {
920*a61ed2ceSHans Rosenfeld if (data->atr_ti[i].atrti_protocol == ATR_PROTOCOL_T1) {
921*a61ed2ceSHans Rosenfeld if ((data->atr_ti[i].atrti_flags & ATR_TI_HAVE_TC) !=
922*a61ed2ceSHans Rosenfeld 0) {
923*a61ed2ceSHans Rosenfeld if (ATR_T1_TC0_CRC(data->atr_ti[i].atrti_tc)) {
924*a61ed2ceSHans Rosenfeld return (ATR_T1_CHECKSUM_CRC);
925*a61ed2ceSHans Rosenfeld } else {
926*a61ed2ceSHans Rosenfeld return (ATR_T1_CHECKSUM_LRC);
927*a61ed2ceSHans Rosenfeld }
928*a61ed2ceSHans Rosenfeld }
929*a61ed2ceSHans Rosenfeld
930*a61ed2ceSHans Rosenfeld return (ATR_T1_CHECKSUM_DEFAULT);
931*a61ed2ceSHans Rosenfeld }
932*a61ed2ceSHans Rosenfeld }
933*a61ed2ceSHans Rosenfeld
934*a61ed2ceSHans Rosenfeld return (ATR_T1_CHECKSUM_DEFAULT);
935*a61ed2ceSHans Rosenfeld
936*a61ed2ceSHans Rosenfeld }
937*a61ed2ceSHans Rosenfeld
938*a61ed2ceSHans Rosenfeld uint8_t
atr_t1_bwi(atr_data_t * data)939*a61ed2ceSHans Rosenfeld atr_t1_bwi(atr_data_t *data)
940*a61ed2ceSHans Rosenfeld {
941*a61ed2ceSHans Rosenfeld uint8_t i;
942*a61ed2ceSHans Rosenfeld
943*a61ed2ceSHans Rosenfeld if (data->atr_nti <= 2) {
944*a61ed2ceSHans Rosenfeld return (ATR_T1_BWI_DEFAULT);
945*a61ed2ceSHans Rosenfeld }
946*a61ed2ceSHans Rosenfeld
947*a61ed2ceSHans Rosenfeld for (i = 2; i < data->atr_nti; i++) {
948*a61ed2ceSHans Rosenfeld if (data->atr_ti[i].atrti_protocol == ATR_PROTOCOL_T1) {
949*a61ed2ceSHans Rosenfeld if ((data->atr_ti[i].atrti_flags & ATR_TI_HAVE_TB) !=
950*a61ed2ceSHans Rosenfeld 0) {
951*a61ed2ceSHans Rosenfeld uint8_t tb = data->atr_ti[i].atrti_tb;
952*a61ed2ceSHans Rosenfeld return (ATR_T1_TB0_BWI(tb));
953*a61ed2ceSHans Rosenfeld }
954*a61ed2ceSHans Rosenfeld
955*a61ed2ceSHans Rosenfeld return (ATR_T1_BWI_DEFAULT);
956*a61ed2ceSHans Rosenfeld }
957*a61ed2ceSHans Rosenfeld }
958*a61ed2ceSHans Rosenfeld
959*a61ed2ceSHans Rosenfeld return (ATR_T1_BWI_DEFAULT);
960*a61ed2ceSHans Rosenfeld }
961*a61ed2ceSHans Rosenfeld
962*a61ed2ceSHans Rosenfeld uint8_t
atr_t1_ifsc(atr_data_t * data)963*a61ed2ceSHans Rosenfeld atr_t1_ifsc(atr_data_t *data)
964*a61ed2ceSHans Rosenfeld {
965*a61ed2ceSHans Rosenfeld uint8_t i;
966*a61ed2ceSHans Rosenfeld
967*a61ed2ceSHans Rosenfeld if (data->atr_nti <= 2) {
968*a61ed2ceSHans Rosenfeld return (ATR_T1_IFSC_DEFAULT);
969*a61ed2ceSHans Rosenfeld }
970*a61ed2ceSHans Rosenfeld
971*a61ed2ceSHans Rosenfeld for (i = 2; i < data->atr_nti; i++) {
972*a61ed2ceSHans Rosenfeld if (data->atr_ti[i].atrti_protocol == ATR_PROTOCOL_T1) {
973*a61ed2ceSHans Rosenfeld if ((data->atr_ti[i].atrti_flags & ATR_TI_HAVE_TA) !=
974*a61ed2ceSHans Rosenfeld 0) {
975*a61ed2ceSHans Rosenfeld return (data->atr_ti[i].atrti_ta);
976*a61ed2ceSHans Rosenfeld }
977*a61ed2ceSHans Rosenfeld
978*a61ed2ceSHans Rosenfeld return (ATR_T1_IFSC_DEFAULT);
979*a61ed2ceSHans Rosenfeld }
980*a61ed2ceSHans Rosenfeld }
981*a61ed2ceSHans Rosenfeld
982*a61ed2ceSHans Rosenfeld return (ATR_T1_IFSC_DEFAULT);
983*a61ed2ceSHans Rosenfeld }
984*a61ed2ceSHans Rosenfeld
985*a61ed2ceSHans Rosenfeld /*
986*a61ed2ceSHans Rosenfeld * Attempt to determine which set of data rates we should be able to use for a
987*a61ed2ceSHans Rosenfeld * given class of protocol. Here we want to do the calculation based on the CCID
988*a61ed2ceSHans Rosenfeld * specification, section 9.4.x. To use these higher rates we need:
989*a61ed2ceSHans Rosenfeld *
990*a61ed2ceSHans Rosenfeld * + Reader's data rate > frequency * Di / Fi.
991*a61ed2ceSHans Rosenfeld *
992*a61ed2ceSHans Rosenfeld * To determine which rate and frequency we use, we look at the reader's
993*a61ed2ceSHans Rosenfeld * features. If the reader supports both the Automatic baud rate and automatic
994*a61ed2ceSHans Rosenfeld * ICC clock frequency change, then we use the _maximum_ rate. Otherwise we will
995*a61ed2ceSHans Rosenfeld * indicate that we can use the ATR's properties, but will require changing the
996*a61ed2ceSHans Rosenfeld * default data rate.
997*a61ed2ceSHans Rosenfeld *
998*a61ed2ceSHans Rosenfeld * Now, some ICC devices are not negotiable. In those cases, we'll see if we can
999*a61ed2ceSHans Rosenfeld * fit it in with either the default or maximum data rates. If not, then we'll
1000*a61ed2ceSHans Rosenfeld * not be able to support this card.
1001*a61ed2ceSHans Rosenfeld *
1002*a61ed2ceSHans Rosenfeld * There are two wrinkles that exist in this. The first is supported frequencies
1003*a61ed2ceSHans Rosenfeld * and data rates. If there are no additional data rates supported, then all of
1004*a61ed2ceSHans Rosenfeld * the data rates between the default and max are supported. If not, then only
1005*a61ed2ceSHans Rosenfeld * those specified in the data rates array are supported.
1006*a61ed2ceSHans Rosenfeld *
1007*a61ed2ceSHans Rosenfeld * The second hurdle is that we need to do this division and try and avoid the
1008*a61ed2ceSHans Rosenfeld * pitfalls of floating point arithmetic, as floating point is not allowed in
1009*a61ed2ceSHans Rosenfeld * the kernel (and this is shared). Importantly that means only integers are
1010*a61ed2ceSHans Rosenfeld * allowed here.
1011*a61ed2ceSHans Rosenfeld */
1012*a61ed2ceSHans Rosenfeld atr_data_rate_choice_t
atr_data_rate(atr_data_t * data,ccid_class_descr_t * class,uint32_t * rates,uint_t nrates,uint32_t * dataratep)1013*a61ed2ceSHans Rosenfeld atr_data_rate(atr_data_t *data, ccid_class_descr_t *class, uint32_t *rates,
1014*a61ed2ceSHans Rosenfeld uint_t nrates, uint32_t *dataratep)
1015*a61ed2ceSHans Rosenfeld {
1016*a61ed2ceSHans Rosenfeld uint_t nfeats = CCID_CLASS_F_AUTO_ICC_CLOCK | CCID_CLASS_F_AUTO_BAUD;
1017*a61ed2ceSHans Rosenfeld uint8_t di, fi;
1018*a61ed2ceSHans Rosenfeld uint_t dival, fival;
1019*a61ed2ceSHans Rosenfeld boolean_t autospeed, negotiable, exprates;
1020*a61ed2ceSHans Rosenfeld uint64_t maxval, defval;
1021*a61ed2ceSHans Rosenfeld
1022*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
1023*a61ed2ceSHans Rosenfeld return (ATR_RATE_UNSUPPORTED);
1024*a61ed2ceSHans Rosenfeld
1025*a61ed2ceSHans Rosenfeld di = atr_di_index(data);
1026*a61ed2ceSHans Rosenfeld fi = atr_fi_index(data);
1027*a61ed2ceSHans Rosenfeld dival = atr_di_index_to_value(di);
1028*a61ed2ceSHans Rosenfeld fival = atr_fi_index_to_value(fi);
1029*a61ed2ceSHans Rosenfeld autospeed = (class->ccd_dwFeatures & nfeats) == nfeats;
1030*a61ed2ceSHans Rosenfeld exprates = class->ccd_bNumDataRatesSupported != 0;
1031*a61ed2ceSHans Rosenfeld negotiable = atr_params_negotiable(data);
1032*a61ed2ceSHans Rosenfeld
1033*a61ed2ceSHans Rosenfeld /*
1034*a61ed2ceSHans Rosenfeld * We don't support cards with fixed rates at this time as it's not
1035*a61ed2ceSHans Rosenfeld * clear what that rate should be. If it's negotiable, we'll let them
1036*a61ed2ceSHans Rosenfeld * run at the default. Otherwise, we have to fail the request until
1037*a61ed2ceSHans Rosenfeld * we implement the logic to search their data rates.
1038*a61ed2ceSHans Rosenfeld */
1039*a61ed2ceSHans Rosenfeld if (exprates) {
1040*a61ed2ceSHans Rosenfeld if (negotiable) {
1041*a61ed2ceSHans Rosenfeld return (ATR_RATE_USEDEFAULT);
1042*a61ed2ceSHans Rosenfeld }
1043*a61ed2ceSHans Rosenfeld return (ATR_RATE_UNSUPPORTED);
1044*a61ed2ceSHans Rosenfeld }
1045*a61ed2ceSHans Rosenfeld
1046*a61ed2ceSHans Rosenfeld /*
1047*a61ed2ceSHans Rosenfeld * This indicates that the card gave us values that were reserved for
1048*a61ed2ceSHans Rosenfeld * future use. If we could negotiate it, then just stick with the
1049*a61ed2ceSHans Rosenfeld * default paramters. Otherwise, return that we can't support this ICC.
1050*a61ed2ceSHans Rosenfeld */
1051*a61ed2ceSHans Rosenfeld if (dival == 0 || fival == 0) {
1052*a61ed2ceSHans Rosenfeld if (negotiable)
1053*a61ed2ceSHans Rosenfeld return (ATR_RATE_USEDEFAULT);
1054*a61ed2ceSHans Rosenfeld return (ATR_RATE_UNSUPPORTED);
1055*a61ed2ceSHans Rosenfeld }
1056*a61ed2ceSHans Rosenfeld
1057*a61ed2ceSHans Rosenfeld /*
1058*a61ed2ceSHans Rosenfeld * Calculate the maximum and default values.
1059*a61ed2ceSHans Rosenfeld */
1060*a61ed2ceSHans Rosenfeld maxval = class->ccd_dwMaximumClock * 1000;
1061*a61ed2ceSHans Rosenfeld maxval *= dival;
1062*a61ed2ceSHans Rosenfeld maxval /= fival;
1063*a61ed2ceSHans Rosenfeld
1064*a61ed2ceSHans Rosenfeld defval = class->ccd_dwDefaultClock * 1000;
1065*a61ed2ceSHans Rosenfeld defval *= dival;
1066*a61ed2ceSHans Rosenfeld defval /= fival;
1067*a61ed2ceSHans Rosenfeld
1068*a61ed2ceSHans Rosenfeld /*
1069*a61ed2ceSHans Rosenfeld * We're allowed any set of data rates between the default and the
1070*a61ed2ceSHans Rosenfeld * maximum. Check if the maximum data rate will work for either the
1071*a61ed2ceSHans Rosenfeld * default or maximum clock. If so, then we can use the cards rates.
1072*a61ed2ceSHans Rosenfeld *
1073*a61ed2ceSHans Rosenfeld * To account for the fact that we may have had a fractional value,
1074*a61ed2ceSHans Rosenfeld * we require a strict greater than comparison.
1075*a61ed2ceSHans Rosenfeld */
1076*a61ed2ceSHans Rosenfeld if ((uint64_t)class->ccd_dwMaxDataRate > maxval ||
1077*a61ed2ceSHans Rosenfeld (uint64_t)class->ccd_dwMaxDataRate > defval) {
1078*a61ed2ceSHans Rosenfeld if (autospeed) {
1079*a61ed2ceSHans Rosenfeld return (ATR_RATE_USEATR);
1080*a61ed2ceSHans Rosenfeld }
1081*a61ed2ceSHans Rosenfeld }
1082*a61ed2ceSHans Rosenfeld
1083*a61ed2ceSHans Rosenfeld /*
1084*a61ed2ceSHans Rosenfeld * If the CCID reader can't handle the ICC's proposed rates, then fall
1085*a61ed2ceSHans Rosenfeld * back to the defaults if we're allowed to negotiate. Otherwise, we're
1086*a61ed2ceSHans Rosenfeld * not able to use this ICC.
1087*a61ed2ceSHans Rosenfeld */
1088*a61ed2ceSHans Rosenfeld if (negotiable) {
1089*a61ed2ceSHans Rosenfeld return (ATR_RATE_USEDEFAULT);
1090*a61ed2ceSHans Rosenfeld }
1091*a61ed2ceSHans Rosenfeld
1092*a61ed2ceSHans Rosenfeld return (ATR_RATE_UNSUPPORTED);
1093*a61ed2ceSHans Rosenfeld }
1094*a61ed2ceSHans Rosenfeld
1095*a61ed2ceSHans Rosenfeld void
atr_data_reset(atr_data_t * data)1096*a61ed2ceSHans Rosenfeld atr_data_reset(atr_data_t *data)
1097*a61ed2ceSHans Rosenfeld {
1098*a61ed2ceSHans Rosenfeld bzero(data, sizeof (*data));
1099*a61ed2ceSHans Rosenfeld }
1100*a61ed2ceSHans Rosenfeld
1101*a61ed2ceSHans Rosenfeld #ifdef _KERNEL
1102*a61ed2ceSHans Rosenfeld atr_data_t *
atr_data_alloc(void)1103*a61ed2ceSHans Rosenfeld atr_data_alloc(void)
1104*a61ed2ceSHans Rosenfeld {
1105*a61ed2ceSHans Rosenfeld return (kmem_zalloc(sizeof (atr_data_t), KM_SLEEP));
1106*a61ed2ceSHans Rosenfeld }
1107*a61ed2ceSHans Rosenfeld
1108*a61ed2ceSHans Rosenfeld void
atr_data_free(atr_data_t * data)1109*a61ed2ceSHans Rosenfeld atr_data_free(atr_data_t *data)
1110*a61ed2ceSHans Rosenfeld {
1111*a61ed2ceSHans Rosenfeld kmem_free(data, sizeof (atr_data_t));
1112*a61ed2ceSHans Rosenfeld }
1113*a61ed2ceSHans Rosenfeld
1114*a61ed2ceSHans Rosenfeld /*
1115*a61ed2ceSHans Rosenfeld * Make sure that the response we got from the ICC is valid. It must pass
1116*a61ed2ceSHans Rosenfeld * checksum and have the PPSS value set correctly. The protocol must match
1117*a61ed2ceSHans Rosenfeld * what we requested; however, the PPS1-3 bits are a bit different. They may
1118*a61ed2ceSHans Rosenfeld * only be set in the response if we set them in the request. However, they
1119*a61ed2ceSHans Rosenfeld * do not have to be set in the response.
1120*a61ed2ceSHans Rosenfeld */
1121*a61ed2ceSHans Rosenfeld boolean_t
atr_pps_valid(void * reqbuf,size_t reqlen,void * respbuf,size_t resplen)1122*a61ed2ceSHans Rosenfeld atr_pps_valid(void *reqbuf, size_t reqlen, void *respbuf, size_t resplen)
1123*a61ed2ceSHans Rosenfeld {
1124*a61ed2ceSHans Rosenfeld uint8_t val, i, reqidx, respidx;
1125*a61ed2ceSHans Rosenfeld uint8_t *req = reqbuf, *resp = respbuf;
1126*a61ed2ceSHans Rosenfeld
1127*a61ed2ceSHans Rosenfeld if (resplen > PPS_LEN_MAX || resplen < PPS_LEN_MIN)
1128*a61ed2ceSHans Rosenfeld return (B_FALSE);
1129*a61ed2ceSHans Rosenfeld
1130*a61ed2ceSHans Rosenfeld /*
1131*a61ed2ceSHans Rosenfeld * Before we validate the data, make sure the checksum is valid.
1132*a61ed2ceSHans Rosenfeld */
1133*a61ed2ceSHans Rosenfeld for (i = 0, val = 0; i < resplen; i++) {
1134*a61ed2ceSHans Rosenfeld val ^= resp[i];
1135*a61ed2ceSHans Rosenfeld }
1136*a61ed2ceSHans Rosenfeld
1137*a61ed2ceSHans Rosenfeld /* Checksum failure */
1138*a61ed2ceSHans Rosenfeld if (val != 0) {
1139*a61ed2ceSHans Rosenfeld return (B_FALSE);
1140*a61ed2ceSHans Rosenfeld }
1141*a61ed2ceSHans Rosenfeld
1142*a61ed2ceSHans Rosenfeld /*
1143*a61ed2ceSHans Rosenfeld * We should always have PPSS echoed back as we set it.
1144*a61ed2ceSHans Rosenfeld */
1145*a61ed2ceSHans Rosenfeld if (resp[PPS_PPSS_INDEX] != PPS_PPSS_VAL) {
1146*a61ed2ceSHans Rosenfeld return (B_FALSE);
1147*a61ed2ceSHans Rosenfeld }
1148*a61ed2ceSHans Rosenfeld
1149*a61ed2ceSHans Rosenfeld /*
1150*a61ed2ceSHans Rosenfeld * Go through and make sure the number of bytes present makes sense for
1151*a61ed2ceSHans Rosenfeld * the number of bits set in PPS1.
1152*a61ed2ceSHans Rosenfeld */
1153*a61ed2ceSHans Rosenfeld val = PPS_LEN_MIN;
1154*a61ed2ceSHans Rosenfeld if (resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS1)
1155*a61ed2ceSHans Rosenfeld val++;
1156*a61ed2ceSHans Rosenfeld if (resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS2)
1157*a61ed2ceSHans Rosenfeld val++;
1158*a61ed2ceSHans Rosenfeld if (resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS3)
1159*a61ed2ceSHans Rosenfeld val++;
1160*a61ed2ceSHans Rosenfeld if (val != resplen)
1161*a61ed2ceSHans Rosenfeld return (B_FALSE);
1162*a61ed2ceSHans Rosenfeld
1163*a61ed2ceSHans Rosenfeld /*
1164*a61ed2ceSHans Rosenfeld * Now we've finally verified that the response is syntactically valid.
1165*a61ed2ceSHans Rosenfeld * We must go through and make sure that it is semantically valid.
1166*a61ed2ceSHans Rosenfeld */
1167*a61ed2ceSHans Rosenfeld if (PPS_PPS0_PROT(req[PPS_PPS0_INDEX]) !=
1168*a61ed2ceSHans Rosenfeld PPS_PPS0_PROT(resp[PPS_PPS0_INDEX])) {
1169*a61ed2ceSHans Rosenfeld return (B_FALSE);
1170*a61ed2ceSHans Rosenfeld }
1171*a61ed2ceSHans Rosenfeld
1172*a61ed2ceSHans Rosenfeld /*
1173*a61ed2ceSHans Rosenfeld * When checking the PPS bit and extensions, we first check in the
1174*a61ed2ceSHans Rosenfeld * response as a bit in the request is allowed to not be in the
1175*a61ed2ceSHans Rosenfeld * response. But not the opposite way around. We also have to keep track
1176*a61ed2ceSHans Rosenfeld * of the fact that the index for values will vary.
1177*a61ed2ceSHans Rosenfeld */
1178*a61ed2ceSHans Rosenfeld reqidx = respidx = PPS_PPS0_INDEX + 1;
1179*a61ed2ceSHans Rosenfeld if ((resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS1) != 0) {
1180*a61ed2ceSHans Rosenfeld if ((req[PPS_PPS0_INDEX] & PPS_PPS0_PPS1) == 0) {
1181*a61ed2ceSHans Rosenfeld return (B_FALSE);
1182*a61ed2ceSHans Rosenfeld }
1183*a61ed2ceSHans Rosenfeld
1184*a61ed2ceSHans Rosenfeld if (req[reqidx] != resp[respidx]) {
1185*a61ed2ceSHans Rosenfeld return (B_FALSE);
1186*a61ed2ceSHans Rosenfeld }
1187*a61ed2ceSHans Rosenfeld
1188*a61ed2ceSHans Rosenfeld reqidx++;
1189*a61ed2ceSHans Rosenfeld respidx++;
1190*a61ed2ceSHans Rosenfeld } else if ((req[PPS_PPS0_INDEX] & PPS_PPS0_PPS1) != 0) {
1191*a61ed2ceSHans Rosenfeld reqidx++;
1192*a61ed2ceSHans Rosenfeld }
1193*a61ed2ceSHans Rosenfeld
1194*a61ed2ceSHans Rosenfeld if ((resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS2) != 0) {
1195*a61ed2ceSHans Rosenfeld if ((req[PPS_PPS0_INDEX] & PPS_PPS0_PPS2) == 0) {
1196*a61ed2ceSHans Rosenfeld return (B_FALSE);
1197*a61ed2ceSHans Rosenfeld }
1198*a61ed2ceSHans Rosenfeld
1199*a61ed2ceSHans Rosenfeld if (req[reqidx] != resp[respidx]) {
1200*a61ed2ceSHans Rosenfeld return (B_FALSE);
1201*a61ed2ceSHans Rosenfeld }
1202*a61ed2ceSHans Rosenfeld
1203*a61ed2ceSHans Rosenfeld reqidx++;
1204*a61ed2ceSHans Rosenfeld respidx++;
1205*a61ed2ceSHans Rosenfeld } else if ((req[PPS_PPS0_INDEX] & PPS_PPS0_PPS2) != 0) {
1206*a61ed2ceSHans Rosenfeld reqidx++;
1207*a61ed2ceSHans Rosenfeld }
1208*a61ed2ceSHans Rosenfeld
1209*a61ed2ceSHans Rosenfeld if ((resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS3) != 0) {
1210*a61ed2ceSHans Rosenfeld /*
1211*a61ed2ceSHans Rosenfeld * At this time, we never specify PPS3 in a request. Therefore
1212*a61ed2ceSHans Rosenfeld * if it is present in the response, treat this as an invalid
1213*a61ed2ceSHans Rosenfeld * request.
1214*a61ed2ceSHans Rosenfeld */
1215*a61ed2ceSHans Rosenfeld return (B_FALSE);
1216*a61ed2ceSHans Rosenfeld }
1217*a61ed2ceSHans Rosenfeld
1218*a61ed2ceSHans Rosenfeld return (B_TRUE);
1219*a61ed2ceSHans Rosenfeld }
1220*a61ed2ceSHans Rosenfeld
1221*a61ed2ceSHans Rosenfeld uint_t
atr_pps_generate(uint8_t * buf,size_t buflen,atr_protocol_t prot,boolean_t pps1,uint8_t fi,uint8_t di,boolean_t pps2,uint8_t spu)1222*a61ed2ceSHans Rosenfeld atr_pps_generate(uint8_t *buf, size_t buflen, atr_protocol_t prot,
1223*a61ed2ceSHans Rosenfeld boolean_t pps1, uint8_t fi, uint8_t di, boolean_t pps2, uint8_t spu)
1224*a61ed2ceSHans Rosenfeld {
1225*a61ed2ceSHans Rosenfeld uint8_t protval, cksum, i;
1226*a61ed2ceSHans Rosenfeld uint_t len = 0;
1227*a61ed2ceSHans Rosenfeld
1228*a61ed2ceSHans Rosenfeld if (buflen < PPS_BUFFER_MAX)
1229*a61ed2ceSHans Rosenfeld return (0);
1230*a61ed2ceSHans Rosenfeld
1231*a61ed2ceSHans Rosenfeld buf[PPS_PPSS_INDEX] = PPS_PPSS_VAL;
1232*a61ed2ceSHans Rosenfeld switch (prot) {
1233*a61ed2ceSHans Rosenfeld case ATR_P_T0:
1234*a61ed2ceSHans Rosenfeld protval = 0;
1235*a61ed2ceSHans Rosenfeld break;
1236*a61ed2ceSHans Rosenfeld case ATR_P_T1:
1237*a61ed2ceSHans Rosenfeld protval = 1;
1238*a61ed2ceSHans Rosenfeld break;
1239*a61ed2ceSHans Rosenfeld default:
1240*a61ed2ceSHans Rosenfeld return (0);
1241*a61ed2ceSHans Rosenfeld }
1242*a61ed2ceSHans Rosenfeld
1243*a61ed2ceSHans Rosenfeld buf[PPS_PPS0_INDEX] = PPS_PPS0_PROT(protval);
1244*a61ed2ceSHans Rosenfeld len = 2;
1245*a61ed2ceSHans Rosenfeld if (pps1) {
1246*a61ed2ceSHans Rosenfeld buf[PPS_PPS0_INDEX] |= PPS_PPS0_PPS1;
1247*a61ed2ceSHans Rosenfeld buf[len++] = PPS_PPS1_SETVAL(fi, di);
1248*a61ed2ceSHans Rosenfeld }
1249*a61ed2ceSHans Rosenfeld
1250*a61ed2ceSHans Rosenfeld if (pps2) {
1251*a61ed2ceSHans Rosenfeld buf[PPS_PPS0_INDEX] |= PPS_PPS0_PPS2;
1252*a61ed2ceSHans Rosenfeld buf[len++] = spu;
1253*a61ed2ceSHans Rosenfeld }
1254*a61ed2ceSHans Rosenfeld
1255*a61ed2ceSHans Rosenfeld /*
1256*a61ed2ceSHans Rosenfeld * The checksum must xor to zero.
1257*a61ed2ceSHans Rosenfeld */
1258*a61ed2ceSHans Rosenfeld for (i = 0, cksum = 0; i < len; i++) {
1259*a61ed2ceSHans Rosenfeld cksum ^= buf[i];
1260*a61ed2ceSHans Rosenfeld }
1261*a61ed2ceSHans Rosenfeld buf[len++] = cksum;
1262*a61ed2ceSHans Rosenfeld return (len);
1263*a61ed2ceSHans Rosenfeld }
1264*a61ed2ceSHans Rosenfeld
1265*a61ed2ceSHans Rosenfeld /*
1266*a61ed2ceSHans Rosenfeld * The caller of this wants to know if the Fi/Di values that they proposed were
1267*a61ed2ceSHans Rosenfeld * accepted. The caller must have already called atr_pps_valid(). At this point,
1268*a61ed2ceSHans Rosenfeld * we can say that the value was accepted if the PPS1 bit is set.
1269*a61ed2ceSHans Rosenfeld */
1270*a61ed2ceSHans Rosenfeld boolean_t
atr_pps_fidi_accepted(void * respbuf,size_t len)1271*a61ed2ceSHans Rosenfeld atr_pps_fidi_accepted(void *respbuf, size_t len)
1272*a61ed2ceSHans Rosenfeld {
1273*a61ed2ceSHans Rosenfeld uint8_t *resp = respbuf;
1274*a61ed2ceSHans Rosenfeld return ((resp[PPS_PPS0_INDEX] & PPS_PPS0_PPS1) != 0);
1275*a61ed2ceSHans Rosenfeld }
1276*a61ed2ceSHans Rosenfeld
1277*a61ed2ceSHans Rosenfeld #else /* !_KERNEL */
1278*a61ed2ceSHans Rosenfeld atr_data_t *
atr_data_alloc(void)1279*a61ed2ceSHans Rosenfeld atr_data_alloc(void)
1280*a61ed2ceSHans Rosenfeld {
1281*a61ed2ceSHans Rosenfeld return (calloc(1, sizeof (atr_data_t)));
1282*a61ed2ceSHans Rosenfeld }
1283*a61ed2ceSHans Rosenfeld
1284*a61ed2ceSHans Rosenfeld void
atr_data_free(atr_data_t * data)1285*a61ed2ceSHans Rosenfeld atr_data_free(atr_data_t *data)
1286*a61ed2ceSHans Rosenfeld {
1287*a61ed2ceSHans Rosenfeld if (data == NULL)
1288*a61ed2ceSHans Rosenfeld return;
1289*a61ed2ceSHans Rosenfeld free(data);
1290*a61ed2ceSHans Rosenfeld }
1291*a61ed2ceSHans Rosenfeld
1292*a61ed2ceSHans Rosenfeld /*
1293*a61ed2ceSHans Rosenfeld * This table maps the bit values for Fi from 7816-3:2006 section 8.3 Table 9.
1294*a61ed2ceSHans Rosenfeld * The table is up to 6 bits wide. Entries not present are RFU. We use NULL as a
1295*a61ed2ceSHans Rosenfeld * sentinel to indicate that.
1296*a61ed2ceSHans Rosenfeld */
1297*a61ed2ceSHans Rosenfeld static const char *atr_voltage_table[64] = {
1298*a61ed2ceSHans Rosenfeld NULL, /* 00 0000 */
1299*a61ed2ceSHans Rosenfeld "5V", /* 00 0001 */
1300*a61ed2ceSHans Rosenfeld "3V", /* 00 0010 */
1301*a61ed2ceSHans Rosenfeld "5V, 3V", /* 00 0011 */
1302*a61ed2ceSHans Rosenfeld "1.5V", /* 00 0100 */
1303*a61ed2ceSHans Rosenfeld NULL, /* 00 0101 */
1304*a61ed2ceSHans Rosenfeld "3V, 1.5V", /* 00 0110 */
1305*a61ed2ceSHans Rosenfeld "5V, 3V, 1.5V" /* 00 0111 */
1306*a61ed2ceSHans Rosenfeld };
1307*a61ed2ceSHans Rosenfeld
1308*a61ed2ceSHans Rosenfeld static void
atr_data_dump_ta(atr_ti_t * atp,FILE * out,uint_t level)1309*a61ed2ceSHans Rosenfeld atr_data_dump_ta(atr_ti_t *atp, FILE *out, uint_t level)
1310*a61ed2ceSHans Rosenfeld {
1311*a61ed2ceSHans Rosenfeld uint8_t ta;
1312*a61ed2ceSHans Rosenfeld
1313*a61ed2ceSHans Rosenfeld if (!(atp->atrti_flags & ATR_TI_HAVE_TA)) {
1314*a61ed2ceSHans Rosenfeld return;
1315*a61ed2ceSHans Rosenfeld }
1316*a61ed2ceSHans Rosenfeld
1317*a61ed2ceSHans Rosenfeld ta = atp->atrti_ta;
1318*a61ed2ceSHans Rosenfeld (void) fprintf(out, " %c%c%c+-> TA%u 0x%02x",
1319*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TD ? '|' : ' ',
1320*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TC ? '|' : ' ',
1321*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TB ? '|' : ' ',
1322*a61ed2ceSHans Rosenfeld atp->atrti_ti_val, ta);
1323*a61ed2ceSHans Rosenfeld switch (atp->atrti_ti_val) {
1324*a61ed2ceSHans Rosenfeld case 1:
1325*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; Fi: %s, F(max): %s MHz, Di: %s",
1326*a61ed2ceSHans Rosenfeld atr_fi_table[ATR_TA1_FTABLE(ta)],
1327*a61ed2ceSHans Rosenfeld atr_fmax_table[ATR_TA1_FTABLE(ta)],
1328*a61ed2ceSHans Rosenfeld atr_di_table[ATR_TA1_DITABLE(ta)]);
1329*a61ed2ceSHans Rosenfeld break;
1330*a61ed2ceSHans Rosenfeld case 2:
1331*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; ICC in %s mode; %shonoring TA1; default "
1332*a61ed2ceSHans Rosenfeld "T=%u",
1333*a61ed2ceSHans Rosenfeld ATR_TA2_CANCHANGE(ta) ? "negotiable" : "specific",
1334*a61ed2ceSHans Rosenfeld ATR_TA2_HONORTA1(ta) ? "" : "not ",
1335*a61ed2ceSHans Rosenfeld ATR_TA2_PROTOCOL(ta));
1336*a61ed2ceSHans Rosenfeld break;
1337*a61ed2ceSHans Rosenfeld default:
1338*a61ed2ceSHans Rosenfeld switch (atp->atrti_protocol) {
1339*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T1:
1340*a61ed2ceSHans Rosenfeld if (level != 0)
1341*a61ed2ceSHans Rosenfeld break;
1342*a61ed2ceSHans Rosenfeld if (ta == 0 || ta == 0xff) {
1343*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; IFSC: RFU");
1344*a61ed2ceSHans Rosenfeld } else {
1345*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; IFSC: %u", ta);
1346*a61ed2ceSHans Rosenfeld }
1347*a61ed2ceSHans Rosenfeld break;
1348*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T15:
1349*a61ed2ceSHans Rosenfeld if (level != 0)
1350*a61ed2ceSHans Rosenfeld break;
1351*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; Clock stop: %s, Supported "
1352*a61ed2ceSHans Rosenfeld "Voltage: %s",
1353*a61ed2ceSHans Rosenfeld atr_clock_table[ATR_T15_TA0_CLOCK(ta)],
1354*a61ed2ceSHans Rosenfeld atr_voltage_table[ATR_T15_TA0_VOLTAGE(ta)] != NULL ?
1355*a61ed2ceSHans Rosenfeld atr_voltage_table[ATR_T15_TA0_VOLTAGE(ta)] : "RFU");
1356*a61ed2ceSHans Rosenfeld break;
1357*a61ed2ceSHans Rosenfeld default:
1358*a61ed2ceSHans Rosenfeld break;
1359*a61ed2ceSHans Rosenfeld }
1360*a61ed2ceSHans Rosenfeld }
1361*a61ed2ceSHans Rosenfeld (void) fprintf(out, "\n");
1362*a61ed2ceSHans Rosenfeld }
1363*a61ed2ceSHans Rosenfeld
1364*a61ed2ceSHans Rosenfeld static void
atr_data_dump_tb(atr_ti_t * atp,FILE * out,uint_t level)1365*a61ed2ceSHans Rosenfeld atr_data_dump_tb(atr_ti_t *atp, FILE *out, uint_t level)
1366*a61ed2ceSHans Rosenfeld {
1367*a61ed2ceSHans Rosenfeld uint8_t tb;
1368*a61ed2ceSHans Rosenfeld
1369*a61ed2ceSHans Rosenfeld if (!(atp->atrti_flags & ATR_TI_HAVE_TB)) {
1370*a61ed2ceSHans Rosenfeld return;
1371*a61ed2ceSHans Rosenfeld }
1372*a61ed2ceSHans Rosenfeld
1373*a61ed2ceSHans Rosenfeld tb = atp->atrti_tb;
1374*a61ed2ceSHans Rosenfeld (void) fprintf(out, " %c%c+--> TB%u 0x%02x",
1375*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TD ? '|' : ' ',
1376*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TC ? '|' : ' ',
1377*a61ed2ceSHans Rosenfeld atp->atrti_ti_val, tb);
1378*a61ed2ceSHans Rosenfeld switch (atp->atrti_ti_val) {
1379*a61ed2ceSHans Rosenfeld case 1:
1380*a61ed2ceSHans Rosenfeld case 2:
1381*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; deprecated");
1382*a61ed2ceSHans Rosenfeld break;
1383*a61ed2ceSHans Rosenfeld default:
1384*a61ed2ceSHans Rosenfeld switch (atp->atrti_protocol) {
1385*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T1:
1386*a61ed2ceSHans Rosenfeld if (level != 0)
1387*a61ed2ceSHans Rosenfeld break;
1388*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; CWI: %u, BWI: %u\n",
1389*a61ed2ceSHans Rosenfeld ATR_T1_TB0_CWI(tb),
1390*a61ed2ceSHans Rosenfeld ATR_T1_TB0_BWI(tb));
1391*a61ed2ceSHans Rosenfeld break;
1392*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T15:
1393*a61ed2ceSHans Rosenfeld if (level != 0)
1394*a61ed2ceSHans Rosenfeld break;
1395*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; SPU: %s", tb == 0 ? "not used" :
1396*a61ed2ceSHans Rosenfeld ATR_T15_TB0_SPU_STANDARD(tb) ? "standard" :
1397*a61ed2ceSHans Rosenfeld "proprietary");
1398*a61ed2ceSHans Rosenfeld break;
1399*a61ed2ceSHans Rosenfeld default:
1400*a61ed2ceSHans Rosenfeld break;
1401*a61ed2ceSHans Rosenfeld }
1402*a61ed2ceSHans Rosenfeld }
1403*a61ed2ceSHans Rosenfeld (void) fprintf(out, "\n");
1404*a61ed2ceSHans Rosenfeld }
1405*a61ed2ceSHans Rosenfeld
1406*a61ed2ceSHans Rosenfeld static void
atr_data_dump_tc(atr_ti_t * atp,FILE * out,uint_t level)1407*a61ed2ceSHans Rosenfeld atr_data_dump_tc(atr_ti_t *atp, FILE *out, uint_t level)
1408*a61ed2ceSHans Rosenfeld {
1409*a61ed2ceSHans Rosenfeld uint8_t tc;
1410*a61ed2ceSHans Rosenfeld
1411*a61ed2ceSHans Rosenfeld if (!(atp->atrti_flags & ATR_TI_HAVE_TC)) {
1412*a61ed2ceSHans Rosenfeld return;
1413*a61ed2ceSHans Rosenfeld }
1414*a61ed2ceSHans Rosenfeld
1415*a61ed2ceSHans Rosenfeld tc = atp->atrti_tc;
1416*a61ed2ceSHans Rosenfeld (void) fprintf(out, " %c+---> TC%u 0x%02x",
1417*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TD ? '|' : ' ',
1418*a61ed2ceSHans Rosenfeld atp->atrti_ti_val, tc);
1419*a61ed2ceSHans Rosenfeld
1420*a61ed2ceSHans Rosenfeld switch (atp->atrti_ti_val) {
1421*a61ed2ceSHans Rosenfeld case 1:
1422*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; Extra Guard Time Integer: %u", tc);
1423*a61ed2ceSHans Rosenfeld break;
1424*a61ed2ceSHans Rosenfeld case 2:
1425*a61ed2ceSHans Rosenfeld if (atp->atrti_protocol != ATR_PROTOCOL_T0) {
1426*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; illegal value -- only valid for "
1427*a61ed2ceSHans Rosenfeld "T=0");
1428*a61ed2ceSHans Rosenfeld } else {
1429*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; Waiting Time Integer: %u", tc);
1430*a61ed2ceSHans Rosenfeld }
1431*a61ed2ceSHans Rosenfeld break;
1432*a61ed2ceSHans Rosenfeld default:
1433*a61ed2ceSHans Rosenfeld switch (atp->atrti_protocol) {
1434*a61ed2ceSHans Rosenfeld case ATR_PROTOCOL_T1:
1435*a61ed2ceSHans Rosenfeld if (level != 0)
1436*a61ed2ceSHans Rosenfeld break;
1437*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; Error Detection Code: %s",
1438*a61ed2ceSHans Rosenfeld ATR_T1_TC0_CRC(tc) ? "CRC" : "LRC");
1439*a61ed2ceSHans Rosenfeld break;
1440*a61ed2ceSHans Rosenfeld default:
1441*a61ed2ceSHans Rosenfeld break;
1442*a61ed2ceSHans Rosenfeld }
1443*a61ed2ceSHans Rosenfeld }
1444*a61ed2ceSHans Rosenfeld (void) fprintf(out, "\n");
1445*a61ed2ceSHans Rosenfeld }
1446*a61ed2ceSHans Rosenfeld
1447*a61ed2ceSHans Rosenfeld void
atr_data_hexdump(const uint8_t * buf,size_t nbytes,FILE * out)1448*a61ed2ceSHans Rosenfeld atr_data_hexdump(const uint8_t *buf, size_t nbytes, FILE *out)
1449*a61ed2ceSHans Rosenfeld {
1450*a61ed2ceSHans Rosenfeld size_t i, j;
1451*a61ed2ceSHans Rosenfeld
1452*a61ed2ceSHans Rosenfeld /* Print out the header */
1453*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%*s 0", 4, "");
1454*a61ed2ceSHans Rosenfeld for (i = 1; i < 16; i++) {
1455*a61ed2ceSHans Rosenfeld if (i % 4 == 0 && i % 16 != 0) {
1456*a61ed2ceSHans Rosenfeld (void) fprintf(out, " ");
1457*a61ed2ceSHans Rosenfeld }
1458*a61ed2ceSHans Rosenfeld
1459*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%2x", i);
1460*a61ed2ceSHans Rosenfeld }
1461*a61ed2ceSHans Rosenfeld (void) fprintf(out, " 0123456789abcdef\n");
1462*a61ed2ceSHans Rosenfeld
1463*a61ed2ceSHans Rosenfeld /* Print out data */
1464*a61ed2ceSHans Rosenfeld for (i = 0; i < nbytes; i++) {
1465*a61ed2ceSHans Rosenfeld
1466*a61ed2ceSHans Rosenfeld if (i % 16 == 0) {
1467*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%04x: ", i);
1468*a61ed2ceSHans Rosenfeld }
1469*a61ed2ceSHans Rosenfeld
1470*a61ed2ceSHans Rosenfeld if (i % 4 == 0 && i % 16 != 0) {
1471*a61ed2ceSHans Rosenfeld (void) fprintf(out, " ");
1472*a61ed2ceSHans Rosenfeld }
1473*a61ed2ceSHans Rosenfeld
1474*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%02x", buf[i]);
1475*a61ed2ceSHans Rosenfeld
1476*a61ed2ceSHans Rosenfeld if (i % 16 == 15 || i + 1 == nbytes) {
1477*a61ed2ceSHans Rosenfeld for (j = (i % 16) + 1; j < 16; j++) {
1478*a61ed2ceSHans Rosenfeld if (j % 4 == 0 && j % 16 != 0) {
1479*a61ed2ceSHans Rosenfeld (void) fprintf(out, " ");
1480*a61ed2ceSHans Rosenfeld }
1481*a61ed2ceSHans Rosenfeld
1482*a61ed2ceSHans Rosenfeld (void) fprintf(out, " ");
1483*a61ed2ceSHans Rosenfeld }
1484*a61ed2ceSHans Rosenfeld
1485*a61ed2ceSHans Rosenfeld (void) fprintf(out, " ");
1486*a61ed2ceSHans Rosenfeld for (j = i - (i % 16); j <= i; j++) {
1487*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%c",
1488*a61ed2ceSHans Rosenfeld isprint(buf[j]) ? buf[j] : '.');
1489*a61ed2ceSHans Rosenfeld }
1490*a61ed2ceSHans Rosenfeld (void) printf("\n");
1491*a61ed2ceSHans Rosenfeld }
1492*a61ed2ceSHans Rosenfeld }
1493*a61ed2ceSHans Rosenfeld }
1494*a61ed2ceSHans Rosenfeld
1495*a61ed2ceSHans Rosenfeld static void
atr_data_hexdump_historical(atr_data_t * data,FILE * out)1496*a61ed2ceSHans Rosenfeld atr_data_hexdump_historical(atr_data_t *data, FILE *out)
1497*a61ed2ceSHans Rosenfeld {
1498*a61ed2ceSHans Rosenfeld (void) fprintf(out, "Dumping raw historical bytes\n");
1499*a61ed2ceSHans Rosenfeld
1500*a61ed2ceSHans Rosenfeld atr_data_hexdump(data->atr_historic, data->atr_nhistoric, out);
1501*a61ed2ceSHans Rosenfeld }
1502*a61ed2ceSHans Rosenfeld
1503*a61ed2ceSHans Rosenfeld static void
atr_data_dump_historical(atr_data_t * data,FILE * out)1504*a61ed2ceSHans Rosenfeld atr_data_dump_historical(atr_data_t *data, FILE *out)
1505*a61ed2ceSHans Rosenfeld {
1506*a61ed2ceSHans Rosenfeld uint8_t cat;
1507*a61ed2ceSHans Rosenfeld
1508*a61ed2ceSHans Rosenfeld (void) fprintf(out, "Historic Data: %u bytes", data->atr_nhistoric);
1509*a61ed2ceSHans Rosenfeld if (data->atr_nhistoric == 0) {
1510*a61ed2ceSHans Rosenfeld (void) fprintf(out, "\n");
1511*a61ed2ceSHans Rosenfeld return;
1512*a61ed2ceSHans Rosenfeld }
1513*a61ed2ceSHans Rosenfeld
1514*a61ed2ceSHans Rosenfeld cat = data->atr_historic[0];
1515*a61ed2ceSHans Rosenfeld (void) fprintf(out, "; format (0x%02x) ", cat);
1516*a61ed2ceSHans Rosenfeld if (cat == ATR_HIST_CAT_MAND_STATUS) {
1517*a61ed2ceSHans Rosenfeld (void) fprintf(out, "card status, not shown");
1518*a61ed2ceSHans Rosenfeld } else if (cat == ATR_HIST_CAT_TLV_STATUS) {
1519*a61ed2ceSHans Rosenfeld (void) fprintf(out, "COMPACT-TLV, not shown");
1520*a61ed2ceSHans Rosenfeld } else if (cat >= ATR_HIST_CAT_RFU_MIN && cat <= ATR_HIST_CAT_RFU_MAX) {
1521*a61ed2ceSHans Rosenfeld (void) fprintf(out, "reserved\n");
1522*a61ed2ceSHans Rosenfeld atr_data_hexdump_historical(data, out);
1523*a61ed2ceSHans Rosenfeld return;
1524*a61ed2ceSHans Rosenfeld } else {
1525*a61ed2ceSHans Rosenfeld (void) fprintf(out, "proprietary\n");
1526*a61ed2ceSHans Rosenfeld atr_data_hexdump_historical(data, out);
1527*a61ed2ceSHans Rosenfeld return;
1528*a61ed2ceSHans Rosenfeld }
1529*a61ed2ceSHans Rosenfeld }
1530*a61ed2ceSHans Rosenfeld
1531*a61ed2ceSHans Rosenfeld void
atr_data_dump(atr_data_t * data,FILE * out)1532*a61ed2ceSHans Rosenfeld atr_data_dump(atr_data_t *data, FILE *out)
1533*a61ed2ceSHans Rosenfeld {
1534*a61ed2ceSHans Rosenfeld uint8_t i, level;
1535*a61ed2ceSHans Rosenfeld if ((data->atr_flags & ATR_F_VALID) == 0)
1536*a61ed2ceSHans Rosenfeld return;
1537*a61ed2ceSHans Rosenfeld
1538*a61ed2ceSHans Rosenfeld (void) fprintf(out, "TS 0x%02u - ", data->atr_raw[0]);
1539*a61ed2ceSHans Rosenfeld if (data->atr_flags & ATR_F_USES_DIRECT) {
1540*a61ed2ceSHans Rosenfeld (void) fprintf(out, "direct convention\n");
1541*a61ed2ceSHans Rosenfeld } else {
1542*a61ed2ceSHans Rosenfeld (void) fprintf(out, "inverse convention\n");
1543*a61ed2ceSHans Rosenfeld }
1544*a61ed2ceSHans Rosenfeld
1545*a61ed2ceSHans Rosenfeld level = 0;
1546*a61ed2ceSHans Rosenfeld for (i = 0; i < data->atr_nti; i++) {
1547*a61ed2ceSHans Rosenfeld atr_ti_t *atp = &data->atr_ti[i];
1548*a61ed2ceSHans Rosenfeld
1549*a61ed2ceSHans Rosenfeld /*
1550*a61ed2ceSHans Rosenfeld * Various protocols may appear multiple times, indicating
1551*a61ed2ceSHans Rosenfeld * different sets of bits each time. When dealing with T0 and
1552*a61ed2ceSHans Rosenfeld * TD1, the protocol doesn't matter. Otherwise if we have the
1553*a61ed2ceSHans Rosenfeld * same value, we should increment this.
1554*a61ed2ceSHans Rosenfeld */
1555*a61ed2ceSHans Rosenfeld if (i <= 2) {
1556*a61ed2ceSHans Rosenfeld level = 0;
1557*a61ed2ceSHans Rosenfeld } else if (atp->atrti_protocol ==
1558*a61ed2ceSHans Rosenfeld data->atr_ti[i - 1].atrti_protocol) {
1559*a61ed2ceSHans Rosenfeld level++;
1560*a61ed2ceSHans Rosenfeld } else {
1561*a61ed2ceSHans Rosenfeld level = 0;
1562*a61ed2ceSHans Rosenfeld }
1563*a61ed2ceSHans Rosenfeld
1564*a61ed2ceSHans Rosenfeld if (i == 0) {
1565*a61ed2ceSHans Rosenfeld (void) fprintf(out, "T0 ");
1566*a61ed2ceSHans Rosenfeld } else {
1567*a61ed2ceSHans Rosenfeld (void) fprintf(out, "TD%u ", i);
1568*a61ed2ceSHans Rosenfeld }
1569*a61ed2ceSHans Rosenfeld (void) fprintf(out, "0x%02x\n",
1570*a61ed2ceSHans Rosenfeld data->atr_raw[atp->atrti_td_idx]);
1571*a61ed2ceSHans Rosenfeld (void) fprintf(out, " |+-> ");
1572*a61ed2ceSHans Rosenfeld if (i == 0) {
1573*a61ed2ceSHans Rosenfeld (void) fprintf(out, "%u historical bytes\n",
1574*a61ed2ceSHans Rosenfeld data->atr_nhistoric);
1575*a61ed2ceSHans Rosenfeld } else {
1576*a61ed2ceSHans Rosenfeld (void) fprintf(out, "protocol T=%u\n",
1577*a61ed2ceSHans Rosenfeld atp->atrti_protocol);
1578*a61ed2ceSHans Rosenfeld }
1579*a61ed2ceSHans Rosenfeld (void) fprintf(out, " v\n");
1580*a61ed2ceSHans Rosenfeld (void) fprintf(out, " 0r%u%u%u%u\n",
1581*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TD ? 1 : 0,
1582*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TC ? 1 : 0,
1583*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TB ? 1 : 0,
1584*a61ed2ceSHans Rosenfeld atp->atrti_flags & ATR_TI_HAVE_TA ? 1 : 0);
1585*a61ed2ceSHans Rosenfeld
1586*a61ed2ceSHans Rosenfeld atr_data_dump_ta(atp, out, level);
1587*a61ed2ceSHans Rosenfeld atr_data_dump_tb(atp, out, level);
1588*a61ed2ceSHans Rosenfeld atr_data_dump_tc(atp, out, level);
1589*a61ed2ceSHans Rosenfeld if (atp->atrti_flags & ATR_TI_HAVE_TD) {
1590*a61ed2ceSHans Rosenfeld (void) fprintf(out, " v\n");
1591*a61ed2ceSHans Rosenfeld }
1592*a61ed2ceSHans Rosenfeld }
1593*a61ed2ceSHans Rosenfeld
1594*a61ed2ceSHans Rosenfeld atr_data_dump_historical(data, out);
1595*a61ed2ceSHans Rosenfeld
1596*a61ed2ceSHans Rosenfeld if (data->atr_flags & ATR_F_HAS_CHECKSUM) {
1597*a61ed2ceSHans Rosenfeld (void) fprintf(out, "TCK 0x%02x\n", data->atr_cksum);
1598*a61ed2ceSHans Rosenfeld } else {
1599*a61ed2ceSHans Rosenfeld (void) fprintf(out, "TCK ----; Checksum not present\n");
1600*a61ed2ceSHans Rosenfeld }
1601*a61ed2ceSHans Rosenfeld
1602*a61ed2ceSHans Rosenfeld }
1603*a61ed2ceSHans Rosenfeld #endif /* _KERNEL */
1604