1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019, Joyent, Inc.
14  */
15 
16 #ifndef _SYS_USB_CCID_H
17 #define	_SYS_USB_CCID_H
18 
19 /*
20  * CCID class driver definitions.
21  */
22 
23 #include <sys/stdint.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /*
30  * Values for various Hardware, Mechanical, and Pin features. These come from
31  * the device's class descriptor.
32  */
33 typedef enum ccid_class_voltage {
34 	CCID_CLASS_VOLT_AUTO	= 0x00,
35 	CCID_CLASS_VOLT_5_0	= 0x01,
36 	CCID_CLASS_VOLT_3_0	= 0x02,
37 	CCID_CLASS_VOLT_1_8	= 0x04
38 } ccid_class_voltage_t;
39 
40 typedef enum ccid_class_mechanical {
41 	CCID_CLASS_MECH_CARD_ACCEPT	= 0x01,
42 	CCID_CLASS_MECH_CARD_EJECT	= 0x02,
43 	CCID_CLASS_MECH_CARD_CAPTURE	= 0x04,
44 	CCID_CLASS_MECH_CARD_LOCK	= 0x08
45 } ccid_class_mechanical_t;
46 
47 typedef enum ccid_class_features {
48 	CCID_CLASS_F_AUTO_PARAM_ATR	= 0x00000002,
49 	CCID_CLASS_F_AUTO_ICC_ACTIVATE	= 0x00000004,
50 	CCID_CLASS_F_AUTO_ICC_VOLTAGE	= 0x00000008,
51 	CCID_CLASS_F_AUTO_ICC_CLOCK	= 0x00000010,
52 	CCID_CLASS_F_AUTO_BAUD		= 0x00000020,
53 	CCID_CLASS_F_AUTO_PARAM_NEG	= 0x00000040,
54 	CCID_CLASS_F_AUTO_PPS		= 0x00000080,
55 	CCID_CLASS_F_ICC_CLOCK_STOP	= 0x00000100,
56 	CCID_CLASS_F_ALTNAD_SUP		= 0x00000200,
57 	CCID_CLASS_F_AUTO_IFSD		= 0x00000400,
58 	CCID_CLASS_F_TPDU_XCHG		= 0x00010000,
59 	CCID_CLASS_F_SHORT_APDU_XCHG	= 0x00020000,
60 	CCID_CLASS_F_EXT_APDU_XCHG	= 0x00040000,
61 	CCID_CLASS_F_WAKE_UP		= 0x00100000
62 } ccid_class_features_t;
63 
64 typedef enum ccid_class_pin {
65 	CCID_CLASS_PIN_VERIFICATION	= 0x01,
66 	CCID_CLASS_PIN_MODIFICATION	= 0x02
67 } ccid_class_pin_t;
68 
69 /*
70  * CCID Class Descriptor
71  *
72  * This structure represents the CCID class descriptor. Note, it should not be a
73  * packed structure. This is designed to be a native representation. The raw
74  * structure will be parsed into this instead.
75  */
76 typedef struct ccid_class_descr {
77 	uint8_t		ccd_bLength;
78 	uint8_t		ccd_bDescriptorType;
79 	uint16_t	ccd_bcdCCID;
80 	uint8_t		ccd_bMaxSlotIndex;
81 	uint8_t		ccd_bVoltageSupport;
82 	uint32_t	ccd_dwProtocols;
83 	uint32_t	ccd_dwDefaultClock;
84 	uint32_t	ccd_dwMaximumClock;
85 	uint8_t		ccd_bNumClockSupported;
86 	uint32_t	ccd_dwDataRate;
87 	uint32_t	ccd_dwMaxDataRate;
88 	uint8_t		ccd_bNumDataRatesSupported;
89 	uint32_t	ccd_dwMaxIFSD;
90 	uint32_t	ccd_dwSyncProtocols;
91 	uint32_t	ccd_dwMechanical;
92 	uint32_t	ccd_dwFeatures;
93 	uint32_t	ccd_dwMaxCCIDMessageLength;
94 	uint8_t		ccd_bClassGetResponse;
95 	uint8_t		ccd_bClassEnvelope;
96 	uint16_t	ccd_wLcdLayout;
97 	uint8_t		ccd_bPinSupport;
98 	uint8_t		ccd_bMaxCCIDBusySlots;
99 } ccid_class_descr_t;
100 
101 /*
102  * Definitions for the supported versions of the CCID specification. The version
103  * is encoded in binary encoded decimal. The major version is in the upper 8
104  * bits and the minor version is in the lower 8 bits. We currently check for the
105  * major version to match.
106  */
107 #define	CCID_VERSION_MAJOR(ver)	(((ver) & 0xff00) >> 8)
108 #define	CCID_VERSION_MINOR(ver)	((ver) & 0x00ff)
109 #define	CCID_VERSION_ONE	0x01
110 
111 /*
112  * This structure is used as the data for the CCID_REQUEST_SET_PARAMS request
113  * and the CCID_RESPONSE_PARAMETERS response. There are different structures for
114  * T=0 and T=1. These come from CCID r1.1 / Section 6.1.7.
115  */
116 typedef struct ccid_params_t0 {
117 	uint8_t cp0_bmFindexDindex;
118 	uint8_t cp0_bmTCCKST0;
119 	uint8_t cp0_bGuardTimeT0;
120 	uint8_t cp0_bWaitingIntegerT0;
121 	uint8_t	cp0_bClockStop;
122 } __packed ccid_params_t0_t;
123 
124 #define	CCID_P_TCCKST0_DIRECT	0x00
125 #define	CCID_P_TCCKST0_INVERSE	0x02
126 
127 typedef struct ccid_params_t1 {
128 	uint8_t cp1_bmFindexDindex;
129 	uint8_t cp1_bmTCCKST1;
130 	uint8_t cp1_bGuardTimeT1;
131 	uint8_t cp1_bmWaitingIntegersT1;
132 	uint8_t cp1_bClockStop;
133 	uint8_t cp1_bIFSC;
134 	uint8_t cp1_bNadValue;
135 } __packed ccid_params_t1_t;
136 
137 typedef union ccid_params {
138 	ccid_params_t0_t ccp_t0;
139 	ccid_params_t1_t ccp_t1;
140 } ccid_params_t;
141 
142 #define	CCID_P_FI_DI(fi, di)	((((fi) & 0x0f) << 4) | ((di) & 0x0f))
143 
144 /*
145  * Everything below this point is reserved for the kernel.
146  */
147 #ifdef	_KERNEL
148 
149 /*
150  * These values come from CCID r1.1.0 Table 5.1-1 'Smart Card Device
151  * Descriptors'
152  */
153 #define	CCID_DESCR_TYPE		0x21
154 #define	CCID_DESCR_LENGTH	0x36
155 
156 
157 /*
158  * Minimum and maximum value for a sequence number in the CCID specification.
159  * The sequence is a 1 byte unsigned value. The values are inclusive. We reserve
160  * the value of 0x00 so that we can use it as a sentinel in the ccid_command_t
161  * structure to know when we should or shouldn't free a command structure's
162  * sequence number back to the id space.
163  */
164 #define	CCID_SEQ_MIN	0x01
165 #define	CCID_SEQ_MAX	UINT8_MAX
166 
167 
168 /*
169  * All structures from the specification must be packed.
170  */
171 
172 /*
173  * Interrupt-IN messages codes.
174  */
175 typedef enum ccid_intr_code {
176 	CCID_INTR_CODE_SLOT_CHANGE	= 0x50,
177 	CCID_INTR_CODE_HW_ERROR		= 0x51
178 } ccid_intr_code_t;
179 
180 typedef enum ccid_intr_hwerr_code {
181 	CCID_INTR_HWERR_OVERCURRENT	= 0x01
182 } ccid_intr_hwerr_code_t;
183 
184 typedef struct ccid_intr_slot {
185 	uint8_t	cis_type;
186 	uint8_t	cis_state[];
187 } ccid_intr_slot_t;
188 
189 typedef struct ccid_intr_hwerr {
190 	uint8_t	cih_type;
191 	uint8_t	cih_slot;
192 	uint8_t	cih_seq;
193 	uint8_t	cih_code;
194 } ccid_intr_hwerr_t;
195 
196 /*
197  * Message request codes. These codes are based on CCID r1.1.0 Table 6.1-1
198  * 'Summary of Bulk-Out Messages'. The name from the standard is to the right of
199  * the enum.
200  */
201 typedef enum ccid_request_code {
202 	CCID_REQUEST_POWER_ON		= 0x62,	/* PC_to_RDR_IccPowerOn */
203 	CCID_REQUEST_POWER_OFF		= 0x63,	/* PC_to_RDR_IccPowerOff */
204 	CCID_REQUEST_SLOT_STATUS	= 0x65,	/* PC_to_RDR_GetSlotStatus */
205 	CCID_REQUEST_TRANSFER_BLOCK	= 0x6f,	/* PC_to_RDR_XfrBlock */
206 	CCID_REQUEST_GET_PARAMS		= 0x6c,	/* PC_to_RDR_GetParameters */
207 	CCID_REQUEST_RESET_PARAMS	= 0x6d,	/* PC_to_RDR_ResetParameters */
208 	CCID_REQUEST_SET_PARAMS		= 0x61,	/* PC_to_RDR_SetParameters */
209 	CCID_REQUEST_ESCAPE		= 0x6b,	/* PC_to_RDR_Escape */
210 	CCID_REQUEST_ICC_CLOCK		= 0x6e,	/* PC_to_RDR_IccClock */
211 	CCID_REQUEST_T0APDU		= 0x6a,	/* PC_to_RDR_T0APDU */
212 	CCID_REQUEST_SECURE		= 0x69,	/* PC_to_RDR_Secure */
213 	CCID_REQUEST_MECHANICAL		= 0x71,	/* PC_to_RDR_Mechanica */
214 	CCID_REQEUST_ABORT		= 0x72,	/* PC_to_RDR_Abort */
215 	CCID_REQUEST_DATA_CLOCK		= 0x73	/* PC_to_RDR_SetDataRateAnd */
216 						/* ClockFrequency */
217 } ccid_request_code_t;
218 
219 /*
220  * Message request codes. These codes are based on CCID r1.1.0 Table 6.2-1
221  * 'Summary of Bulk-In Messages'. The name from the standard is to the right of
222  * the enum.
223  */
224 typedef enum ccid_response_code {
225 	CCID_RESPONSE_DATA_BLOCK	= 0x80,	/* RDR_to_PC_DataBlock */
226 	CCID_RESPONSE_SLOT_STATUS	= 0x81,	/* RDR_to_PC_SlotStatus */
227 	CCID_RESPONSE_PARAMETERS	= 0x82, /* RDR_to_PC_Parameters */
228 	CCID_RESPONSE_ESCAPE		= 0x83,	/* RDR_to_PC_Escape */
229 	CCID_RESPONSE_DATA_CLOCK	= 0x84	/* RDR_to_PC_DataRateAnd */
230 						/* ClockFrequency */
231 } ccid_response_code_t;
232 
233 /*
234  * This represents the CCID command header that is used for every request and
235  * response.
236  */
237 typedef struct ccid_header {
238 	uint8_t		ch_mtype;
239 	uint32_t	ch_length;	/* Length of ch_data in bytes */
240 	uint8_t		ch_slot;	/* CCID slot to target */
241 	uint8_t		ch_seq;		/* Request/Response sequence num */
242 	uint8_t		ch_param0;	/* Request/Response specific */
243 	uint8_t		ch_param1;	/* Request/Response specific */
244 	uint8_t		ch_param2;	/* Request/Response specific */
245 	uint8_t		ch_data[];	/* Optional Request/Response Data */
246 } __packed ccid_header_t;
247 
248 /*
249  * This structure is used as the data for the CCID_REQUEST_DATA_CLOCK and
250  * CCID_RESPONSE_DATA_CLOCK commands.
251  */
252 typedef struct ccid_data_clock {
253 	uint32_t	cdc_clock;
254 	uint32_t	cdc_data;
255 } __packed ccid_data_clock_t;
256 
257 /*
258  * Macros and constants to take apart the slot status (in ch_param1) when a CCID
259  * reply comes in.
260  */
261 #define	CCID_REPLY_ICC(x)	(x & 0x3)
262 #define	CCID_REPLY_STATUS(x)	((x & 0xc0) >> 6)
263 
264 typedef enum {
265 	CCID_REPLY_ICC_ACTIVE = 0,
266 	CCID_REPLY_ICC_INACTIVE,
267 	CCID_REPLY_ICC_MISSING
268 } ccid_reply_icc_status_t;
269 
270 typedef enum {
271 	CCID_REPLY_STATUS_COMPLETE = 0,
272 	CCID_REPLY_STATUS_FAILED,
273 	CCID_REPLY_STATUS_MORE_TIME
274 } ccid_reply_command_status_t;
275 
276 /*
277  * Errors that are defined based when commands fail. These are based on CCID
278  * r.1.1.0 Table 6.2-2 'Slot error register when bmCommandStatus = 1'.
279  */
280 typedef enum ccid_command_err {
281 	CCID_ERR_CMD_ABORTED			= 0xff,
282 	CCID_ERR_ICC_MUTE			= 0xfe,
283 	CCID_ERR_XFR_PARITY_ERROR		= 0xfd,
284 	CCID_ERR_XFR_OVERRUN			= 0xfc,
285 	CCID_ERR_HW_ERROR			= 0xfb,
286 	CCID_ERR_BAD_ATR_TS			= 0xf8,
287 	CCID_ERR_BAD_ATR_TCK			= 0xf7,
288 	CCID_ERR_ICC_PROTOCOL_NOT_SUPPORTED	= 0xf6,
289 	CCID_ERR_ICC_CLASS_NOT_SUPPORTED	= 0xf5,
290 	CCID_ERR_PROCEDURE_BYTE_CONFLICT	= 0xf4,
291 	CCID_ERR_DEACTIVATED_PROTOCOL		= 0xf3,
292 	CCID_ERR_BUSY_WITH_AUTO_SEQUENCE	= 0xf2,
293 	CCID_ERR_PIN_TIMEOUT			= 0xf0,
294 	CCID_ERR_PIN_CANCELLED			= 0xef,
295 	CCID_ERR_CMD_SLOT_BUSY			= 0xe0,
296 	CCID_ERR_CMD_NOT_SUPPORTED		= 0x00
297 } ccid_command_err_t;
298 
299 /*
300  * Maximum size of an APDU (application data unit) payload. There are both short
301  * and extended ADPUs. At this time, we only support the short ADPUs.
302  */
303 #define	CCID_APDU_LEN_MAX	261
304 
305 #endif	/* _KERNEL */
306 
307 #ifdef __cplusplus
308 }
309 #endif
310 
311 #endif /* _SYS_USB_CCID_H */
312