From 98f9d442b44dbe2e3e4b3c8296be7e78d5d05450 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 24 Jul 2011 09:39:28 +0200 Subject: initial import of the usb ccid example for the sam7s --- at91lib/usb/device/ccid/cciddriver.c | 1503 +++++++++++++++++++++++ at91lib/usb/device/ccid/cciddriver.h | 378 ++++++ at91lib/usb/device/ccid/cciddriverdescriptors.h | 152 +++ 3 files changed, 2033 insertions(+) create mode 100644 at91lib/usb/device/ccid/cciddriver.c create mode 100644 at91lib/usb/device/ccid/cciddriver.h create mode 100644 at91lib/usb/device/ccid/cciddriverdescriptors.h (limited to 'at91lib/usb/device/ccid') diff --git a/at91lib/usb/device/ccid/cciddriver.c b/at91lib/usb/device/ccid/cciddriver.c new file mode 100644 index 0000000..a23fc21 --- /dev/null +++ b/at91lib/usb/device/ccid/cciddriver.c @@ -0,0 +1,1503 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// CCID driver +/// +/// !Usage +/// +/// Explanation on the usage of the code made available through the header file. +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Local definition +//------------------------------------------------------------------------------ + +/// Constants: IDs: Device product ID. +#define CCIDDriverDescriptors_PRODUCTID 0x6129 +/// Constants: IDs: Device vendor ID. +#define CCIDDriverDescriptors_VENDORID 0x03EB +/// Constants: IDs: Device release number. +#define CCIDDriverDescriptors_RELEASE 0x0100 + +/// Returns the minimum between two values. +#define MIN(a, b) ((a < b) ? a : b) + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/// CCIDDriverConfiguration Descriptors +/// List of descriptors that make up the configuration descriptors of a +/// device using the CCID driver. +typedef struct { + + /// Configuration descriptor + USBConfigurationDescriptor configuration; + /// Interface descriptor + USBInterfaceDescriptor interface; + /// CCID descriptor + CCIDDescriptor ccid; + /// Bulk OUT endpoint descriptor + USBEndpointDescriptor bulkOut; + /// Bulk IN endpoint descriptor + USBEndpointDescriptor bulkIn; + /// Interrupt OUT endpoint descriptor + USBEndpointDescriptor interruptIn; + +} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors; + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/// Driver structure for an CCID device +typedef struct { + + /// Standard USB device driver instance + USBDDriver usbdDriver; + /// CCID message + S_ccid_bulk_in_header sCcidMessage; + /// CCID command + S_ccid_bulk_out_header sCcidCommand; + /// Interrupt message answer + unsigned char BufferINT[4]; + /// Buffer data of message + unsigned char ProtocolDataStructure[10]; + /// Protocol used + unsigned char bProtocol; + /// SlotStatus + /// Bit 0 = Slot 0 current state + /// Bit 1 = Slot 0 changed status + /// Bit 2 = Slot 1 current state + /// Bit 3 = Slot 1 changed status + /// Bit 4 = Slot 2 current state + /// Bit 5 = Slot 2 changed status + unsigned char SlotStatus; + +} CCIDDriver; + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// Static instance of the CCID device driver. +static CCIDDriver ccidDriver; + +/// Standard USB device descriptor. +static const USBDeviceDescriptor deviceDescriptor = { + + sizeof(USBDeviceDescriptor), + USBGenericDescriptor_DEVICE, + USBDeviceDescriptor_USB2_00, + 0, + 0, + 0, + BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0), + CCIDDriverDescriptors_VENDORID, + CCIDDriverDescriptors_PRODUCTID, + CCIDDriverDescriptors_RELEASE, + 1, // Index of manufacturer description + 2, // Index of product description + 3, // Index of serial number description + 1 // One possible configuration +}; + + +/// List of configuration descriptors. +static const CCIDDriverConfigurationDescriptors configurationDescriptorsFS = { + + // Standard USB configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_CONFIGURATION, + sizeof(CCIDDriverConfigurationDescriptors), + 1, // One interface in this configuration + 1, // This is configuration #1 + 0, // No associated string descriptor + BOARD_USB_BMATTRIBUTES, + USBConfigurationDescriptor_POWER(100) + }, + // CCID interface descriptor + // Table 4.3-1 Interface Descriptor + // Interface descriptor + { + sizeof(USBInterfaceDescriptor), + USBGenericDescriptor_INTERFACE, + 0, // Interface 0 + 0, // No alternate settings + 3, // uses bulk-IN, bulk-OUT and interrupt–IN + SMART_CARD_DEVICE_CLASS, + 0, // Subclass code + 0, // bulk transfers optional interrupt-IN + 0 // No associated string descriptor + }, + { + sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes + CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type + CCID1_10, // bcdCCID: CCID version + 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported + VOLTS_5_0, // bVoltageSupport + PROTOCOL_TO, // dwProtocols + 3580, // dwDefaultClock + 3580, // dwMaxClock + 0, // bNumClockSupported + 9600, // dwDataRate : 9600 bauds + 9600, // dwMaxDataRate : 9600 bauds + 0, // bNumDataRatesSupported + 0xfe, // dwMaxIFSD + 0, // dwSynchProtocols + 0, // dwMechanical + //0x00010042, // dwFeatures: Short APDU level exchanges + CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU, + 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 + 0xFF, // bClassGetResponse: Echoes the class of the APDU + 0xFF, // bClassEnvelope: Echoes the class of the APDU + 0, // wLcdLayout: no LCD + 0, // bPINSupport: No PIN + 1 // bMaxCCIDBusySlot + }, + // Bulk-OUT endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT), + USBEndpointDescriptor_MAXBULKSIZE_FS), + 0x00 // Does not apply to Bulk endpoints + }, + // Bulk-IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN), + USBEndpointDescriptor_MAXBULKSIZE_FS), + 0x00 // Does not apply to Bulk endpoints + }, + // Notification endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ), + USBEndpointDescriptor_INTERRUPT, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION), + USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), + 0x10 + } +}; + +#ifdef BOARD_USB_UDPHS +static const CCIDDriverConfigurationDescriptors configurationDescriptorsHS = { + + // Standard USB configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_CONFIGURATION, + sizeof(CCIDDriverConfigurationDescriptors), + 1, // One interface in this configuration + 1, // This is configuration #1 + 0, // No associated string descriptor + BOARD_USB_BMATTRIBUTES, + USBConfigurationDescriptor_POWER(100) + }, + // CCID interface descriptor + // Table 4.3-1 Interface Descriptor + // Interface descriptor + { + sizeof(USBInterfaceDescriptor), + USBGenericDescriptor_INTERFACE, + 0, // Interface 0 + 0, // No alternate settings + 3, // uses bulk-IN, bulk-OUT and interrupt–IN + SMART_CARD_DEVICE_CLASS, + 0, // Subclass code + 0, // bulk transfers optional interrupt-IN + 0 // No associated string descriptor + }, + { + sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes + CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type + CCID1_10, // bcdCCID: CCID version + 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported + VOLTS_5_0, // bVoltageSupport + PROTOCOL_TO, // dwProtocols + 3580, // dwDefaultClock + 3580, // dwMaxClock + 0, // bNumClockSupported + 9600, // dwDataRate : 9600 bauds + 9600, // dwMaxDataRate : 9600 bauds + 0, // bNumDataRatesSupported + 0xfe, // dwMaxIFSD + 0, // dwSynchProtocols + 0, // dwMechanical + //0x00010042, // dwFeatures: Short APDU level exchanges + CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU, + 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 + 0xFF, // bClassGetResponse: Echoes the class of the APDU + 0xFF, // bClassEnvelope: Echoes the class of the APDU + 0, // wLcdLayout: no LCD + 0, // bPINSupport: No PIN + 1 // bMaxCCIDBusySlot + }, + // Bulk-OUT endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT), + USBEndpointDescriptor_MAXBULKSIZE_HS), + 0x00 // Does not apply to Bulk endpoints + }, + // Bulk-IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN), + USBEndpointDescriptor_MAXBULKSIZE_HS), + 0x00 // Does not apply to Bulk endpoints + }, + // Notification endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ), + USBEndpointDescriptor_INTERRUPT, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION), + USBEndpointDescriptor_MAXINTERRUPTSIZE_HS), + 0x10 + } +}; + +/// Qualifier descriptor +const USBDeviceQualifierDescriptor deviceQualifierDescriptor = { + + sizeof(USBDeviceQualifierDescriptor), // Size of this descriptor in bytes + USBGenericDescriptor_DEVICEQUALIFIER, // Qualifier Descriptor Type + USBDeviceDescriptor_USB2_00, // USB specification 2.00 + 0x00, // Class is specified in interface + 0x00, // Subclass is specified in interface + 0x00, // Protocol is specified in interface + BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0), + 0x01, // One possible configuration + 0x00 // Reserved for future use, must be zero +}; + +/// OtherSpeed configuration descriptor in Full Speed mode +static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationFS = { + + // Standard USB configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_OTHERSPEEDCONFIGURATION, + sizeof(CCIDDriverConfigurationDescriptors), + 1, // One interface in this configuration + 1, // This is configuration #1 + 0, // No associated string descriptor + BOARD_USB_BMATTRIBUTES, + USBConfigurationDescriptor_POWER(100) + }, + // CCID interface descriptor + // Table 4.3-1 Interface Descriptor + // Interface descriptor + { + sizeof(USBInterfaceDescriptor), + USBGenericDescriptor_INTERFACE, + 0, // Interface 0 + 0, // No alternate settings + 3, // uses bulk-IN, bulk-OUT and interrupt–IN + SMART_CARD_DEVICE_CLASS, + 0, // Subclass code + 0, // bulk transfers optional interrupt-IN + 0 // No associated string descriptor + }, + { + sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes + CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type + CCID1_10, // bcdCCID: CCID version + 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported + VOLTS_5_0, // bVoltageSupport + PROTOCOL_TO, // dwProtocols + 3580, // dwDefaultClock + 3580, // dwMaxClock + 0, // bNumClockSupported + 9600, // dwDataRate : 9600 bauds + 9600, // dwMaxDataRate : 9600 bauds + 0, // bNumDataRatesSupported + 0xfe, // dwMaxIFSD + 0, // dwSynchProtocols + 0, // dwMechanical + //0x00010042, // dwFeatures: Short APDU level exchanges + CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU, + 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 + 0xFF, // bClassGetResponse: Echoes the class of the APDU + 0xFF, // bClassEnvelope: Echoes the class of the APDU + 0, // wLcdLayout: no LCD + 0, // bPINSupport: No PIN + 1 // bMaxCCIDBusySlot + }, + // Bulk-OUT endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT), + USBEndpointDescriptor_MAXBULKSIZE_FS), + 0x00 // Does not apply to Bulk endpoints + }, + // Bulk-IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN), + USBEndpointDescriptor_MAXBULKSIZE_FS), + 0x00 // Does not apply to Bulk endpoints + }, + // Notification endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ), + USBEndpointDescriptor_INTERRUPT, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION), + USBEndpointDescriptor_MAXINTERRUPTSIZE_FS), + 0x10 + } +}; + +/// OtherSpeed configuration descriptor in High Speed mode +static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationHS = { + + // Standard USB configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_OTHERSPEEDCONFIGURATION, + sizeof(CCIDDriverConfigurationDescriptors), + 1, // One interface in this configuration + 1, // This is configuration #1 + 0, // No associated string descriptor + BOARD_USB_BMATTRIBUTES, + USBConfigurationDescriptor_POWER(100) + }, + // CCID interface descriptor + // Table 4.3-1 Interface Descriptor + // Interface descriptor + { + sizeof(USBInterfaceDescriptor), + USBGenericDescriptor_INTERFACE, + 0, // Interface 0 + 0, // No alternate settings + 3, // uses bulk-IN, bulk-OUT and interrupt–IN + SMART_CARD_DEVICE_CLASS, + 0, // Subclass code + 0, // bulk transfers optional interrupt-IN + 0 // No associated string descriptor + }, + { + sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes + CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type + CCID1_10, // bcdCCID: CCID version + 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported + VOLTS_5_0, // bVoltageSupport + PROTOCOL_TO, // dwProtocols + 3580, // dwDefaultClock + 3580, // dwMaxClock + 0, // bNumClockSupported + 9600, // dwDataRate : 9600 bauds + 9600, // dwMaxDataRate : 9600 bauds + 0, // bNumDataRatesSupported + 0xfe, // dwMaxIFSD + 0, // dwSynchProtocols + 0, // dwMechanical + //0x00010042, // dwFeatures: Short APDU level exchanges + CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU, + 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 + 0xFF, // bClassGetResponse: Echoes the class of the APDU + 0xFF, // bClassEnvelope: Echoes the class of the APDU + 0, // wLcdLayout: no LCD + 0, // bPINSupport: No PIN + 1 // bMaxCCIDBusySlot + }, + // Bulk-OUT endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT), + USBEndpointDescriptor_MAXBULKSIZE_HS), + 0x00 // Does not apply to Bulk endpoints + }, + // Bulk-IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ), + USBEndpointDescriptor_BULK, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN), + USBEndpointDescriptor_MAXBULKSIZE_HS), + 0x00 // Does not apply to Bulk endpoints + }, + // Notification endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ), + USBEndpointDescriptor_INTERRUPT, + MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION), + USBEndpointDescriptor_MAXINTERRUPTSIZE_HS), + 0x10 + } +}; +#endif + +/// Language ID string descriptor. +static const unsigned char languageIdDescriptor[] = { + + USBStringDescriptor_LENGTH(1), + USBGenericDescriptor_STRING, + USBStringDescriptor_ENGLISH_US +}; + +/// Manufacturer name. +static const unsigned char manufacturerDescriptor[] = { + + USBStringDescriptor_LENGTH(5), + USBGenericDescriptor_STRING, + USBStringDescriptor_UNICODE('A'), + USBStringDescriptor_UNICODE('T'), + USBStringDescriptor_UNICODE('M'), + USBStringDescriptor_UNICODE('E'), + USBStringDescriptor_UNICODE('L') +}; + +/// Product name. +static const unsigned char productDescriptor[] = { + + USBStringDescriptor_LENGTH(23), + USBGenericDescriptor_STRING, + USBStringDescriptor_UNICODE('A'), + USBStringDescriptor_UNICODE('T'), + USBStringDescriptor_UNICODE('M'), + USBStringDescriptor_UNICODE('E'), + USBStringDescriptor_UNICODE('L'), + USBStringDescriptor_UNICODE(' '), + USBStringDescriptor_UNICODE('A'), + USBStringDescriptor_UNICODE('T'), + USBStringDescriptor_UNICODE('9'), + USBStringDescriptor_UNICODE('1'), + USBStringDescriptor_UNICODE(' '), + USBStringDescriptor_UNICODE('C'), + USBStringDescriptor_UNICODE('C'), + USBStringDescriptor_UNICODE('I'), + USBStringDescriptor_UNICODE('D'), + USBStringDescriptor_UNICODE(' '), + USBStringDescriptor_UNICODE('D'), + USBStringDescriptor_UNICODE('R'), + USBStringDescriptor_UNICODE('I'), + USBStringDescriptor_UNICODE('V'), + USBStringDescriptor_UNICODE('E'), + USBStringDescriptor_UNICODE('R'), + USBStringDescriptor_UNICODE(' ') +}; + +/// Product serial number. +static const unsigned char serialNumberDescriptor[] = { + + USBStringDescriptor_LENGTH(12), + USBGenericDescriptor_STRING, + USBStringDescriptor_UNICODE('0'), + USBStringDescriptor_UNICODE('1'), + USBStringDescriptor_UNICODE('2'), + USBStringDescriptor_UNICODE('3'), + USBStringDescriptor_UNICODE('4'), + USBStringDescriptor_UNICODE('5'), + USBStringDescriptor_UNICODE('6'), + USBStringDescriptor_UNICODE('7'), + USBStringDescriptor_UNICODE('8'), + USBStringDescriptor_UNICODE('9'), + USBStringDescriptor_UNICODE('A'), + USBStringDescriptor_UNICODE('F') +}; + +/// Array of pointers to string descriptors. +static const unsigned char *stringDescriptors[] = { + + languageIdDescriptor, + manufacturerDescriptor, + productDescriptor, + serialNumberDescriptor +}; + + +/// List of standard descriptors for the serial driver. +const USBDDriverDescriptors ccidDriverDescriptors = { + + &deviceDescriptor, // FS + (USBConfigurationDescriptor *) &configurationDescriptorsFS, +#ifdef BOARD_USB_UDPHS + (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // FS + (USBConfigurationDescriptor *) &sOtherSpeedConfigurationFS, + &deviceDescriptor, // HS + (USBConfigurationDescriptor *) &configurationDescriptorsHS, + (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // HS + (USBConfigurationDescriptor *) &sOtherSpeedConfigurationHS, +#else + 0, // No qualifier descriptor FS + 0, // No other-speed configuration FS + 0, // No device descriptor HS + 0, // No configuration HS + 0, // No qualifier descriptor HS + 0, // No other-speed configuration HS +#endif + stringDescriptors, + 4 // Four string descriptors in array +}; + +//------------------------------------------------------------------------------ +// Internal functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Response Pipe, Bulk-IN Messages +/// Return the Slot Status to the host +/// Answer to: +/// PC_to_RDR_IccPowerOff +/// PC_to_RDR_GetSlotStatus +/// PC_to_RDR_IccClock +/// PC_to_RDR_T0APDU +/// PC_to_RDR_Mechanical +/// PC_to_RDR_Abort and Class specific ABORT request +//------------------------------------------------------------------------------ +static void RDRtoPCSlotStatus( void ) +{ + TRACE_DEBUG("RDRtoPCSlotStatus\n\r"); + + // Header fields settings + ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS; + ccidDriver.sCcidMessage.wLength = 0; + ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus; + ccidDriver.sCcidMessage.bError = 0; + // 00h Clock running + // 01h Clock stopped in state L + // 02h Clock stopped in state H + // 03h Clock stopped in an unknown state + // All other values are Reserved for Future Use. + ccidDriver.sCcidMessage.bSpecific = 0; +} + +//------------------------------------------------------------------------------ +/// Response Pipe, Bulk-IN Messages +/// Answer to PC_to_RDR_IccPowerOn +//------------------------------------------------------------------------------ +static void RDRtoPCDatablock_ATR( void ) +{ + unsigned char i; + unsigned char Atr[ATR_SIZE_MAX]; + unsigned char length; + + //TRACE_DEBUG("RDRtoPCDatablock\n\r"); + + ISO7816_Datablock_ATR( Atr, &length ); + + if( length > 5 ) { + ccidDriver.ProtocolDataStructure[1] = Atr[5]&0x0F; // TD(1) + ccidDriver.bProtocol = Atr[5]&0x0F; // TD(1) + } + + // S_ccid_protocol_t0 + // bmFindexDindex + ccidDriver.ProtocolDataStructure[0] = Atr[2]; // TA(1) + + // bmTCCKST0 + // For T=0 ,B0 – 0b, B7-2 – 000000b + // B1 – Convention used (b1=0 for direct, b1=1 for inverse) + + // bGuardTimeT0 + // Extra Guardtime between two characters. Add 0 to 254 etu to the normal + // guardtime of 12etu. FFh is the same as 00h. + ccidDriver.ProtocolDataStructure[2] = Atr[4]; // TC(1) + // AT91C_BASE_US0->US_TTGR = 0; // TC1 + + // bWaitingIntegerT0 + // WI for T=0 used to define WWT + ccidDriver.ProtocolDataStructure[3] = Atr[7]; // TC(2) + + // bClockStop + // ICC Clock Stop Support + // 00 = Stopping the Clock is not allowed + // 01 = Stop with Clock signal Low + // 02 = Stop with Clock signal High + // 03 = Stop with Clock either High or Low + ccidDriver.ProtocolDataStructure[4] = 0x00; // 0 to 3 + + // Header fields settings + ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK; + ccidDriver.sCcidMessage.wLength = length; // Size of ATR + ccidDriver.sCcidMessage.bSizeToSend += length; // Size of ATR + // bChainParameter: 00 the response APDU begins and ends in this command + ccidDriver.sCcidMessage.bSpecific = 0; + + for( i=0; i (configurationDescriptorsFS.ccid.dwMaxCCIDMessageLength-10) ) { + + ccidDriver.sCcidMessage.bStatus = 1; + ccidDriver.sCcidMessage.bError = 0; + } + // check bBWI + else if ( 0 != ccidDriver.sCcidCommand.bSpecific_0 ) { + + TRACE_ERROR("Bad bBWI\n\r"); + } + else { + + // APDU or TPDU + switch(configurationDescriptorsFS.ccid.dwFeatures + & (CCID_FEATURES_EXC_TPDU|CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU)) { + + case CCID_FEATURES_EXC_TPDU: + if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) { + + // Send commande APDU + indexMessage = ISO7816_XfrBlockTPDU_T0( ccidDriver.sCcidCommand.APDU , + ccidDriver.sCcidMessage.abData, + ccidDriver.sCcidCommand.wLength ); + } + else { + if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_T1) { + TRACE_INFO("Not supported T=1\n\r"); + } + else { + TRACE_INFO("Not supported\n\r"); + } + } + break; + + case CCID_FEATURES_EXC_APDU: + TRACE_INFO("Not supported\n\r"); + break; + + default: + break; + } + + } + + ccidDriver.sCcidMessage.wLength = indexMessage; + TRACE_DEBUG("USB: 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\n\r", ccidDriver.sCcidMessage.abData[0], + ccidDriver.sCcidMessage.abData[1], + ccidDriver.sCcidMessage.abData[2], + ccidDriver.sCcidMessage.abData[3], + ccidDriver.sCcidMessage.abData[4] ); + RDRtoPCDatablock(); + +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// return parameters by the command: RDR_to_PC_Parameters +//------------------------------------------------------------------------------ +static void PCtoRDRGetParameters( void ) +{ + TRACE_DEBUG("PCtoRDRGetParameters\n\r"); + + // We support only one slot + + // bmIccStatus + if( ISO7816_StatusReset() ) { + // 0: An ICC is present and active (power is on and stable, RST is inactive + ccidDriver.sCcidMessage.bStatus = 0; + } + else { + // 1: An ICC is present and inactive (not activated or shut down by hardware error) + ccidDriver.sCcidMessage.bStatus = 1; + } + + RDRtoPCParameters(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command resets the slot parameters to their default values +//------------------------------------------------------------------------------ +static void PCtoRDRResetParameters( void ) +{ + TRACE_DEBUG("PCtoRDRResetParameters\n\r"); + + ccidDriver.SlotStatus = ICC_NOT_PRESENT; + ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus; + + RDRtoPCParameters(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command is used to change the parameters for a given slot. +//------------------------------------------------------------------------------ +static void PCtoRDRSetParameters( void ) +{ + TRACE_DEBUG("PCtoRDRSetParameters\n\r"); + + ccidDriver.SlotStatus = ccidDriver.sCcidCommand.bSlot; + ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus; + // Not all feature supported + + RDRtoPCParameters(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command allows the CCID manufacturer to define and access extended +/// features. +/// Information sent via this command is processed by the CCID control logic. +//------------------------------------------------------------------------------ +static void PCtoRDREscape( void ) +{ + TRACE_DEBUG("PCtoRDREscape\n\r"); + + // If needed by the user + ISO7816_Escape(); + + // stub, return all value send + RDRtoPCEscape( ccidDriver.sCcidCommand.wLength, ccidDriver.sCcidCommand.APDU); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command stops or restarts the clock. +//------------------------------------------------------------------------------ +static void PCtoRDRICCClock( void ) +{ + TRACE_DEBUG("PCtoRDRICCClock\n\r"); + + if( 0 == ccidDriver.sCcidCommand.bSpecific_0 ) { + // restarts the clock + ISO7816_RestartClock(); + } + else { + // stop clock in the state shown in the bClockStop field + ISO7816_StopClock(); + } + + RDRtoPCSlotStatus( ); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command changes the parameters used to perform the transportation of +/// APDU messages by the T=0 protocol. +//------------------------------------------------------------------------------ +static void PCtoRDRtoAPDU( void ) +{ + unsigned char bmChanges; + unsigned char bClassGetResponse; + unsigned char bClassEnvelope; + + TRACE_DEBUG("PCtoRDRtoAPDU\n\r"); + + if( configurationDescriptorsFS.ccid.dwFeatures == (CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU) ) { + + bmChanges = ccidDriver.sCcidCommand.bSpecific_0; + bClassGetResponse = ccidDriver.sCcidCommand.bSpecific_1; + bClassEnvelope = ccidDriver.sCcidCommand.bSpecific_2; + + ISO7816_toAPDU(); + } + + RDRtoPCSlotStatus(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This is a command message to allow entering the PIN for verification or +/// modification. +//------------------------------------------------------------------------------ +static void PCtoRDRSecure( void ) +{ + TRACE_DEBUG("PCtoRDRSecure\n\r"); + + TRACE_DEBUG("For user\n\r"); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command is used to manage motorized type CCID functionality. +/// The Lock Card function is used to hold the ICC. +/// This prevents an ICC from being easily removed from the CCID. +/// The Unlock Card function is used to remove the hold initiated by the Lock +/// Card function +//------------------------------------------------------------------------------ +static void PCtoRDRMechanical( void ) +{ + TRACE_DEBUG("PCtoRDRMechanical\n\r"); + TRACE_DEBUG("Not implemented\n\r"); + + RDRtoPCSlotStatus(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command is used with the Control pipe Abort request to tell the CCID +/// to stop any current transfer at the specified slot and return to a state +/// where the slot is ready to accept a new command pipe Bulk-OUT message. +//------------------------------------------------------------------------------ +static void PCtoRDRAbort( void ) +{ + TRACE_DEBUG("PCtoRDRAbort\n\r"); + + RDRtoPCSlotStatus(); +} + +//------------------------------------------------------------------------------ +/// Command Pipe, Bulk-OUT Messages +/// This command is used to manually set the data rate and clock frequency of +/// a specific slot. +//------------------------------------------------------------------------------ +static void PCtoRDRSetDataRateAndClockFrequency( void ) +{ + unsigned int dwClockFrequency; + unsigned int dwDataRate; + + TRACE_DEBUG("PCtoRDRSetDatarateandClockFrequency\n\r"); + + dwClockFrequency = ccidDriver.sCcidCommand.APDU[0] + + (ccidDriver.sCcidCommand.APDU[1]<<8) + + (ccidDriver.sCcidCommand.APDU[2]<<16) + + (ccidDriver.sCcidCommand.APDU[3]<<24); + + dwDataRate = ccidDriver.sCcidCommand.APDU[4] + + (ccidDriver.sCcidCommand.APDU[5]<<8) + + (ccidDriver.sCcidCommand.APDU[6]<<16) + + (ccidDriver.sCcidCommand.APDU[7]<<24); + + ISO7816_SetDataRateandClockFrequency( dwClockFrequency, dwDataRate ); + + RDRtoPCDataRateAndClockFrequency( dwClockFrequency, dwDataRate ); + +} + +//------------------------------------------------------------------------------ +/// Report the CMD_NOT_SUPPORTED error to the host +//------------------------------------------------------------------------------ +static void vCCIDCommandNotSupported( void ) +{ + // Command not supported + // vCCIDReportError(CMD_NOT_SUPPORTED); + + TRACE_DEBUG("CMD_NOT_SUPPORTED\n\r"); + + // Header fields settings + ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS; + ccidDriver.sCcidMessage.wLength = 0; + ccidDriver.sCcidMessage.bSpecific = 0; + + ccidDriver.sCcidMessage.bStatus |= ICC_CS_FAILED; + + // Send the response to the host + //vCCIDSendResponse(); +} + +//------------------------------------------------------------------------------ +/// Sent CCID response on USB +//------------------------------------------------------------------------------ +static void vCCIDSendResponse( void ) +{ + unsigned char bStatus; + + do { + bStatus = USBD_Write( CCID_EPT_DATA_IN, (void*)&ccidDriver.sCcidMessage, + ccidDriver.sCcidMessage.bSizeToSend, 0, 0 ); + } + while (bStatus != USBD_STATUS_SUCCESS); +} + + +//------------------------------------------------------------------------------ +/// Description: CCID Command dispatcher +//------------------------------------------------------------------------------ +static void CCIDCommandDispatcher( void ) +{ + unsigned char MessageToSend = 0; + + //TRACE_DEBUG("Command: 0x%X 0x%x 0x%X 0x%X 0x%X 0x%X 0x%X\n\r\n\r", + // (unsigned int)ccidDriver.sCcidCommand.bMessageType, + // (unsigned int)ccidDriver.sCcidCommand.wLength, + // (unsigned int)ccidDriver.sCcidCommand.bSlot, + // (unsigned int)ccidDriver.sCcidCommand.bSeq, + // (unsigned int)ccidDriver.sCcidCommand.bSpecific_0, + // (unsigned int)ccidDriver.sCcidCommand.bSpecific_1, + // (unsigned int)ccidDriver.sCcidCommand.bSpecific_2); + + // Check the slot number + if ( ccidDriver.sCcidCommand.bSlot > 0 ) { + + TRACE_ERROR("BAD_SLOT_NUMBER\n\r"); + } + + TRACE_DEBUG("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType); + + ccidDriver.sCcidMessage.bStatus = 0; + + ccidDriver.sCcidMessage.bSeq = ccidDriver.sCcidCommand.bSeq; + ccidDriver.sCcidMessage.bSlot = ccidDriver.sCcidCommand.bSlot; + + ccidDriver.sCcidMessage.bSizeToSend = sizeof(S_ccid_bulk_in_header)-(ABDATA_SIZE+1); + + + // Command dispatcher + switch ( ccidDriver.sCcidCommand.bMessageType ) { + + case PC_TO_RDR_ICCPOWERON: + PCtoRDRIccPowerOn(); + MessageToSend = 1; + break; + + case PC_TO_RDR_ICCPOWEROFF: + PCtoRDRIccPowerOff(); + MessageToSend = 1; + break; + + case PC_TO_RDR_GETSLOTSTATUS: + PCtoRDRGetSlotStatus(); + MessageToSend = 1; + break; + + case PC_TO_RDR_XFRBLOCK: + PCtoRDRXfrBlock(); + MessageToSend = 1; + break; + + case PC_TO_RDR_GETPARAMETERS: + PCtoRDRGetParameters(); + MessageToSend = 1; + break; + + case PC_TO_RDR_RESETPARAMETERS: + PCtoRDRResetParameters(); + MessageToSend = 1; + break; + + case PC_TO_RDR_SETPARAMETERS: + PCtoRDRSetParameters(); + MessageToSend = 1; + break; + + case PC_TO_RDR_ESCAPE: + PCtoRDREscape(); + MessageToSend = 1; + break; + + case PC_TO_RDR_ICCCLOCK: + PCtoRDRICCClock(); + MessageToSend = 1; + break; + + case PC_TO_RDR_T0APDU: + // Only CCIDs reporting a short or extended APDU level in the dwFeatures + // field of the CCID class descriptor may take this command into account. + if( (CCID_FEATURES_EXC_SAPDU == (CCID_FEATURES_EXC_SAPDU&configurationDescriptorsFS.ccid.dwFeatures)) + || (CCID_FEATURES_EXC_APDU == (CCID_FEATURES_EXC_APDU &configurationDescriptorsFS.ccid.dwFeatures)) ) { + + // command supported + PCtoRDRtoAPDU(); + } + else { + // command not supported + TRACE_DEBUG("PC_TO_RDR_T0APDU\n\r"); + vCCIDCommandNotSupported(); + } + MessageToSend = 1; + break; + + case PC_TO_RDR_SECURE: + PCtoRDRSecure(); + MessageToSend = 1; + break; + + case PC_TO_RDR_MECHANICAL: + PCtoRDRMechanical(); + MessageToSend = 1; + break; + + case PC_TO_RDR_ABORT: + PCtoRDRAbort(); + MessageToSend = 1; + break; + + case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY: + PCtoRDRSetDataRateAndClockFrequency(); + MessageToSend = 1; + break; + + default: + TRACE_DEBUG("default: 0x%X\n\r", ccidDriver.sCcidCommand.bMessageType); + vCCIDCommandNotSupported(); + MessageToSend = 1; + break; + + } + + if( MessageToSend == 1 ) { + vCCIDSendResponse(); + } +} + + +//------------------------------------------------------------------------------ +/// SETUP request handler for a CCID device +/// \param pRequest Pointer to a USBGenericRequest instance +//------------------------------------------------------------------------------ +static void CCID_RequestHandler(const USBGenericRequest *pRequest) +{ + TRACE_DEBUG("CCID_RHl\n\r"); + + // Check if this is a class request + if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_CLASS) { + + // Check if the request is supported + switch (USBGenericRequest_GetRequest(pRequest)) { + + case CCIDGenericRequest_ABORT: + TRACE_DEBUG("CCIDGenericRequest_ABORT\n\r"); + break; + + case CCIDGenericRequest_GET_CLOCK_FREQUENCIES: + TRACE_DEBUG("Not supported\n\r"); + // A CCID with bNumClockSupported equal to 00h does not have + // to support this request + break; + + case CCIDGenericRequest_GET_DATA_RATES: + TRACE_DEBUG("Not supported\n\r"); + // A CCID with bNumDataRatesSupported equal to 00h does not have + // to support this request. + break; + + default: + TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request (%d)\n\r", + USBGenericRequest_GetRequest(pRequest)); + USBD_Stall(0); + } + } + + else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) { + + // Forward request to the standard handler + USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest); + } + else { + + // Unsupported request type + TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request type (%d)\n\r", + USBGenericRequest_GetType(pRequest)); + USBD_Stall(0); + } +} + + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Optional callback re-implementation +//------------------------------------------------------------------------------ +#if !defined(NOAUTOCALLBACK) +// not static function +void USBDCallbacks_RequestReceived(const USBGenericRequest *request) +{ + CCID_RequestHandler(request); +} +#endif + + +//------------------------------------------------------------------------------ +/// Handles SmartCart request +//------------------------------------------------------------------------------ +void CCID_SmartCardRequest( void ) +{ + unsigned char bStatus; + + do { + + bStatus = CCID_Read( (void*)&ccidDriver.sCcidCommand, + sizeof(S_ccid_bulk_out_header), + (TransferCallback)&CCIDCommandDispatcher, + (void*)0 ); + } + while (bStatus != USBD_STATUS_SUCCESS); + +} + +//------------------------------------------------------------------------------ +/// Initializes the CCID device driver. +//------------------------------------------------------------------------------ +void CCIDDriver_Initialize( void ) +{ + TRACE_DEBUG("CCID_Init\n\r"); + USBDDriver_Initialize(&(ccidDriver.usbdDriver), + &ccidDriverDescriptors, + 0); // Multiple interface settings not supported + USBD_Init(); +} + +//------------------------------------------------------------------------------ +/// Reads data from the Data OUT endpoint +/// \param pBuffer Buffer to store the received data +/// \param dLength data buffer length +/// \param fCallback Optional callback function +/// \param pArgument Optional parameter for the callback function +/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS +//------------------------------------------------------------------------------ +unsigned char CCID_Read(void *pBuffer, + unsigned int dLength, + TransferCallback fCallback, + void *pArgument) +{ + return USBD_Read(CCID_EPT_DATA_OUT, pBuffer, dLength, fCallback, pArgument); +} + +//------------------------------------------------------------------------------ +/// Sends data through the Data IN endpoint +/// \param pBuffer Buffer holding the data to transmit +/// \param dLength Length of data buffer +/// \param fCallback Optional callback function +/// \param pArgument Optional parameter for the callback function +/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS +//------------------------------------------------------------------------------ +unsigned char CCID_Write(void *pBuffer, + unsigned int dLength, + TransferCallback fCallback, + void *pArgument) +{ + return USBD_Write(CCID_EPT_DATA_IN, pBuffer, dLength, fCallback, pArgument); +} + +//------------------------------------------------------------------------------ +/// Sends data through the interrupt endpoint, ICC insertion event +/// RDR_to_PC_NotifySlotChange +/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS +//------------------------------------------------------------------------------ +unsigned char CCID_Insertion( void ) +{ + TRACE_DEBUG("CCID_Insertion\n\r"); + + // Build the Interrupt-IN message + ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE; + ccidDriver.BufferINT[1] = ICC_INSERTED_EVENT; + ccidDriver.SlotStatus = ICC_INSERTED_EVENT; + + // Notify the host that a ICC is inserted + return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 ); +} + +//------------------------------------------------------------------------------ +/// Sends data through the interrupt endpoint, ICC removal event +/// RDR_to_PC_NotifySlotChange +/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS +//------------------------------------------------------------------------------ +unsigned char CCID_Removal( void ) +{ + TRACE_DEBUG("CCID_Removal\n\r"); + + // Build the Interrupt-IN message + ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE; + ccidDriver.BufferINT[1] = ICC_NOT_PRESENT; + ccidDriver.SlotStatus = ICC_NOT_PRESENT; + + // Notify the host that a ICC is inserted + return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 ); +} + +//------------------------------------------------------------------------------ +/// Interrupt-IN Messages +/// This message is sent when any bit in the bHardwareErrorCode field is set. +/// If this message is sent when there is no “outstanding” command, the bSeq +/// field will be undefined. +/// \param bSlot ICC slot number +/// \param bSeq Sequence number of the bulk OUT command when the hardware error +/// occured +/// \param bHardwareErrorCode Hardware error code +/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS +//------------------------------------------------------------------------------ +unsigned char RDRtoPCHardwareError( unsigned char bSlot, + unsigned char bSeq, + unsigned char bHardwareErrorCode ) +{ + TRACE_DEBUG("RDRtoPCHardwareError\n\r"); + + // Build the Interrupt-IN message + ccidDriver.BufferINT[0] = RDR_TO_PC_HARDWAREERROR; + ccidDriver.BufferINT[1] = bSlot; + ccidDriver.BufferINT[2] = bSeq; + ccidDriver.BufferINT[3] = bHardwareErrorCode; + + // Notify the host that a ICC is inserted + return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 4, 0, 0 ); +} + + diff --git a/at91lib/usb/device/ccid/cciddriver.h b/at91lib/usb/device/ccid/cciddriver.h new file mode 100644 index 0000000..8bac286 --- /dev/null +++ b/at91lib/usb/device/ccid/cciddriver.h @@ -0,0 +1,378 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Definition of methods for using a CCID device driver. +/// +/// !Usage +/// +/// -# CCIDDriver_Initialize +/// -# CCID_Read +/// -# CCID_Write +/// -# CCID_SmartCardRequest +/// -# CCID_Insertion +/// -# CCID_Removal +/// -# RDRtoPCHardwareError +//------------------------------------------------------------------------------ + +#ifndef CCID_DRIVER_H +#define CCID_DRIVER_H + +/// For reference, the absolute maximum block size +/// for a TPDU T=0 block is 260 bytes (5 bytes command; 255 bytes data), or +/// for a TPDU T=1 block is 259 bytes, or +/// for a short APDU T=1 block is 261 bytes, or +/// for an extended APDU T=1 block is 65544 bytes. +#define ABDATA_SIZE 260 + +/// define protocol T=0 +#define PROTOCOL_TO 0 +/// define protocol T=1 +#define PROTOCOL_T1 1 + +/// define for dwFeatures see Table 5.1-1 Smart Card Device Class Descriptors +/// No special characteristics +#define CCID_FEATURES_NADA 0x00000000 +/// Automatic parameter configuration based on ATR data +#define CCID_FEATURES_AUTO_PCONF 0x00000002 +/// Automatic activation of ICC on inserting +#define CCID_FEATURES_AUTO_ACTIV 0x00000004 +/// Automatic ICC voltage selection +#define CCID_FEATURES_AUTO_VOLT 0x00000008 +/// Automatic ICC clock frequency change according to active parameters provided +/// by the Host or self determined +#define CCID_FEATURES_AUTO_CLOCK 0x00000010 +/// Automatic baud rate change according to active parameters provided by the +/// Host or self determined +#define CCID_FEATURES_AUTO_BAUD 0x00000020 +/// Automatic parameters negotiation made by the CCID (use of warm or cold +/// resets or PPS according to a manufacturer proprietary algorithm to select +/// the communication parameters with the ICC) +#define CCID_FEATURES_AUTO_PNEGO 0x00000040 +/// Automatic PPS made by the CCID according to the active parameters +#define CCID_FEATURES_AUTO_PPS 0x00000080 +/// CCID can set ICC in clock stop mode +#define CCID_FEATURES_ICCSTOP 0x00000100 +/// NAD value other than 00 accepted (T=1 protocol in use) +#define CCID_FEATURES_NAD 0x00000200 +/// Automatic IFSD exchange as first exchange (T=1 protocol in use) +#define CCID_FEATURES_AUTO_IFSD 0x00000400 +/// TPDU level exchanges with CCID +#define CCID_FEATURES_EXC_TPDU 0x00010000 +/// Short APDU level exchange with CCID +#define CCID_FEATURES_EXC_SAPDU 0x00020000 +/// Short and Extended APDU level exchange with CCID +#define CCID_FEATURES_EXC_APDU 0x00040000 +/// USB Wake up signaling supported on card insertion and removal +#define CCID_FEATURES_WAKEUP 0x00100000 + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/// Bulk CCID Message header structure +typedef struct +{ + unsigned char bMessageType; + /// Message-specific data length + unsigned long wLength; + /// Identifies the slot number for this command + unsigned char bSlot; + /// Sequence number for command. + unsigned char bSeq; + /// Slot status register + unsigned char bStatus; + /// Slot error + unsigned char bError; + /// specific register + unsigned char bSpecific; + /// Data block sent to the CCID. + unsigned char abData[ABDATA_SIZE]; + unsigned char bSizeToSend; +} __attribute__ ((packed)) S_ccid_bulk_in_header; + +/// 6.1 Bulk Transfers +typedef struct +{ + unsigned char bMessageType; + /// Message-specific data length + unsigned long wLength; + /// Identifies the slot number for this command + unsigned char bSlot; + /// Sequence number for command. + unsigned char bSeq; + /// specific register + unsigned char bSpecific_0; + unsigned char bSpecific_1; + unsigned char bSpecific_2; + /// Application Protocol Data Unit + unsigned char APDU[ABDATA_SIZE]; +} __attribute__ ((packed)) S_ccid_bulk_out_header; + + +/// 6.1.11.2 PIN Verification Data Structure +typedef struct +{ + /// Number of seconds. + unsigned char bTimerOut; + /// Several parameters for the PIN format options + unsigned char bmFormatString; + /// Define the length of the PIN to present in the APDU command + unsigned char bmPINBlockString; + /// Allows the length PIN insertion in the APDU command + unsigned char bmPINLengthFormat; + /// Minimum PIN size in digit and Maximum PIN size in digit + unsigned char wPINMaxExtraDigit; + /// The value is a bit wise OR operation. + unsigned char bEntryValidationCondition; + /// Number of messages to display for the PIN modify command + unsigned char bNumberMessage; + /// Language used to display the messages. + unsigned char wLangId; + /// Message index in the Reader message table + unsigned char bMsgIndex; + /// T=1 I-block prologue field to use + unsigned char bTeoPrologue[3]; + /// APDU to send to the ICC + unsigned char abPINApdu[255]; +}__attribute__ ((packed)) S_ccid_PIN_Verification; + + +/// 6.1.11.7 PIN Modification Data Structure +typedef struct +{ + /// Number of seconds. If 00h then CCID default value is used. + unsigned char bTimeOut; + /// Several parameters for the PIN format options (defined in § 6.1.11.4) + unsigned char bmFormatString4; + /// Define the length of the PIN to present in the APDU command + unsigned char bmPINBlockString; + /// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6) + unsigned char bmPinLengthFormat; + /// Insertion position offset in byte for the current PIN + unsigned char bInsertionOffsetOld; + /// Insertion position offset in byte for the new PIN + unsigned char bInsertionOffsetNew; + /// XXYYh + /// XX: Minimum PIN size in digit + /// YY: Maximum PIN size in digit + unsigned char wPINMaxExtraDigit; + /// 00h,01h,02h,03h + /// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted) + /// Indicates if the current PIN must be entered and set in the same APDU field of not. + unsigned char bConfirmPIN; + /// The value is a bit wise OR operation. + /// 01h Max size reached + /// 02h Validation key pressed + /// 04h Timeout occurred + unsigned char bEntryValidationCondition; + /// 00h,01h,02h,03h,or FFh + /// Number of messages to display for the PIN modify command. + unsigned char bNumberMessage; + /// Language used to display the messages. The 16 bit + unsigned char wLangId; + /// Message index in the Reader message table (should be 00h or 01h). + unsigned char bMsgIndex1; + /// Message index in the Reader message table (should be 01h or 02h). + unsigned char bMsgIndex2; + /// Message index in the Reader message table (should be 02h). + unsigned char bMsgIndex3; + /// T=1 I-block prologue field to use. Significant only if protocol in use is T=1. + unsigned char bTeoPrologue[3]; + /// Byte array APDU to send to the ICC + unsigned char abPINApdu[255]; +}__attribute__ ((packed)) S_ccid_PIN_Modification; + +/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h) +typedef struct +{ + /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a + /// clock rate conversion factor + /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a + /// baud rate conversion factor + unsigned char bmFindexDindex; + /// For T=0 ,B0 – 0b, B7-2 – 000000b + /// B1 – Convention used (b1=0 for direct, b1=1 for inverse) + unsigned char bmTCCKST0; // 0 to 2 + /// Extra Guardtime between two characters. Add 0 to 254 etu to the normal + /// guardtime of 12etu. FFh is the same as 00h. + unsigned char bGuardTimeT0; // 0 to FF + /// WI for T=0 used to define WWT + unsigned char bWaitingIntegerT0; // 0 to FF + /// ICC Clock Stop Support + /// 00 = Stopping the Clock is not allowed + /// 01 = Stop with Clock signal Low + /// 02 = Stop with Clock signal High + /// 03 = Stop with Clock either High or Low + unsigned char bClockStop; // 0 to 3 +} __attribute__ ((packed)) S_ccid_protocol_t0; + + +/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h) +typedef struct +{ + /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a + /// clock rate conversion factor + /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a + /// baud rate conversion factor + unsigned char bmFindexDindex; + /// For T=1, B7-2 – 000100b + /// B0 – Checksum type (b0=0 for LRC, b0=1 for CRC + /// B1 – Convention used (b1=0 for direct, b1=1 for inverse) + unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h + /// Extra Guardtime (0 to 254 etu between two characters). + /// If value is FFh, then guardtime is reduced by 1. + unsigned char bGuardTimeT1; // 0 to FF + /// B7-4 = BWI + /// B3-0 = CWI + unsigned char bmWaitingIntegersT1; // 0 to 9 + /// ICC Clock Stop Support + /// 00 = Stopping the Clock is not allowed + /// 01 = Stop with Clock signal Low + /// 02 = Stop with Clock signal High + /// 03 = Stop with Clock either High or Low + unsigned char bClockStop; // 0 to 3 + /// Size of negotiated IFSC + unsigned char bIFSC; // 0 to FE + /// Nad value used by CCID + unsigned char bNadValue; // 0 to FF +} __attribute__ ((packed)) S_ccid_protocol_t1; + + +/// Identifies the length of type of subordinate descriptors of a CCID device +/// Table 5.1-1 Smart Card Device Class descriptors +typedef struct +{ + /// Size of this descriptor, in bytes. + unsigned char bLength; + /// Functional Descriptor type + unsigned char bDescriptorType; + /// Integrated Circuit(s) Cards Interface Devices (CCID) Specification + /// Release Number + unsigned short bcdCCID; + /// Index of the highest available slot. An USB-ICC is regarded as a single + /// slot CCID. + unsigned char bMaxSlotIndex; + /// This value indicates what voltages the CCID can supply to its slots. + /// It is a bitwise OR operation performed on the following values: + /// - 01h 5.0V + /// - 02h 3.0V + /// - 04h 1.8V + /// Other bits are RFU. + unsigned char bVoltageSupport; + /// RRRR –Upper Word- is RFU = 0000h + /// PPPP –Lower Word- Encodes the supported protocol types. A ‘1’ in a given + /// bit position indicates support for the associated ISO protocol. + /// 0001h = Protocol T=0 + /// 0002h = Protocol T=1 + /// All other bits are reserved and must be set to zero. The field is + /// intended to correspond to the PCSC specification definitions. + unsigned long dwProtocols; + /// Default ICC clock frequency in KHz. This is an integer value. + unsigned long dwDefaultClock; + /// Maximum supported ICC clock frequency in KHz. This is an integer value. + unsigned long dwMaximumClock; + /// The number of clock frequencies that are supported by the CCID. If the + /// value is 00h, the supported clock frequencies are assumed to be the + /// default clock frequency defined by dwDefaultClock and the maximum clock + /// frequency defined by dwMaximumClock. + unsigned char bNumClockSupported; + /// Default ICC I/O data rate in bps. This is an integer value + unsigned long dwDataRate; + /// Maximum supported ICC I/O data rate in bps + unsigned long dwMaxDataRate; + /// The number of data rates that are supported by the CCID. + unsigned char bNumDataRatesSupported; + /// Indicates the maximum IFSD supported by CCID for protocol T=1. + unsigned long dwMaxIFSD; + /// - RRRR-Upper Word- is RFU = 0000h + /// - PPPP-Lower Word- encodes the supported protocol types. A ‘1’ in a given + /// bit position indicates support for the associated protocol. + /// 0001h indicates support for the 2-wire protocol 1 + /// 0002h indicates support for the 3-wire protocol 1 + /// 0004h indicates support for the I2C protocol 1 + /// All other values are outside of this specification, and must be handled + /// by vendor-supplied drivers. + unsigned long dwSynchProtocols; + /// The value is a bitwise OR operation performed on the following values: + /// - 00000000h No special characteristics + /// - 00000001h Card accept mechanism 2 + /// - 00000002h Card ejection mechanism 2 + /// - 00000004h Card capture mechanism 2 + /// - 00000008h Card lock/unlock mechanism + unsigned long dwMechanical; + /// This value indicates what intelligent features the CCID has. + unsigned long dwFeatures; + /// For extended APDU level the value shall be between 261 + 10 (header) and + /// 65544 +10, otherwise the minimum value is the wMaxPacketSize of the + /// Bulk-OUT endpoint. + unsigned long dwMaxCCIDMessageLength; + /// Significant only for CCID that offers an APDU level for exchanges. + unsigned char bClassGetResponse; + /// Significant only for CCID that offers an extended APDU level for exchanges. + unsigned char bClassEnvelope; + /// Number of lines and characters for the LCD display used to send messages for PIN entry. + unsigned short wLcdLayout; + /// This value indicates what PIN support features the CCID has. + unsigned char bPINSupport; + /// Maximum number of slots which can be simultaneously busy. + unsigned char bMaxCCIDBusySlots; + +} __attribute__ ((packed)) CCIDDescriptor; + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +extern unsigned char RDRtoPCHardwareError( unsigned char bSlot, + unsigned char bSeq, + unsigned char bHardwareErrorCode ); + +#if !defined(NOAUTOCALLBACK) +extern void USBDCallbacks_RequestReceived(const USBGenericRequest *pRequest); +#endif +extern void CCID_SmartCardRequest( void ); +extern void CCIDDriver_Initialize( void ); +extern unsigned char CCID_Read(void *pBuffer, + unsigned int dLength, + TransferCallback fCallback, + void *pArgument); +extern unsigned char CCID_Write(void *pBuffer, + unsigned int dLength, + TransferCallback fCallback, + void *pArgument); +extern unsigned char CCID_Insertion( void ); +extern unsigned char CCID_Removal( void ); + +#endif //#ifndef CCID_DRIVER_H + diff --git a/at91lib/usb/device/ccid/cciddriverdescriptors.h b/at91lib/usb/device/ccid/cciddriverdescriptors.h new file mode 100644 index 0000000..2daea67 --- /dev/null +++ b/at91lib/usb/device/ccid/cciddriverdescriptors.h @@ -0,0 +1,152 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Title: cciddriverdescriptors.h +// +// About: Purpose +// Definitions of the descriptors required by the ccid device driver. +// DWG_Smart-Card_CCID_Rev110.pdf +//------------------------------------------------------------------------------ + +#ifndef CCID_DRIVER_DESCRIPTORS_H +#define CCID_DRIVER_DESCRIPTORS_H + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constants: Endpoints +// CCID_EPT_DATA_OUT endpoint data out bulk 1 +// CCID_EPT_DATA_IN endpoint data in bulk 2 +// CCID_EPT_NOTIFICATION endpoint data interupt 3 +//------------------------------------------------------------------------------ +#define CCID_EPT_DATA_OUT 1 +#define CCID_EPT_DATA_IN 2 +#define CCID_EPT_NOTIFICATION 3 + +//------------------------------------------------------------------------------ +// USB-ICC protocol +//------------------------------------------------------------------------------ +// CCID specification version 1.10 +#define CCID1_10 0x0110 + +#define SMART_CARD_DEVICE_CLASS 0x0B +// Smart Card Device Class Descriptor Type +#define CCID_DECRIPTOR_TYPE 0x21 + +// Table 5.3-1 Summary of CCID Class Specific Request +#define CCIDGenericRequest_ABORT 0x01 +#define CCIDGenericRequest_GET_CLOCK_FREQUENCIES 0x02 +#define CCIDGenericRequest_GET_DATA_RATES 0x03 + +// 6.1 Command Pipe, Bulk-OUT Messages +#define PC_TO_RDR_ICCPOWERON 0x62 +#define PC_TO_RDR_ICCPOWEROFF 0x63 +#define PC_TO_RDR_GETSLOTSTATUS 0x65 +#define PC_TO_RDR_XFRBLOCK 0x6F +#define PC_TO_RDR_GETPARAMETERS 0x6C +#define PC_TO_RDR_RESETPARAMETERS 0x6D +#define PC_TO_RDR_SETPARAMETERS 0x61 +#define PC_TO_RDR_ESCAPE 0x6B +#define PC_TO_RDR_ICCCLOCK 0x6E +#define PC_TO_RDR_T0APDU 0x6A +#define PC_TO_RDR_SECURE 0x69 +#define PC_TO_RDR_MECHANICAL 0x71 +#define PC_TO_RDR_ABORT 0x72 +#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73 + +// 6.2 Response Pipe, Bulk-IN Messages +#define RDR_TO_PC_DATABLOCK 0x80 +#define RDR_TO_PC_SLOTSTATUS 0x81 +#define RDR_TO_PC_PARAMETERS 0x82 +#define RDR_TO_PC_ESCAPE 0x83 +#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84 + +// 6.3 Interrupt-IN Messages +#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50 +#define RDR_TO_PC_HARDWAREERROR 0x51 + +// Table 6.2-2 Slot error register when bmCommandStatus = 1 +#define CMD_ABORTED 0xFF +#define ICC_MUTE 0xFE +#define XFR_PARITY_ERROR 0xFD +#define XFR_OVERRUN 0xFC +#define HW_ERROR 0xFB +#define BAD_ATR_TS 0xF8 +#define BAD_ATR_TCK 0xF7 +#define ICC_PROTOCOL_NOT_SUPPORTED 0xF6 +#define ICC_CLASS_NOT_SUPPORTED 0xF5 +#define PROCEDURE_BYTE_CONFLICT 0xF4 +#define DEACTIVATED_PROTOCOL 0xF3 +#define BUSY_WITH_AUTO_SEQUENCE 0xF2 +#define PIN_TIMEOUT 0xF0 +#define PIN_CANCELLED 0xEF +#define CMD_SLOT_BUSY 0xE0 +// User defined 0xC0 to 0x81 +// Reserved for futur use 0x80 +// not supported incorrect message parameter 0x7F to 0x01 +// Command not supported 0x00 + +// CCID rev 1.1, p.27 +#define VOLTS_AUTO 0x00 +#define VOLTS_5_0 0x01 +#define VOLTS_3_0 0x02 +#define VOLTS_1_8 0x03 + +// 6.3.1 RDR_to_PC_NotifySlotChange +#define ICC_NOT_PRESENT 0x00 +#define ICC_PRESENT 0x01 +#define ICC_CHANGE 0x02 +#define ICC_INSERTED_EVENT ICC_PRESENT+ICC_CHANGE + +// ICCD: Table 6.1-8 Bitmap for bStatus field +#define ICC_BS_PRESENT_ACTIVATED 0x00 // USB-ICC is present and activated +#define ICC_BS_PRESENT_NOTACTIVATED 0x01 // USB-ICC is present but not activated +#define ICC_BS_NOTPRESENT 0x02 // USB-ICC is virtually not present +#define ICC_BS_RFU 0x03 // RFU +#define ICC_CS_NO_ERROR (0x00<<6) // Processed without error +#define ICC_CS_FAILED (0x01<<6) // Failed, error condition given by bError +#define ICC_CS_TIME_EXT (0x02<<6) // Time extension is requested +#define ICC_CS_RFU (0x03<<6) // RFU + +/* +#define NO_ERROR 0x00 +#define NO_EXTRA_BYTES 0x00 +#define CCID_FLAG_INITIAL_VALUE 0x05 +#define CCID_EVENT_SIZE 0x02 +#define STATUS_MASK 0x41 +*/ +//------------------------------------------------------------------------------ +// Structures +//------------------------------------------------------------------------------ + +#endif //#ifndef CCID_DRIVER_DESCRIPTORS_H + -- cgit v1.2.3