blob: 190227a5d454b80bf63326c30c8d5db97c104785 [file] [log] [blame]
Christina Quastb123d742014-12-23 13:03:36 +01001/* ----------------------------------------------------------------------------
Christina Quastf51e0d22015-01-03 21:51:24 +01002 * ATMEL Microcontroller Software Support
Christina Quastb123d742014-12-23 13:03:36 +01003 * ----------------------------------------------------------------------------
4 * Copyright (c) 2008, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
Christina Quastf51e0d22015-01-03 21:51:24 +010030//------------------------------------------------------------------------------
31/// \unit
32///
33/// !Purpose
34///
35/// CCID driver
36///
37/// !Usage
38///
39/// Explanation on the usage of the code made available through the header file.
40//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +010041
Christina Quastf51e0d22015-01-03 21:51:24 +010042//------------------------------------------------------------------------------
43// Headers
44//------------------------------------------------------------------------------
45
46#include <board.h>
47#include <USBDDriver.h>
48#include <USBRequests.h>
49#include <USBDescriptors.h>
50//#include <usb/device/dfu/dfu.h>
51#include <cciddriverdescriptors.h>
52
53// FIXME: Remove DFU related stuff
54/* no DFU bootloader is being used */
55#define DFU_NUM_IF 0
56#define DFU_IF_DESCRIPTORS_STRUCT
57#define DFU_IF_DESCRIPTORS
58
59#define DFU_NUM_STRINGS 0
60#define DFU_STRING_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +010061
62
Christina Quastf51e0d22015-01-03 21:51:24 +010063//------------------------------------------------------------------------------
64// Local definition
65//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +010066
Christina Quastf51e0d22015-01-03 21:51:24 +010067/// Constants: IDs: Device product ID.
68//#define CCIDDriverDescriptors_PRODUCTID 0x6129
69#define CCIDDriverDescriptors_PRODUCTID SIMTRACE_PRODUCT_ID
70/// Constants: IDs: Device vendor ID.
71#define CCIDDriverDescriptors_VENDORID ATMEL_VENDOR_ID
72//#define CCIDDriverDescriptors_VENDORID 0x03EB
73/// Constants: IDs: Device release number.
Christina Quastb123d742014-12-23 13:03:36 +010074#define CCIDDriverDescriptors_RELEASE 0x0100
75
Christina Quastf51e0d22015-01-03 21:51:24 +010076/// Returns the minimum between two values.
Christina Quastb123d742014-12-23 13:03:36 +010077#define MIN(a, b) ((a < b) ? a : b)
78
Christina Quastf51e0d22015-01-03 21:51:24 +010079//------------------------------------------------------------------------------
80// Types
81//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +010082
Christina Quastf51e0d22015-01-03 21:51:24 +010083/// CCIDDriverConfiguration Descriptors
84/// List of descriptors that make up the configuration descriptors of a
85/// device using the CCID driver.
Christina Quastb123d742014-12-23 13:03:36 +010086typedef struct {
87
Christina Quastf51e0d22015-01-03 21:51:24 +010088 /// Configuration descriptor
89 USBConfigurationDescriptor configuration;
90 /// Interface descriptor
91 USBInterfaceDescriptor interface;
92 /// CCID descriptor
93 CCIDDescriptor ccid;
94 /// Bulk OUT endpoint descriptor
95 USBEndpointDescriptor bulkOut;
96 /// Bulk IN endpoint descriptor
97 USBEndpointDescriptor bulkIn;
98 /// Interrupt OUT endpoint descriptor
99 USBEndpointDescriptor interruptIn;
100 DFU_IF_DESCRIPTORS_STRUCT
101} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
102
103//------------------------------------------------------------------------------
104// Types
105//------------------------------------------------------------------------------
106
107/// Driver structure for an CCID device
108typedef struct {
109
110 /// Standard USB device driver instance
Christina Quastb123d742014-12-23 13:03:36 +0100111 USBDDriver usbdDriver;
Christina Quastf51e0d22015-01-03 21:51:24 +0100112 /// CCID message
Christina Quastb123d742014-12-23 13:03:36 +0100113 S_ccid_bulk_in_header sCcidMessage;
Christina Quastf51e0d22015-01-03 21:51:24 +0100114 /// CCID command
Christina Quastb123d742014-12-23 13:03:36 +0100115 S_ccid_bulk_out_header sCcidCommand;
Christina Quastf51e0d22015-01-03 21:51:24 +0100116 /// Interrupt message answer
Christina Quastb123d742014-12-23 13:03:36 +0100117 unsigned char BufferINT[4];
Christina Quastf51e0d22015-01-03 21:51:24 +0100118 /// Buffer data of message
Christina Quastb123d742014-12-23 13:03:36 +0100119 unsigned char ProtocolDataStructure[10];
Christina Quastf51e0d22015-01-03 21:51:24 +0100120 /// Protocol used
Christina Quastb123d742014-12-23 13:03:36 +0100121 unsigned char bProtocol;
Christina Quastf51e0d22015-01-03 21:51:24 +0100122 /// SlotStatus
123 /// Bit 0 = Slot 0 current state
124 /// Bit 1 = Slot 0 changed status
125 /// Bit 2 = Slot 1 current state
126 /// Bit 3 = Slot 1 changed status
127 /// Bit 4 = Slot 2 current state
128 /// Bit 5 = Slot 2 changed status
Christina Quastb123d742014-12-23 13:03:36 +0100129 unsigned char SlotStatus;
130
131} CCIDDriver;
132
Christina Quastf51e0d22015-01-03 21:51:24 +0100133//------------------------------------------------------------------------------
134// Local variables
135//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100136
Christina Quastf51e0d22015-01-03 21:51:24 +0100137/// Static instance of the CCID device driver.
Christina Quastb123d742014-12-23 13:03:36 +0100138static CCIDDriver ccidDriver;
139
Christina Quastf51e0d22015-01-03 21:51:24 +0100140/// Standard USB device descriptor.
Christina Quastb123d742014-12-23 13:03:36 +0100141static const USBDeviceDescriptor deviceDescriptor = {
142
143 sizeof(USBDeviceDescriptor),
144 USBGenericDescriptor_DEVICE,
145 USBDeviceDescriptor_USB2_00,
146 0,
147 0,
148 0,
Christina Quastf51e0d22015-01-03 21:51:24 +0100149 BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
Christina Quastb123d742014-12-23 13:03:36 +0100150 CCIDDriverDescriptors_VENDORID,
151 CCIDDriverDescriptors_PRODUCTID,
152 CCIDDriverDescriptors_RELEASE,
Christina Quastf51e0d22015-01-03 21:51:24 +0100153 1, // Index of manufacturer description
154 2, // Index of product description
155 3, // Index of serial number description
156 1 // One possible configuration
Christina Quastb123d742014-12-23 13:03:36 +0100157};
158
159
Christina Quastf51e0d22015-01-03 21:51:24 +0100160/// List of configuration descriptors.
Christina Quastb123d742014-12-23 13:03:36 +0100161static const CCIDDriverConfigurationDescriptors configurationDescriptorsFS = {
162
Christina Quastf51e0d22015-01-03 21:51:24 +0100163 // Standard USB configuration descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100164 {
165 sizeof(USBConfigurationDescriptor),
166 USBGenericDescriptor_CONFIGURATION,
167 sizeof(CCIDDriverConfigurationDescriptors),
Christina Quastf51e0d22015-01-03 21:51:24 +0100168 1+DFU_NUM_IF, // One interface in this configuration
169 1, // This is configuration #1
170 0, // No associated string descriptor
171 BOARD_USB_BMATTRIBUTES,
Christina Quastb123d742014-12-23 13:03:36 +0100172 USBConfigurationDescriptor_POWER(100)
173 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100174 // CCID interface descriptor
175 // Table 4.3-1 Interface Descriptor
176 // Interface descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100177 {
178 sizeof(USBInterfaceDescriptor),
179 USBGenericDescriptor_INTERFACE,
Christina Quastf51e0d22015-01-03 21:51:24 +0100180 0, // Interface 0
181 0, // No alternate settings
182 3, // uses bulk-IN, bulk-OUT and interrupt–IN
Christina Quastb123d742014-12-23 13:03:36 +0100183 SMART_CARD_DEVICE_CLASS,
Christina Quastf51e0d22015-01-03 21:51:24 +0100184 0, // Subclass code
185 0, // bulk transfers optional interrupt-IN
186 0 // No associated string descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100187 },
188 {
Christina Quastf51e0d22015-01-03 21:51:24 +0100189 sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
190 CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
191 CCID1_10, // bcdCCID: CCID version
192 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
193 VOLTS_5_0, // bVoltageSupport
194 (1 << PROTOCOL_TO), // dwProtocols
195 3580, // dwDefaultClock
196 3580, // dwMaxClock
197 0, // bNumClockSupported
198 9600, // dwDataRate : 9600 bauds
199 9600, // dwMaxDataRate : 9600 bauds
200 0, // bNumDataRatesSupported
201 0xfe, // dwMaxIFSD
202 0, // dwSynchProtocols
203 0, // dwMechanical
204 //0x00010042, // dwFeatures: Short APDU level exchanges
205 CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
Christina Quastb123d742014-12-23 13:03:36 +0100206 CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
Christina Quastf51e0d22015-01-03 21:51:24 +0100207 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
208 0xFF, // bClassGetResponse: Echoes the class of the APDU
209 0xFF, // bClassEnvelope: Echoes the class of the APDU
210 0, // wLcdLayout: no LCD
211 0, // bPINSupport: No PIN
212 1 // bMaxCCIDBusySlot
Christina Quastb123d742014-12-23 13:03:36 +0100213 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100214 // Bulk-OUT endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100215 {
216 sizeof(USBEndpointDescriptor),
217 USBGenericDescriptor_ENDPOINT,
218 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
219 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100220 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
Christina Quastb123d742014-12-23 13:03:36 +0100221 USBEndpointDescriptor_MAXBULKSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100222 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100223 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100224 // Bulk-IN endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100225 {
226 sizeof(USBEndpointDescriptor),
227 USBGenericDescriptor_ENDPOINT,
228 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
229 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100230 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
Christina Quastb123d742014-12-23 13:03:36 +0100231 USBEndpointDescriptor_MAXBULKSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100232 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100233 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100234 // Notification endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100235 {
236 sizeof(USBEndpointDescriptor),
237 USBGenericDescriptor_ENDPOINT,
238 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
239 USBEndpointDescriptor_INTERRUPT,
Christina Quastf51e0d22015-01-03 21:51:24 +0100240 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
Christina Quastb123d742014-12-23 13:03:36 +0100241 USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100242 0x10
243 },
244 DFU_IF_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +0100245};
246
Christina Quastf51e0d22015-01-03 21:51:24 +0100247#ifdef BOARD_USB_UDPHS
Christina Quastb123d742014-12-23 13:03:36 +0100248static const CCIDDriverConfigurationDescriptors configurationDescriptorsHS = {
249
Christina Quastf51e0d22015-01-03 21:51:24 +0100250 // Standard USB configuration descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100251 {
252 sizeof(USBConfigurationDescriptor),
253 USBGenericDescriptor_CONFIGURATION,
254 sizeof(CCIDDriverConfigurationDescriptors),
Christina Quastf51e0d22015-01-03 21:51:24 +0100255 1+DFU_NUM_IF, // One interface in this configuration
256 1, // This is configuration #1
257 0, // No associated string descriptor
258 BOARD_USB_BMATTRIBUTES,
Christina Quastb123d742014-12-23 13:03:36 +0100259 USBConfigurationDescriptor_POWER(100)
260 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100261 // CCID interface descriptor
262 // Table 4.3-1 Interface Descriptor
263 // Interface descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100264 {
265 sizeof(USBInterfaceDescriptor),
266 USBGenericDescriptor_INTERFACE,
Christina Quastf51e0d22015-01-03 21:51:24 +0100267 0, // Interface 0
268 0, // No alternate settings
269 3, // uses bulk-IN, bulk-OUT and interrupt–IN
Christina Quastb123d742014-12-23 13:03:36 +0100270 SMART_CARD_DEVICE_CLASS,
Christina Quastf51e0d22015-01-03 21:51:24 +0100271 0, // Subclass code
272 0, // bulk transfers optional interrupt-IN
273 0 // No associated string descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100274 },
275 {
Christina Quastf51e0d22015-01-03 21:51:24 +0100276 sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
277 CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
278 CCID1_10, // bcdCCID: CCID version
279 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
280 VOLTS_5_0, // bVoltageSupport
281 (1 << PROTOCOL_TO), // dwProtocols
282 3580, // dwDefaultClock
283 3580, // dwMaxClock
284 0, // bNumClockSupported
285 9600, // dwDataRate : 9600 bauds
286 9600, // dwMaxDataRate : 9600 bauds
287 0, // bNumDataRatesSupported
288 0xfe, // dwMaxIFSD
289 0, // dwSynchProtocols
290 0, // dwMechanical
291 //0x00010042, // dwFeatures: Short APDU level exchanges
292 CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
Christina Quastb123d742014-12-23 13:03:36 +0100293 CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
Christina Quastf51e0d22015-01-03 21:51:24 +0100294 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
295 0xFF, // bClassGetResponse: Echoes the class of the APDU
296 0xFF, // bClassEnvelope: Echoes the class of the APDU
297 0, // wLcdLayout: no LCD
298 0, // bPINSupport: No PIN
299 1 // bMaxCCIDBusySlot
Christina Quastb123d742014-12-23 13:03:36 +0100300 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100301 // Bulk-OUT endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100302 {
303 sizeof(USBEndpointDescriptor),
304 USBGenericDescriptor_ENDPOINT,
305 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
306 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100307 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
Christina Quastb123d742014-12-23 13:03:36 +0100308 USBEndpointDescriptor_MAXBULKSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100309 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100310 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100311 // Bulk-IN endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100312 {
313 sizeof(USBEndpointDescriptor),
314 USBGenericDescriptor_ENDPOINT,
315 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
316 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100317 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
Christina Quastb123d742014-12-23 13:03:36 +0100318 USBEndpointDescriptor_MAXBULKSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100319 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100320 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100321 // Notification endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100322 {
323 sizeof(USBEndpointDescriptor),
324 USBGenericDescriptor_ENDPOINT,
325 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
326 USBEndpointDescriptor_INTERRUPT,
Christina Quastf51e0d22015-01-03 21:51:24 +0100327 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
Christina Quastb123d742014-12-23 13:03:36 +0100328 USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100329 0x10
330 },
331 DFU_IF_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +0100332};
333
Christina Quastf51e0d22015-01-03 21:51:24 +0100334/// Qualifier descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100335const USBDeviceQualifierDescriptor deviceQualifierDescriptor = {
336
Christina Quastf51e0d22015-01-03 21:51:24 +0100337 sizeof(USBDeviceQualifierDescriptor), // Size of this descriptor in bytes
338 USBGenericDescriptor_DEVICEQUALIFIER, // Qualifier Descriptor Type
339 USBDeviceDescriptor_USB2_00, // USB specification 2.00
340 0x00, // Class is specified in interface
341 0x00, // Subclass is specified in interface
342 0x00, // Protocol is specified in interface
343 BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
344 0x01, // One possible configuration
345 0x00 // Reserved for future use, must be zero
Christina Quastb123d742014-12-23 13:03:36 +0100346};
347
Christina Quastf51e0d22015-01-03 21:51:24 +0100348/// OtherSpeed configuration descriptor in Full Speed mode
Christina Quastb123d742014-12-23 13:03:36 +0100349static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationFS = {
350
Christina Quastf51e0d22015-01-03 21:51:24 +0100351 // Standard USB configuration descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100352 {
353 sizeof(USBConfigurationDescriptor),
354 USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
355 sizeof(CCIDDriverConfigurationDescriptors),
Christina Quastf51e0d22015-01-03 21:51:24 +0100356 1+DFU_NUM_IF, // One interface in this configuration
357 1, // This is configuration #1
358 0, // No associated string descriptor
359 BOARD_USB_BMATTRIBUTES,
Christina Quastb123d742014-12-23 13:03:36 +0100360 USBConfigurationDescriptor_POWER(100)
361 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100362 // CCID interface descriptor
363 // Table 4.3-1 Interface Descriptor
364 // Interface descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100365 {
366 sizeof(USBInterfaceDescriptor),
367 USBGenericDescriptor_INTERFACE,
Christina Quastf51e0d22015-01-03 21:51:24 +0100368 0, // Interface 0
369 0, // No alternate settings
370 3, // uses bulk-IN, bulk-OUT and interrupt–IN
Christina Quastb123d742014-12-23 13:03:36 +0100371 SMART_CARD_DEVICE_CLASS,
Christina Quastf51e0d22015-01-03 21:51:24 +0100372 0, // Subclass code
373 0, // bulk transfers optional interrupt-IN
374 0 // No associated string descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100375 },
376 {
Christina Quastf51e0d22015-01-03 21:51:24 +0100377 sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
378 CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
379 CCID1_10, // bcdCCID: CCID version
380 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
381 VOLTS_5_0, // bVoltageSupport
382 (1 << PROTOCOL_TO), // dwProtocols
383 3580, // dwDefaultClock
384 3580, // dwMaxClock
385 0, // bNumClockSupported
386 9600, // dwDataRate : 9600 bauds
387 9600, // dwMaxDataRate : 9600 bauds
388 0, // bNumDataRatesSupported
389 0xfe, // dwMaxIFSD
390 0, // dwSynchProtocols
391 0, // dwMechanical
392 //0x00010042, // dwFeatures: Short APDU level exchanges
393 CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
Christina Quastb123d742014-12-23 13:03:36 +0100394 CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
Christina Quastf51e0d22015-01-03 21:51:24 +0100395 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
396 0xFF, // bClassGetResponse: Echoes the class of the APDU
397 0xFF, // bClassEnvelope: Echoes the class of the APDU
398 0, // wLcdLayout: no LCD
399 0, // bPINSupport: No PIN
400 1 // bMaxCCIDBusySlot
Christina Quastb123d742014-12-23 13:03:36 +0100401 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100402 // Bulk-OUT endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100403 {
404 sizeof(USBEndpointDescriptor),
405 USBGenericDescriptor_ENDPOINT,
406 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
407 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100408 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
Christina Quastb123d742014-12-23 13:03:36 +0100409 USBEndpointDescriptor_MAXBULKSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100410 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100411 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100412 // Bulk-IN endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100413 {
414 sizeof(USBEndpointDescriptor),
415 USBGenericDescriptor_ENDPOINT,
416 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
417 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100418 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
Christina Quastb123d742014-12-23 13:03:36 +0100419 USBEndpointDescriptor_MAXBULKSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100420 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100421 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100422 // Notification endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100423 {
424 sizeof(USBEndpointDescriptor),
425 USBGenericDescriptor_ENDPOINT,
426 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
427 USBEndpointDescriptor_INTERRUPT,
Christina Quastf51e0d22015-01-03 21:51:24 +0100428 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
Christina Quastb123d742014-12-23 13:03:36 +0100429 USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100430 0x10
431 },
432 DFU_IF_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +0100433};
434
Christina Quastf51e0d22015-01-03 21:51:24 +0100435/// OtherSpeed configuration descriptor in High Speed mode
Christina Quastb123d742014-12-23 13:03:36 +0100436static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationHS = {
437
Christina Quastf51e0d22015-01-03 21:51:24 +0100438 // Standard USB configuration descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100439 {
440 sizeof(USBConfigurationDescriptor),
441 USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
442 sizeof(CCIDDriverConfigurationDescriptors),
Christina Quastf51e0d22015-01-03 21:51:24 +0100443 1+DFU_NUM_IF, // One interface in this configuration
444 1, // This is configuration #1
445 0, // No associated string descriptor
446 BOARD_USB_BMATTRIBUTES,
Christina Quastb123d742014-12-23 13:03:36 +0100447 USBConfigurationDescriptor_POWER(100)
448 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100449 // CCID interface descriptor
450 // Table 4.3-1 Interface Descriptor
451 // Interface descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100452 {
453 sizeof(USBInterfaceDescriptor),
454 USBGenericDescriptor_INTERFACE,
Christina Quastf51e0d22015-01-03 21:51:24 +0100455 0, // Interface 0
456 0, // No alternate settings
457 3, // uses bulk-IN, bulk-OUT and interrupt–IN
Christina Quastb123d742014-12-23 13:03:36 +0100458 SMART_CARD_DEVICE_CLASS,
Christina Quastf51e0d22015-01-03 21:51:24 +0100459 0, // Subclass code
460 0, // bulk transfers optional interrupt-IN
461 0 // No associated string descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100462 },
463 {
Christina Quastf51e0d22015-01-03 21:51:24 +0100464 sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
465 CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
466 CCID1_10, // bcdCCID: CCID version
467 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
468 VOLTS_5_0, // bVoltageSupport
469 (1 << PROTOCOL_TO), // dwProtocols
470 3580, // dwDefaultClock
471 3580, // dwMaxClock
472 0, // bNumClockSupported
473 9600, // dwDataRate : 9600 bauds
474 9600, // dwMaxDataRate : 9600 bauds
475 0, // bNumDataRatesSupported
476 0xfe, // dwMaxIFSD
477 0, // dwSynchProtocols
478 0, // dwMechanical
479 //0x00010042, // dwFeatures: Short APDU level exchanges
480 CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
481 CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
482 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
483 0xFF, // bClassGetResponse: Echoes the class of the APDU
484 0xFF, // bClassEnvelope: Echoes the class of the APDU
485 0, // wLcdLayout: no LCD
486 0, // bPINSupport: No PIN
487 1 // bMaxCCIDBusySlot
Christina Quastb123d742014-12-23 13:03:36 +0100488 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100489 // Bulk-OUT endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100490 {
491 sizeof(USBEndpointDescriptor),
492 USBGenericDescriptor_ENDPOINT,
493 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
494 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100495 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
Christina Quastb123d742014-12-23 13:03:36 +0100496 USBEndpointDescriptor_MAXBULKSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100497 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100498 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100499 // Bulk-IN endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100500 {
501 sizeof(USBEndpointDescriptor),
502 USBGenericDescriptor_ENDPOINT,
503 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
504 USBEndpointDescriptor_BULK,
Christina Quastf51e0d22015-01-03 21:51:24 +0100505 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
Christina Quastb123d742014-12-23 13:03:36 +0100506 USBEndpointDescriptor_MAXBULKSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100507 0x00 // Does not apply to Bulk endpoints
Christina Quastb123d742014-12-23 13:03:36 +0100508 },
Christina Quastf51e0d22015-01-03 21:51:24 +0100509 // Notification endpoint descriptor
Christina Quastb123d742014-12-23 13:03:36 +0100510 {
511 sizeof(USBEndpointDescriptor),
512 USBGenericDescriptor_ENDPOINT,
513 USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
514 USBEndpointDescriptor_INTERRUPT,
Christina Quastf51e0d22015-01-03 21:51:24 +0100515 MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
Christina Quastb123d742014-12-23 13:03:36 +0100516 USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
Christina Quastf51e0d22015-01-03 21:51:24 +0100517 0x10
518 },
519 DFU_IF_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +0100520};
521#endif
522
Christina Quastf51e0d22015-01-03 21:51:24 +0100523/// Language ID string descriptor.
Christina Quastb123d742014-12-23 13:03:36 +0100524static const unsigned char languageIdDescriptor[] = {
525
526 USBStringDescriptor_LENGTH(1),
527 USBGenericDescriptor_STRING,
528 USBStringDescriptor_ENGLISH_US
529};
530
Christina Quastf51e0d22015-01-03 21:51:24 +0100531/// Manufacturer name.
Christina Quastb123d742014-12-23 13:03:36 +0100532static const unsigned char manufacturerDescriptor[] = {
533
534 USBStringDescriptor_LENGTH(5),
535 USBGenericDescriptor_STRING,
536 USBStringDescriptor_UNICODE('A'),
537 USBStringDescriptor_UNICODE('T'),
538 USBStringDescriptor_UNICODE('M'),
539 USBStringDescriptor_UNICODE('E'),
540 USBStringDescriptor_UNICODE('L')
541};
542
Christina Quastf51e0d22015-01-03 21:51:24 +0100543/// Product name.
Christina Quastb123d742014-12-23 13:03:36 +0100544static const unsigned char productDescriptor[] = {
545
546 USBStringDescriptor_LENGTH(23),
547 USBGenericDescriptor_STRING,
548 USBStringDescriptor_UNICODE('A'),
549 USBStringDescriptor_UNICODE('T'),
550 USBStringDescriptor_UNICODE('M'),
551 USBStringDescriptor_UNICODE('E'),
552 USBStringDescriptor_UNICODE('L'),
553 USBStringDescriptor_UNICODE(' '),
554 USBStringDescriptor_UNICODE('A'),
555 USBStringDescriptor_UNICODE('T'),
556 USBStringDescriptor_UNICODE('9'),
557 USBStringDescriptor_UNICODE('1'),
558 USBStringDescriptor_UNICODE(' '),
559 USBStringDescriptor_UNICODE('C'),
560 USBStringDescriptor_UNICODE('C'),
561 USBStringDescriptor_UNICODE('I'),
562 USBStringDescriptor_UNICODE('D'),
563 USBStringDescriptor_UNICODE(' '),
564 USBStringDescriptor_UNICODE('D'),
565 USBStringDescriptor_UNICODE('R'),
566 USBStringDescriptor_UNICODE('I'),
567 USBStringDescriptor_UNICODE('V'),
568 USBStringDescriptor_UNICODE('E'),
569 USBStringDescriptor_UNICODE('R'),
570 USBStringDescriptor_UNICODE(' ')
571};
572
Christina Quastf51e0d22015-01-03 21:51:24 +0100573/// Product serial number.
Christina Quastb123d742014-12-23 13:03:36 +0100574static const unsigned char serialNumberDescriptor[] = {
575
576 USBStringDescriptor_LENGTH(12),
577 USBGenericDescriptor_STRING,
578 USBStringDescriptor_UNICODE('0'),
579 USBStringDescriptor_UNICODE('1'),
580 USBStringDescriptor_UNICODE('2'),
581 USBStringDescriptor_UNICODE('3'),
582 USBStringDescriptor_UNICODE('4'),
583 USBStringDescriptor_UNICODE('5'),
584 USBStringDescriptor_UNICODE('6'),
585 USBStringDescriptor_UNICODE('7'),
586 USBStringDescriptor_UNICODE('8'),
587 USBStringDescriptor_UNICODE('9'),
588 USBStringDescriptor_UNICODE('A'),
589 USBStringDescriptor_UNICODE('F')
590};
591
Christina Quastf51e0d22015-01-03 21:51:24 +0100592/// Array of pointers to string descriptors.
Christina Quastb123d742014-12-23 13:03:36 +0100593static const unsigned char *stringDescriptors[] = {
594
595 languageIdDescriptor,
596 manufacturerDescriptor,
597 productDescriptor,
Christina Quastf51e0d22015-01-03 21:51:24 +0100598 serialNumberDescriptor,
599 DFU_STRING_DESCRIPTORS
Christina Quastb123d742014-12-23 13:03:36 +0100600};
601
602
Christina Quastf51e0d22015-01-03 21:51:24 +0100603/// List of standard descriptors for the serial driver.
Christina Quastb123d742014-12-23 13:03:36 +0100604const USBDDriverDescriptors ccidDriverDescriptors = {
605
Christina Quastf51e0d22015-01-03 21:51:24 +0100606 &deviceDescriptor, // FS
607 (USBConfigurationDescriptor *) &configurationDescriptorsFS ,
608#ifdef BOARD_USB_UDPHS
609 (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // FS
610 { (USBConfigurationDescriptor *) &sOtherSpeedConfigurationFS },
611 &deviceDescriptor, // HS
612 { (USBConfigurationDescriptor *) &configurationDescriptorsHS },
613 (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // HS
614 { (USBConfigurationDescriptor *) &sOtherSpeedConfigurationHS },
Christina Quastb123d742014-12-23 13:03:36 +0100615#else
Christina Quastf51e0d22015-01-03 21:51:24 +0100616 0, // No qualifier descriptor FS
617 0, // No other-speed configuration FS
618 0, // No device descriptor HS
619 0, // No configuration HS
620 0, // No qualifier descriptor HS
621 0, // No other-speed configuration HS
Christina Quastb123d742014-12-23 13:03:36 +0100622#endif
623 stringDescriptors,
Christina Quastf51e0d22015-01-03 21:51:24 +0100624 4+DFU_NUM_STRINGS // Four string descriptors in array
Christina Quastb123d742014-12-23 13:03:36 +0100625};
626
Christina Quastf51e0d22015-01-03 21:51:24 +0100627//------------------------------------------------------------------------------
628// Internal functions
629//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100630
Christina Quastf51e0d22015-01-03 21:51:24 +0100631//------------------------------------------------------------------------------
632/// Response Pipe, Bulk-IN Messages
633/// Return the Slot Status to the host
634/// Answer to:
635/// PC_to_RDR_IccPowerOff
636/// PC_to_RDR_GetSlotStatus
637/// PC_to_RDR_IccClock
638/// PC_to_RDR_T0APDU
639/// PC_to_RDR_Mechanical
640/// PC_to_RDR_Abort and Class specific ABORT request
641//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100642static void RDRtoPCSlotStatus( void )
643{
Christina Quastf51e0d22015-01-03 21:51:24 +0100644 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100645
Christina Quastf51e0d22015-01-03 21:51:24 +0100646 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100647 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
648 ccidDriver.sCcidMessage.wLength = 0;
649 ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
650 ccidDriver.sCcidMessage.bError = 0;
Christina Quastf51e0d22015-01-03 21:51:24 +0100651 // 00h Clock running
652 // 01h Clock stopped in state L
653 // 02h Clock stopped in state H
654 // 03h Clock stopped in an unknown state
655 // All other values are Reserved for Future Use.
Christina Quastb123d742014-12-23 13:03:36 +0100656 ccidDriver.sCcidMessage.bSpecific = 0;
657}
658
Christina Quastf51e0d22015-01-03 21:51:24 +0100659//------------------------------------------------------------------------------
660/// Response Pipe, Bulk-IN Messages
661/// Answer to PC_to_RDR_IccPowerOn
662//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100663static void RDRtoPCDatablock_ATR( void )
664{
665 unsigned char i;
666 unsigned char Atr[ATR_SIZE_MAX];
667 unsigned char length;
Christina Quast8d0f4a62015-01-15 14:53:38 +0100668 uint32_t status;
Christina Quastb123d742014-12-23 13:03:36 +0100669
Christina Quast8d0f4a62015-01-15 14:53:38 +0100670 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100671
Christina Quast8d0f4a62015-01-15 14:53:38 +0100672 status = ISO7816_Datablock_ATR( Atr, &length );
673 if (status == 0) {
674 TRACE_DEBUG("Timeout occured while reading ATR");
675// FIXME: react properly to timeout..
676// return;
677 }
Christina Quastb123d742014-12-23 13:03:36 +0100678
679 if( length > 5 ) {
Christina Quastf51e0d22015-01-03 21:51:24 +0100680 ccidDriver.ProtocolDataStructure[1] = Atr[5]&0x0F; // TD(1)
681 ccidDriver.bProtocol = Atr[5]&0x0F; // TD(1)
Christina Quastb123d742014-12-23 13:03:36 +0100682 }
683
Christina Quastf51e0d22015-01-03 21:51:24 +0100684 // S_ccid_protocol_t0
685 // bmFindexDindex
686 ccidDriver.ProtocolDataStructure[0] = Atr[2]; // TA(1)
Christina Quastb123d742014-12-23 13:03:36 +0100687
Christina Quastf51e0d22015-01-03 21:51:24 +0100688 // bmTCCKST0
689 // For T=0 ,B0 – 0b, B7-2 – 000000b
690 // B1 – Convention used (b1=0 for direct, b1=1 for inverse)
Christina Quastb123d742014-12-23 13:03:36 +0100691
Christina Quastf51e0d22015-01-03 21:51:24 +0100692 // bGuardTimeT0
693 // Extra Guardtime between two characters. Add 0 to 254 etu to the normal
694 // guardtime of 12etu. FFh is the same as 00h.
695 ccidDriver.ProtocolDataStructure[2] = Atr[4]; // TC(1)
696 // AT91C_BASE_US0->US_TTGR = 0; // TC1
Christina Quastb123d742014-12-23 13:03:36 +0100697
Christina Quastf51e0d22015-01-03 21:51:24 +0100698 // bWaitingIntegerT0
699 // WI for T=0 used to define WWT
700 ccidDriver.ProtocolDataStructure[3] = Atr[7]; // TC(2)
Christina Quastb123d742014-12-23 13:03:36 +0100701
Christina Quastf51e0d22015-01-03 21:51:24 +0100702 // bClockStop
703 // ICC Clock Stop Support
704 // 00 = Stopping the Clock is not allowed
705 // 01 = Stop with Clock signal Low
706 // 02 = Stop with Clock signal High
707 // 03 = Stop with Clock either High or Low
708 ccidDriver.ProtocolDataStructure[4] = 0x00; // 0 to 3
Christina Quastb123d742014-12-23 13:03:36 +0100709
Christina Quastf51e0d22015-01-03 21:51:24 +0100710 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100711 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
Christina Quastf51e0d22015-01-03 21:51:24 +0100712 ccidDriver.sCcidMessage.wLength = length; // Size of ATR
713 ccidDriver.sCcidMessage.bSizeToSend += length; // Size of ATR
714 // bChainParameter: 00 the response APDU begins and ends in this command
Christina Quastb123d742014-12-23 13:03:36 +0100715 ccidDriver.sCcidMessage.bSpecific = 0;
716
717 for( i=0; i<length; i++ ) {
718
719 ccidDriver.sCcidMessage.abData[i] = Atr[i];
720 }
721
Christina Quastf51e0d22015-01-03 21:51:24 +0100722 // Set the slot to an active status
Christina Quastb123d742014-12-23 13:03:36 +0100723 ccidDriver.sCcidMessage.bStatus = 0;
724 ccidDriver.sCcidMessage.bError = 0;
725}
726
Christina Quastf51e0d22015-01-03 21:51:24 +0100727//------------------------------------------------------------------------------
728/// Response Pipe, Bulk-IN Messages
729/// In other cases, the response message has the following format:
730/// The response data will contain the optional data returned by the ICC,
731/// followed by the 2 byte-size status words SW1-SW2.
732///
733/// Answer to:
734/// PC_to_RDR_XfrBlock
735/// PC_to_RDR_Secure
736//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100737static void RDRtoPCDatablock( void )
738{
Christina Quastf51e0d22015-01-03 21:51:24 +0100739 //TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100740
Christina Quastf51e0d22015-01-03 21:51:24 +0100741 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100742 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
743 ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
Christina Quastf51e0d22015-01-03 21:51:24 +0100744 // bChainParameter: 00 the response APDU begins and ends in this command
Christina Quastb123d742014-12-23 13:03:36 +0100745 ccidDriver.sCcidMessage.bSpecific = 0;
746
Christina Quastf51e0d22015-01-03 21:51:24 +0100747 // Set the slot to an active status
Christina Quastb123d742014-12-23 13:03:36 +0100748 ccidDriver.sCcidMessage.bStatus = 0;
749 ccidDriver.sCcidMessage.bError = 0;
750}
751
Christina Quastf51e0d22015-01-03 21:51:24 +0100752//------------------------------------------------------------------------------
753/// Response Pipe, Bulk-IN Messages
754/// Answer to:
755/// PC_to_RDR_GetParameters
756/// PC_to_RDR_ResetParameters
757/// PC_to_RDR_SetParameters
758//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100759static void RDRtoPCParameters( void )
760{
761 unsigned int i;
762
Christina Quastf51e0d22015-01-03 21:51:24 +0100763 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100764
Christina Quastf51e0d22015-01-03 21:51:24 +0100765 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100766 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_PARAMETERS;
767
Christina Quastf51e0d22015-01-03 21:51:24 +0100768 //ccidDriver.sCcidMessage.bStatus = 0;
Christina Quastb123d742014-12-23 13:03:36 +0100769 ccidDriver.sCcidMessage.bError = 0;
770
771 if( ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO ) {
772
Christina Quastf51e0d22015-01-03 21:51:24 +0100773 // T=0
Christina Quastb123d742014-12-23 13:03:36 +0100774 ccidDriver.sCcidMessage.wLength = sizeof(S_ccid_protocol_t0);
775 ccidDriver.sCcidMessage.bSpecific = PROTOCOL_TO;
776 }
777 else {
778
Christina Quastf51e0d22015-01-03 21:51:24 +0100779 // T=1
Christina Quastb123d742014-12-23 13:03:36 +0100780 ccidDriver.sCcidMessage.wLength = sizeof(S_ccid_protocol_t1);
781 ccidDriver.sCcidMessage.bSpecific = PROTOCOL_T1;
782 }
783
784 ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
785
786 for( i=0; i<ccidDriver.sCcidMessage.wLength; i++ ) {
787 ccidDriver.sCcidMessage.abData[i] = ccidDriver.ProtocolDataStructure[i];
788 }
789
790}
791
Christina Quastf51e0d22015-01-03 21:51:24 +0100792//------------------------------------------------------------------------------
793/// Response Pipe, Bulk-IN Messages
794/// Answer to:
795/// PC_to_RDR_Escape
796//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100797static void RDRtoPCEscape( unsigned char length, unsigned char *data_send_from_CCID )
798{
799 unsigned int i;
800
Christina Quastf51e0d22015-01-03 21:51:24 +0100801 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100802
Christina Quastf51e0d22015-01-03 21:51:24 +0100803 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100804 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_ESCAPE;
805
806 ccidDriver.sCcidMessage.wLength = length;
807
808 ccidDriver.sCcidMessage.bStatus = 0;
809 ccidDriver.sCcidMessage.bError = 0;
810
Christina Quastf51e0d22015-01-03 21:51:24 +0100811 ccidDriver.sCcidMessage.bSpecific = 0; // bRFU
Christina Quastb123d742014-12-23 13:03:36 +0100812
813 for( i=0; i<length; i++ ) {
814 ccidDriver.sCcidMessage.abData[i] = data_send_from_CCID[i];
815 }
816}
817
Christina Quastf51e0d22015-01-03 21:51:24 +0100818//------------------------------------------------------------------------------
819/// Response Pipe, Bulk-IN Messages
820/// Answer to:
821/// PC_to_RDR_SetDataRateAndClockFrequency
822//------------------------------------------------------------------------------
823static void RDRtoPCDataRateAndClockFrequency( unsigned int dwClockFrequency,
Christina Quastb123d742014-12-23 13:03:36 +0100824 unsigned int dwDataRate )
825{
Christina Quastf51e0d22015-01-03 21:51:24 +0100826 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100827
Christina Quastf51e0d22015-01-03 21:51:24 +0100828 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +0100829 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATARATEANDCLOCKFREQUENCY;
830
831 ccidDriver.sCcidMessage.wLength = 8;
832
833 ccidDriver.sCcidMessage.bStatus = 0;
834 ccidDriver.sCcidMessage.bError = 0;
835
Christina Quastf51e0d22015-01-03 21:51:24 +0100836 ccidDriver.sCcidMessage.bSpecific = 0; // bRFU
Christina Quastb123d742014-12-23 13:03:36 +0100837
838 ccidDriver.sCcidMessage.abData[0] = dwClockFrequency;
Christina Quastf51e0d22015-01-03 21:51:24 +0100839
Christina Quastb123d742014-12-23 13:03:36 +0100840 ccidDriver.sCcidMessage.abData[4] = dwDataRate;
841}
842
Christina Quastf51e0d22015-01-03 21:51:24 +0100843//------------------------------------------------------------------------------
844/// Command Pipe, Bulk-OUT Messages
845/// Power On Command - Cold Reset & Warm Reset
846/// Return the ATR to the host
847//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100848static void PCtoRDRIccPowerOn( void )
849{
Christina Quastf51e0d22015-01-03 21:51:24 +0100850 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100851
852 if( CCID_FEATURES_AUTO_VOLT == (configurationDescriptorsFS.ccid.dwFeatures & CCID_FEATURES_AUTO_VOLT) ) {
853
Christina Quastf51e0d22015-01-03 21:51:24 +0100854 // bPowerSelect = ccidDriver.sCcidCommand.bSpecific_0;
Christina Quastb123d742014-12-23 13:03:36 +0100855 ccidDriver.sCcidCommand.bSpecific_0 = VOLTS_AUTO;
856 }
857
Christina Quastf6bf3492015-01-15 14:42:04 +0100858 ISO7816_warm_reset();
859// ISO7816_cold_reset();
Christina Quastb123d742014-12-23 13:03:36 +0100860
Christina Quastf51e0d22015-01-03 21:51:24 +0100861 // for emulation only //JCB
Christina Quastb123d742014-12-23 13:03:36 +0100862 if ( ccidDriver.sCcidCommand.bSpecific_0 != VOLTS_5_0 ) {
863
864 TRACE_ERROR("POWER_NOT_SUPPORTED\n\r");
865 }
866
867 else {
868
869 RDRtoPCDatablock_ATR();
870
871 }
872}
873
Christina Quastf51e0d22015-01-03 21:51:24 +0100874//------------------------------------------------------------------------------
875/// Command Pipe, Bulk-OUT Messages
876/// Power Off Command - Set the ICC in an inactive state
877/// Return the slot status to the host
878//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100879static void PCtoRDRIccPowerOff( void )
880{
881 unsigned char bStatus;
882
Christina Quastf51e0d22015-01-03 21:51:24 +0100883 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100884
885 ISO7816_IccPowerOff();
886
Christina Quastf51e0d22015-01-03 21:51:24 +0100887 //JCB stub
Christina Quastb123d742014-12-23 13:03:36 +0100888 bStatus = ICC_BS_PRESENT_NOTACTIVATED;
889
Christina Quastf51e0d22015-01-03 21:51:24 +0100890 // Set the slot to an inactive status
Christina Quastb123d742014-12-23 13:03:36 +0100891 ccidDriver.sCcidMessage.bStatus = 0;
892 ccidDriver.sCcidMessage.bError = 0;
893
Christina Quastf51e0d22015-01-03 21:51:24 +0100894 // if error, see Table 6.1-2 errors
Christina Quastb123d742014-12-23 13:03:36 +0100895
Christina Quastf51e0d22015-01-03 21:51:24 +0100896 // Return the slot status to the host
Christina Quastb123d742014-12-23 13:03:36 +0100897 RDRtoPCSlotStatus();
898}
899
Christina Quastf51e0d22015-01-03 21:51:24 +0100900//------------------------------------------------------------------------------
901/// Command Pipe, Bulk-OUT Messages
902/// Get slot status
903//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100904static void PCtoRDRGetSlotStatus( void )
905{
Christina Quastf51e0d22015-01-03 21:51:24 +0100906 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100907
908 ccidDriver.sCcidMessage.bStatus = 0;
909 ccidDriver.sCcidMessage.bError = 0;
910
Christina Quastf51e0d22015-01-03 21:51:24 +0100911 // Return the slot status to the host
Christina Quastb123d742014-12-23 13:03:36 +0100912 RDRtoPCSlotStatus();
913}
914
Christina Quastf51e0d22015-01-03 21:51:24 +0100915//------------------------------------------------------------------------------
916/// Command Pipe, Bulk-OUT Messages
917/// If the command header is valid, an APDU command is received and can be read
918/// by the application
919//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100920static void PCtoRDRXfrBlock( void )
921{
922 unsigned char indexMessage = 0;
Christina Quastb123d742014-12-23 13:03:36 +0100923
Christina Quastf51e0d22015-01-03 21:51:24 +0100924 //TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100925
Christina Quastf51e0d22015-01-03 21:51:24 +0100926 // Check the block length
Christina Quastb123d742014-12-23 13:03:36 +0100927 if ( ccidDriver.sCcidCommand.wLength > (configurationDescriptorsFS.ccid.dwMaxCCIDMessageLength-10) ) {
928
929 ccidDriver.sCcidMessage.bStatus = 1;
930 ccidDriver.sCcidMessage.bError = 0;
931 }
Christina Quastf51e0d22015-01-03 21:51:24 +0100932 // check bBWI
Christina Quastb123d742014-12-23 13:03:36 +0100933 else if ( 0 != ccidDriver.sCcidCommand.bSpecific_0 ) {
934
935 TRACE_ERROR("Bad bBWI\n\r");
936 }
937 else {
938
Christina Quastf51e0d22015-01-03 21:51:24 +0100939 // APDU or TPDU
940 switch(configurationDescriptorsFS.ccid.dwFeatures
Christina Quastb123d742014-12-23 13:03:36 +0100941 & (CCID_FEATURES_EXC_TPDU|CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU)) {
942
943 case CCID_FEATURES_EXC_TPDU:
944 if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) {
945
Christina Quastf51e0d22015-01-03 21:51:24 +0100946 // Send commande APDU
947 indexMessage = ISO7816_XfrBlockTPDU_T0( ccidDriver.sCcidCommand.APDU ,
948 ccidDriver.sCcidMessage.abData,
Christina Quastb123d742014-12-23 13:03:36 +0100949 ccidDriver.sCcidCommand.wLength );
950 }
951 else {
952 if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_T1) {
953 TRACE_INFO("Not supported T=1\n\r");
954 }
955 else {
956 TRACE_INFO("Not supported\n\r");
957 }
958 }
959 break;
960
961 case CCID_FEATURES_EXC_APDU:
962 TRACE_INFO("Not supported\n\r");
963 break;
964
965 default:
966 break;
967 }
968
969 }
970
971 ccidDriver.sCcidMessage.wLength = indexMessage;
Christina Quastf51e0d22015-01-03 21:51:24 +0100972 TRACE_DEBUG("USB: 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\n\r", ccidDriver.sCcidMessage.abData[0],
973 ccidDriver.sCcidMessage.abData[1],
974 ccidDriver.sCcidMessage.abData[2],
Christina Quastb123d742014-12-23 13:03:36 +0100975 ccidDriver.sCcidMessage.abData[3],
976 ccidDriver.sCcidMessage.abData[4] );
977 RDRtoPCDatablock();
978
979}
980
Christina Quastf51e0d22015-01-03 21:51:24 +0100981//------------------------------------------------------------------------------
982/// Command Pipe, Bulk-OUT Messages
983/// return parameters by the command: RDR_to_PC_Parameters
984//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +0100985static void PCtoRDRGetParameters( void )
986{
Christina Quastf51e0d22015-01-03 21:51:24 +0100987 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +0100988
Christina Quastf51e0d22015-01-03 21:51:24 +0100989 // We support only one slot
Christina Quastb123d742014-12-23 13:03:36 +0100990
Christina Quastf51e0d22015-01-03 21:51:24 +0100991 // bmIccStatus
Christina Quastb123d742014-12-23 13:03:36 +0100992 if( ISO7816_StatusReset() ) {
Christina Quastf51e0d22015-01-03 21:51:24 +0100993 // 0: An ICC is present and active (power is on and stable, RST is inactive
Christina Quastb123d742014-12-23 13:03:36 +0100994 ccidDriver.sCcidMessage.bStatus = 0;
995 }
996 else {
Christina Quastf51e0d22015-01-03 21:51:24 +0100997 // 1: An ICC is present and inactive (not activated or shut down by hardware error)
Christina Quastb123d742014-12-23 13:03:36 +0100998 ccidDriver.sCcidMessage.bStatus = 1;
999 }
1000
1001 RDRtoPCParameters();
1002}
1003
Christina Quastf51e0d22015-01-03 21:51:24 +01001004//------------------------------------------------------------------------------
1005/// Command Pipe, Bulk-OUT Messages
1006/// This command resets the slot parameters to their default values
1007//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001008static void PCtoRDRResetParameters( void )
1009{
Christina Quastf51e0d22015-01-03 21:51:24 +01001010 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001011
1012 ccidDriver.SlotStatus = ICC_NOT_PRESENT;
1013 ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
1014
1015 RDRtoPCParameters();
1016}
1017
Christina Quastf51e0d22015-01-03 21:51:24 +01001018//------------------------------------------------------------------------------
1019/// Command Pipe, Bulk-OUT Messages
1020/// This command is used to change the parameters for a given slot.
1021//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001022static void PCtoRDRSetParameters( void )
1023{
Christina Quastf51e0d22015-01-03 21:51:24 +01001024 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001025
1026 ccidDriver.SlotStatus = ccidDriver.sCcidCommand.bSlot;
1027 ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
Christina Quastf51e0d22015-01-03 21:51:24 +01001028 // Not all feature supported
Christina Quastb123d742014-12-23 13:03:36 +01001029
1030 RDRtoPCParameters();
1031}
1032
Christina Quastf51e0d22015-01-03 21:51:24 +01001033//------------------------------------------------------------------------------
1034/// Command Pipe, Bulk-OUT Messages
1035/// This command allows the CCID manufacturer to define and access extended
1036/// features.
1037/// Information sent via this command is processed by the CCID control logic.
1038//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001039static void PCtoRDREscape( void )
1040{
Christina Quastf51e0d22015-01-03 21:51:24 +01001041 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001042
Christina Quastf51e0d22015-01-03 21:51:24 +01001043 // If needed by the user
Christina Quastb123d742014-12-23 13:03:36 +01001044 ISO7816_Escape();
1045
Christina Quastf51e0d22015-01-03 21:51:24 +01001046 // stub, return all value send
1047 RDRtoPCEscape( ccidDriver.sCcidCommand.wLength, ccidDriver.sCcidCommand.APDU);
Christina Quastb123d742014-12-23 13:03:36 +01001048}
1049
Christina Quastf51e0d22015-01-03 21:51:24 +01001050//------------------------------------------------------------------------------
1051/// Command Pipe, Bulk-OUT Messages
1052/// This command stops or restarts the clock.
1053//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001054static void PCtoRDRICCClock( void )
1055{
Christina Quastf51e0d22015-01-03 21:51:24 +01001056 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001057
1058 if( 0 == ccidDriver.sCcidCommand.bSpecific_0 ) {
Christina Quastf51e0d22015-01-03 21:51:24 +01001059 // restarts the clock
Christina Quastb123d742014-12-23 13:03:36 +01001060 ISO7816_RestartClock();
1061 }
1062 else {
Christina Quastf51e0d22015-01-03 21:51:24 +01001063 // stop clock in the state shown in the bClockStop field
Christina Quastb123d742014-12-23 13:03:36 +01001064 ISO7816_StopClock();
1065 }
1066
Christina Quastf51e0d22015-01-03 21:51:24 +01001067 RDRtoPCSlotStatus( );
Christina Quastb123d742014-12-23 13:03:36 +01001068}
1069
Christina Quastf51e0d22015-01-03 21:51:24 +01001070//------------------------------------------------------------------------------
1071/// Command Pipe, Bulk-OUT Messages
1072/// This command changes the parameters used to perform the transportation of
1073/// APDU messages by the T=0 protocol.
1074//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001075static void PCtoRDRtoAPDU( void )
1076{
1077 unsigned char bmChanges;
1078 unsigned char bClassGetResponse;
1079 unsigned char bClassEnvelope;
1080
Christina Quastf51e0d22015-01-03 21:51:24 +01001081 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001082
1083 if( configurationDescriptorsFS.ccid.dwFeatures == (CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU) ) {
1084
1085 bmChanges = ccidDriver.sCcidCommand.bSpecific_0;
1086 bClassGetResponse = ccidDriver.sCcidCommand.bSpecific_1;
1087 bClassEnvelope = ccidDriver.sCcidCommand.bSpecific_2;
1088
1089 ISO7816_toAPDU();
1090 }
1091
Christina Quastf51e0d22015-01-03 21:51:24 +01001092 RDRtoPCSlotStatus();
Christina Quastb123d742014-12-23 13:03:36 +01001093}
1094
Christina Quastf51e0d22015-01-03 21:51:24 +01001095//------------------------------------------------------------------------------
1096/// Command Pipe, Bulk-OUT Messages
1097/// This is a command message to allow entering the PIN for verification or
1098/// modification.
1099//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001100static void PCtoRDRSecure( void )
1101{
Christina Quastf51e0d22015-01-03 21:51:24 +01001102 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001103
1104 TRACE_DEBUG("For user\n\r");
1105}
1106
Christina Quastf51e0d22015-01-03 21:51:24 +01001107//------------------------------------------------------------------------------
1108/// Command Pipe, Bulk-OUT Messages
1109/// This command is used to manage motorized type CCID functionality.
1110/// The Lock Card function is used to hold the ICC.
1111/// This prevents an ICC from being easily removed from the CCID.
1112/// The Unlock Card function is used to remove the hold initiated by the Lock
1113/// Card function
1114//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001115static void PCtoRDRMechanical( void )
1116{
Christina Quastf51e0d22015-01-03 21:51:24 +01001117 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001118 TRACE_DEBUG("Not implemented\n\r");
1119
1120 RDRtoPCSlotStatus();
1121}
1122
Christina Quastf51e0d22015-01-03 21:51:24 +01001123//------------------------------------------------------------------------------
1124/// Command Pipe, Bulk-OUT Messages
1125/// This command is used with the Control pipe Abort request to tell the CCID
1126/// to stop any current transfer at the specified slot and return to a state
1127/// where the slot is ready to accept a new command pipe Bulk-OUT message.
1128//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001129static void PCtoRDRAbort( void )
1130{
Christina Quastf51e0d22015-01-03 21:51:24 +01001131 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001132
1133 RDRtoPCSlotStatus();
1134}
1135
Christina Quastf51e0d22015-01-03 21:51:24 +01001136//------------------------------------------------------------------------------
1137/// Command Pipe, Bulk-OUT Messages
1138/// This command is used to manually set the data rate and clock frequency of
1139/// a specific slot.
1140//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001141static void PCtoRDRSetDataRateAndClockFrequency( void )
1142{
1143 unsigned int dwClockFrequency;
1144 unsigned int dwDataRate;
1145
Christina Quastf51e0d22015-01-03 21:51:24 +01001146 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001147
1148 dwClockFrequency = ccidDriver.sCcidCommand.APDU[0]
1149 + (ccidDriver.sCcidCommand.APDU[1]<<8)
1150 + (ccidDriver.sCcidCommand.APDU[2]<<16)
1151 + (ccidDriver.sCcidCommand.APDU[3]<<24);
1152
1153 dwDataRate = ccidDriver.sCcidCommand.APDU[4]
1154 + (ccidDriver.sCcidCommand.APDU[5]<<8)
1155 + (ccidDriver.sCcidCommand.APDU[6]<<16)
1156 + (ccidDriver.sCcidCommand.APDU[7]<<24);
1157
1158 ISO7816_SetDataRateandClockFrequency( dwClockFrequency, dwDataRate );
1159
1160 RDRtoPCDataRateAndClockFrequency( dwClockFrequency, dwDataRate );
1161
1162}
1163
Christina Quastf51e0d22015-01-03 21:51:24 +01001164//------------------------------------------------------------------------------
1165/// Report the CMD_NOT_SUPPORTED error to the host
1166//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001167static void vCCIDCommandNotSupported( void )
1168{
Christina Quastf51e0d22015-01-03 21:51:24 +01001169 // Command not supported
1170 // vCCIDReportError(CMD_NOT_SUPPORTED);
Christina Quastb123d742014-12-23 13:03:36 +01001171
1172 TRACE_DEBUG("CMD_NOT_SUPPORTED\n\r");
1173
Christina Quastf51e0d22015-01-03 21:51:24 +01001174 // Header fields settings
Christina Quastb123d742014-12-23 13:03:36 +01001175 ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
1176 ccidDriver.sCcidMessage.wLength = 0;
1177 ccidDriver.sCcidMessage.bSpecific = 0;
1178
1179 ccidDriver.sCcidMessage.bStatus |= ICC_CS_FAILED;
1180
Christina Quastf51e0d22015-01-03 21:51:24 +01001181 // Send the response to the host
1182 //vCCIDSendResponse();
Christina Quastb123d742014-12-23 13:03:36 +01001183}
1184
Christina Quastf51e0d22015-01-03 21:51:24 +01001185//------------------------------------------------------------------------------
1186/// Sent CCID response on USB
1187//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001188static void vCCIDSendResponse( void )
1189{
1190 unsigned char bStatus;
Christina Quastf51e0d22015-01-03 21:51:24 +01001191 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001192
1193 do {
Christina Quastf51e0d22015-01-03 21:51:24 +01001194 bStatus = USBD_Write( CCID_EPT_DATA_IN, (void*)&ccidDriver.sCcidMessage,
Christina Quastb123d742014-12-23 13:03:36 +01001195 ccidDriver.sCcidMessage.bSizeToSend, 0, 0 );
Christina Quastf51e0d22015-01-03 21:51:24 +01001196
1197 TRACE_DEBUG("bStatus: 0x%x\n\r", bStatus);
1198
1199 } while (bStatus != USBD_STATUS_SUCCESS);
Christina Quastb123d742014-12-23 13:03:36 +01001200}
1201
1202
Christina Quastf51e0d22015-01-03 21:51:24 +01001203//------------------------------------------------------------------------------
1204/// Description: CCID Command dispatcher
1205//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001206static void CCIDCommandDispatcher( void )
1207{
1208 unsigned char MessageToSend = 0;
1209
Christina Quastf51e0d22015-01-03 21:51:24 +01001210 TRACE_DEBUG("Command: 0x%X 0x%x 0x%X 0x%X 0x%X 0x%X 0x%X\n\r\n\r",
1211 (unsigned int)ccidDriver.sCcidCommand.bMessageType,
1212 (unsigned int)ccidDriver.sCcidCommand.wLength,
1213 (unsigned int)ccidDriver.sCcidCommand.bSlot,
1214 (unsigned int)ccidDriver.sCcidCommand.bSeq,
1215 (unsigned int)ccidDriver.sCcidCommand.bSpecific_0,
1216 (unsigned int)ccidDriver.sCcidCommand.bSpecific_1,
1217 (unsigned int)ccidDriver.sCcidCommand.bSpecific_2);
Christina Quastb123d742014-12-23 13:03:36 +01001218
Christina Quastf51e0d22015-01-03 21:51:24 +01001219 // Check the slot number
Christina Quastb123d742014-12-23 13:03:36 +01001220 if ( ccidDriver.sCcidCommand.bSlot > 0 ) {
1221
1222 TRACE_ERROR("BAD_SLOT_NUMBER\n\r");
1223 }
1224
Christina Quastf51e0d22015-01-03 21:51:24 +01001225 printf("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
Christina Quastb123d742014-12-23 13:03:36 +01001226 TRACE_DEBUG("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
1227
1228 ccidDriver.sCcidMessage.bStatus = 0;
1229
1230 ccidDriver.sCcidMessage.bSeq = ccidDriver.sCcidCommand.bSeq;
1231 ccidDriver.sCcidMessage.bSlot = ccidDriver.sCcidCommand.bSlot;
1232
1233 ccidDriver.sCcidMessage.bSizeToSend = sizeof(S_ccid_bulk_in_header)-(ABDATA_SIZE+1);
1234
1235
Christina Quastf51e0d22015-01-03 21:51:24 +01001236 // Command dispatcher
Christina Quastb123d742014-12-23 13:03:36 +01001237 switch ( ccidDriver.sCcidCommand.bMessageType ) {
1238
1239 case PC_TO_RDR_ICCPOWERON:
1240 PCtoRDRIccPowerOn();
1241 MessageToSend = 1;
1242 break;
1243
1244 case PC_TO_RDR_ICCPOWEROFF:
1245 PCtoRDRIccPowerOff();
1246 MessageToSend = 1;
1247 break;
1248
1249 case PC_TO_RDR_GETSLOTSTATUS:
1250 PCtoRDRGetSlotStatus();
1251 MessageToSend = 1;
1252 break;
1253
1254 case PC_TO_RDR_XFRBLOCK:
1255 PCtoRDRXfrBlock();
1256 MessageToSend = 1;
1257 break;
1258
1259 case PC_TO_RDR_GETPARAMETERS:
1260 PCtoRDRGetParameters();
1261 MessageToSend = 1;
1262 break;
1263
1264 case PC_TO_RDR_RESETPARAMETERS:
1265 PCtoRDRResetParameters();
1266 MessageToSend = 1;
1267 break;
1268
1269 case PC_TO_RDR_SETPARAMETERS:
1270 PCtoRDRSetParameters();
1271 MessageToSend = 1;
1272 break;
1273
1274 case PC_TO_RDR_ESCAPE:
1275 PCtoRDREscape();
1276 MessageToSend = 1;
1277 break;
1278
1279 case PC_TO_RDR_ICCCLOCK:
1280 PCtoRDRICCClock();
1281 MessageToSend = 1;
1282 break;
1283
1284 case PC_TO_RDR_T0APDU:
Christina Quastf51e0d22015-01-03 21:51:24 +01001285 // Only CCIDs reporting a short or extended APDU level in the dwFeatures
1286 // field of the CCID class descriptor may take this command into account.
Christina Quastb123d742014-12-23 13:03:36 +01001287 if( (CCID_FEATURES_EXC_SAPDU == (CCID_FEATURES_EXC_SAPDU&configurationDescriptorsFS.ccid.dwFeatures))
1288 || (CCID_FEATURES_EXC_APDU == (CCID_FEATURES_EXC_APDU &configurationDescriptorsFS.ccid.dwFeatures)) ) {
1289
Christina Quastf51e0d22015-01-03 21:51:24 +01001290 // command supported
Christina Quastb123d742014-12-23 13:03:36 +01001291 PCtoRDRtoAPDU();
1292 }
1293 else {
Christina Quastf51e0d22015-01-03 21:51:24 +01001294 // command not supported
Christina Quastb123d742014-12-23 13:03:36 +01001295 TRACE_DEBUG("PC_TO_RDR_T0APDU\n\r");
1296 vCCIDCommandNotSupported();
1297 }
1298 MessageToSend = 1;
1299 break;
1300
1301 case PC_TO_RDR_SECURE:
1302 PCtoRDRSecure();
1303 MessageToSend = 1;
1304 break;
1305
1306 case PC_TO_RDR_MECHANICAL:
1307 PCtoRDRMechanical();
1308 MessageToSend = 1;
1309 break;
1310
1311 case PC_TO_RDR_ABORT:
1312 PCtoRDRAbort();
1313 MessageToSend = 1;
1314 break;
1315
1316 case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
1317 PCtoRDRSetDataRateAndClockFrequency();
1318 MessageToSend = 1;
1319 break;
1320
1321 default:
1322 TRACE_DEBUG("default: 0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
1323 vCCIDCommandNotSupported();
1324 MessageToSend = 1;
1325 break;
1326
1327 }
1328
1329 if( MessageToSend == 1 ) {
1330 vCCIDSendResponse();
1331 }
1332}
1333
1334
Christina Quastf51e0d22015-01-03 21:51:24 +01001335//------------------------------------------------------------------------------
1336/// SETUP request handler for a CCID device
1337/// \param pRequest Pointer to a USBGenericRequest instance
1338//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001339static void CCID_RequestHandler(const USBGenericRequest *pRequest)
1340{
1341 TRACE_DEBUG("CCID_RHl\n\r");
1342
Christina Quastf51e0d22015-01-03 21:51:24 +01001343 // Check if this is a class request
Christina Quastb123d742014-12-23 13:03:36 +01001344 if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_CLASS) {
1345
Christina Quastf51e0d22015-01-03 21:51:24 +01001346 // Check if the request is supported
Christina Quastb123d742014-12-23 13:03:36 +01001347 switch (USBGenericRequest_GetRequest(pRequest)) {
1348
1349 case CCIDGenericRequest_ABORT:
1350 TRACE_DEBUG("CCIDGenericRequest_ABORT\n\r");
1351 break;
1352
1353 case CCIDGenericRequest_GET_CLOCK_FREQUENCIES:
1354 TRACE_DEBUG("Not supported\n\r");
Christina Quastf51e0d22015-01-03 21:51:24 +01001355 // A CCID with bNumClockSupported equal to 00h does not have
1356 // to support this request
Christina Quastb123d742014-12-23 13:03:36 +01001357 break;
1358
1359 case CCIDGenericRequest_GET_DATA_RATES:
1360 TRACE_DEBUG("Not supported\n\r");
Christina Quastf51e0d22015-01-03 21:51:24 +01001361 // A CCID with bNumDataRatesSupported equal to 00h does not have
1362 // to support this request.
Christina Quastb123d742014-12-23 13:03:36 +01001363 break;
1364
1365 default:
1366 TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request (%d)\n\r",
1367 USBGenericRequest_GetRequest(pRequest));
1368 USBD_Stall(0);
1369 }
1370 }
1371
1372 else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
1373
Christina Quastf51e0d22015-01-03 21:51:24 +01001374 // Forward request to the standard handler
Christina Quastb123d742014-12-23 13:03:36 +01001375 USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest);
1376 }
1377 else {
1378
Christina Quastf51e0d22015-01-03 21:51:24 +01001379 // Unsupported request type
Christina Quastb123d742014-12-23 13:03:36 +01001380 TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request type (%d)\n\r",
1381 USBGenericRequest_GetType(pRequest));
1382 USBD_Stall(0);
1383 }
1384}
1385
1386
Christina Quastf51e0d22015-01-03 21:51:24 +01001387//------------------------------------------------------------------------------
1388// Exported functions
1389//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001390
Christina Quastf51e0d22015-01-03 21:51:24 +01001391//------------------------------------------------------------------------------
1392/// Optional callback re-implementation
1393//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001394#if !defined(NOAUTOCALLBACK)
Christina Quastf51e0d22015-01-03 21:51:24 +01001395// not static function
Christina Quastb123d742014-12-23 13:03:36 +01001396void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
1397{
1398 CCID_RequestHandler(request);
1399}
1400#endif
1401
1402
Christina Quastf51e0d22015-01-03 21:51:24 +01001403//------------------------------------------------------------------------------
1404/// Handles SmartCart request
1405//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001406void CCID_SmartCardRequest( void )
1407{
1408 unsigned char bStatus;
Christina Quastf51e0d22015-01-03 21:51:24 +01001409 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001410
1411 do {
1412
1413 bStatus = CCID_Read( (void*)&ccidDriver.sCcidCommand,
1414 sizeof(S_ccid_bulk_out_header),
1415 (TransferCallback)&CCIDCommandDispatcher,
1416 (void*)0 );
Christina Quastf51e0d22015-01-03 21:51:24 +01001417// TRACE_DEBUG("bStat: %x\n\r", bStatus);
1418 }
Christina Quastb123d742014-12-23 13:03:36 +01001419 while (bStatus != USBD_STATUS_SUCCESS);
1420
1421}
1422
Christina Quastf51e0d22015-01-03 21:51:24 +01001423//------------------------------------------------------------------------------
1424/// Initializes the CCID device driver.
1425//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001426void CCIDDriver_Initialize( void )
1427{
Christina Quastf51e0d22015-01-03 21:51:24 +01001428 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001429 USBDDriver_Initialize(&(ccidDriver.usbdDriver),
1430 &ccidDriverDescriptors,
Christina Quastf51e0d22015-01-03 21:51:24 +01001431 0); // Multiple interface settings not supported
Christina Quastb123d742014-12-23 13:03:36 +01001432 USBD_Init();
Christina Quastf51e0d22015-01-03 21:51:24 +01001433 TRACE_DEBUG("%s", "leaving");
Christina Quastb123d742014-12-23 13:03:36 +01001434}
1435
Christina Quastf51e0d22015-01-03 21:51:24 +01001436//------------------------------------------------------------------------------
1437/// Reads data from the Data OUT endpoint
1438/// \param pBuffer Buffer to store the received data
1439/// \param dLength data buffer length
1440/// \param fCallback Optional callback function
1441/// \param pArgument Optional parameter for the callback function
1442/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
1443//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001444unsigned char CCID_Read(void *pBuffer,
1445 unsigned int dLength,
1446 TransferCallback fCallback,
1447 void *pArgument)
1448{
1449 return USBD_Read(CCID_EPT_DATA_OUT, pBuffer, dLength, fCallback, pArgument);
1450}
1451
Christina Quastf51e0d22015-01-03 21:51:24 +01001452//------------------------------------------------------------------------------
1453/// Sends data through the Data IN endpoint
1454/// \param pBuffer Buffer holding the data to transmit
1455/// \param dLength Length of data buffer
1456/// \param fCallback Optional callback function
1457/// \param pArgument Optional parameter for the callback function
1458/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
1459//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001460unsigned char CCID_Write(void *pBuffer,
1461 unsigned int dLength,
1462 TransferCallback fCallback,
1463 void *pArgument)
1464{
1465 return USBD_Write(CCID_EPT_DATA_IN, pBuffer, dLength, fCallback, pArgument);
1466}
1467
Christina Quastf51e0d22015-01-03 21:51:24 +01001468//------------------------------------------------------------------------------
1469/// Sends data through the interrupt endpoint, ICC insertion event
1470/// RDR_to_PC_NotifySlotChange
1471/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
1472//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001473unsigned char CCID_Insertion( void )
1474{
Christina Quastf51e0d22015-01-03 21:51:24 +01001475 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001476
Christina Quastf51e0d22015-01-03 21:51:24 +01001477 // Build the Interrupt-IN message
Christina Quastb123d742014-12-23 13:03:36 +01001478 ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
1479 ccidDriver.BufferINT[1] = ICC_INSERTED_EVENT;
1480 ccidDriver.SlotStatus = ICC_INSERTED_EVENT;
1481
Christina Quastf51e0d22015-01-03 21:51:24 +01001482 // Notify the host that a ICC is inserted
Christina Quastb123d742014-12-23 13:03:36 +01001483 return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
1484}
1485
Christina Quastf51e0d22015-01-03 21:51:24 +01001486//------------------------------------------------------------------------------
1487/// Sends data through the interrupt endpoint, ICC removal event
1488/// RDR_to_PC_NotifySlotChange
1489/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
1490//------------------------------------------------------------------------------
Christina Quastb123d742014-12-23 13:03:36 +01001491unsigned char CCID_Removal( void )
1492{
Christina Quastf51e0d22015-01-03 21:51:24 +01001493 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001494
Christina Quastf51e0d22015-01-03 21:51:24 +01001495 // Build the Interrupt-IN message
Christina Quastb123d742014-12-23 13:03:36 +01001496 ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
1497 ccidDriver.BufferINT[1] = ICC_NOT_PRESENT;
1498 ccidDriver.SlotStatus = ICC_NOT_PRESENT;
1499
Christina Quastf51e0d22015-01-03 21:51:24 +01001500 // Notify the host that a ICC is inserted
Christina Quastb123d742014-12-23 13:03:36 +01001501 return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
1502}
1503
Christina Quastf51e0d22015-01-03 21:51:24 +01001504//------------------------------------------------------------------------------
1505/// Interrupt-IN Messages
1506/// This message is sent when any bit in the bHardwareErrorCode field is set.
1507/// If this message is sent when there is no “outstanding” command, the bSeq
1508/// field will be undefined.
1509/// \param bSlot ICC slot number
1510/// \param bSeq Sequence number of the bulk OUT command when the hardware error
1511/// occured
1512/// \param bHardwareErrorCode Hardware error code
1513/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
1514//------------------------------------------------------------------------------
1515unsigned char RDRtoPCHardwareError( unsigned char bSlot,
1516 unsigned char bSeq,
Christina Quastb123d742014-12-23 13:03:36 +01001517 unsigned char bHardwareErrorCode )
1518{
Christina Quastf51e0d22015-01-03 21:51:24 +01001519 TRACE_DEBUG(".");
Christina Quastb123d742014-12-23 13:03:36 +01001520
Christina Quastf51e0d22015-01-03 21:51:24 +01001521 // Build the Interrupt-IN message
Christina Quastb123d742014-12-23 13:03:36 +01001522 ccidDriver.BufferINT[0] = RDR_TO_PC_HARDWAREERROR;
1523 ccidDriver.BufferINT[1] = bSlot;
1524 ccidDriver.BufferINT[2] = bSeq;
1525 ccidDriver.BufferINT[3] = bHardwareErrorCode;
1526
Christina Quastf51e0d22015-01-03 21:51:24 +01001527 // Notify the host that a ICC is inserted
Christina Quastb123d742014-12-23 13:03:36 +01001528 return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 4, 0, 0 );
1529}
1530
1531