SAMV71 Xplained Ultra Software Package 1.5

cciddriver.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  * \file
00032  *
00033  * \section Purpose
00034  *
00035  *  CCID driver
00036  *
00037  * \section Usage
00038  *
00039  *  Explanation on the usage of the code made available through the header file.
00040  *  \addtogroup usbd_ccid
00041  * @{
00042  */
00043 
00044 /*------------------------------------------------------------------------------
00045  *       Headers
00046  *------------------------------------------------------------------------------*/
00047 
00048 #include <USBD_Config.h>
00049 
00050 #include "USBLib_Trace.h"
00051 #include "USBD.h"
00052 #include "USBDDriver.h"
00053 #include "USBRequests.h"
00054 //#include "USBStringDescriptor.h"
00055 #include "cciddriver.h"
00056 #include "cciddriverdescriptors.h"
00057 #include "iso7816_4.h"
00058 #include <string.h>
00059 
00060 /*------------------------------------------------------------------------------
00061  *         Local definition
00062  *------------------------------------------------------------------------------*/
00063 
00064 /** Constants: IDs: Device product ID. */
00065 
00066 #define CCIDDriverDescriptors_PRODUCTID       0x6129
00067 /** Constants: IDs: Device vendor ID. */
00068 
00069 #define CCIDDriverDescriptors_VENDORID        0x03EB
00070 /** Constants: IDs: Device release number. */
00071 
00072 #define CCIDDriverDescriptors_RELEASE         0x0100
00073 
00074 /** Returns the minimum between two values. */
00075 
00076 #define MIN(a, b)       ((a < b) ? a : b)
00077 
00078 /*------------------------------------------------------------------------------
00079  *         Types
00080  *------------------------------------------------------------------------------*/
00081 
00082 #pragma pack(1)
00083 #if defined   (__CC_ARM ) /* Keil ¦ÌVision 4 */
00084 #elif defined (__ICCARM__) /* IAR Ewarm 5.41+ */
00085     #define __attribute__(...)
00086 #elif defined (__GNUC__) /* GCC CS3 2009q3-68 */
00087 #endif
00088 
00089 /**
00090  * \typedef CCIDDriverConfigurationDescriptors
00091  * \brief List of descriptors that make up the configuration descriptors of a
00092  *        device using the CCID driver.
00093  */
00094 
00095 typedef struct _CCIDDriverConfigurationDescriptors {
00096 
00097     /** Configuration descriptor */
00098     USBConfigurationDescriptor configuration;
00099     /** Interface descriptor */
00100     USBInterfaceDescriptor     interface;
00101     /** CCID descriptor */
00102     CCIDDescriptor             ccid;
00103     /** Bulk OUT endpoint descriptor */
00104     USBEndpointDescriptor      bulkOut;
00105     /** Bulk IN endpoint descriptor */
00106     USBEndpointDescriptor      bulkIn;
00107     /** Interrupt OUT endpoint descriptor */
00108     USBEndpointDescriptor      interruptIn;
00109 
00110 } __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
00111 
00112 #pragma pack()
00113 
00114 /*------------------------------------------------------------------------------
00115  *         Types
00116  *------------------------------------------------------------------------------*/
00117 
00118 /** \brief Driver structure for an CCID device */
00119 
00120 typedef struct {
00121 
00122     /** Standard USB device driver instance */
00123     USBDDriver             usbdDriver;
00124     /** CCID message */
00125     S_ccid_bulk_in_header  sCcidMessage;
00126     /** CCID command */
00127     S_ccid_bulk_out_header sCcidCommand;
00128     /** Interrupt message answer */
00129     unsigned char          BufferINT[4];
00130     /** Buffer data of message */
00131     unsigned char          ProtocolDataStructure[10];
00132     /** Protocol used */
00133     unsigned char          bProtocol;
00134     /** SlotStatus */
00135     /** Bit 0 = Slot 0 current state */
00136     /** Bit 1 = Slot 0 changed status */
00137     /** Bit 2 = Slot 1 current state */
00138     /** Bit 3 = Slot 1 changed status */
00139     /** Bit 4 = Slot 2 current state */
00140     /** Bit 5 = Slot 2 changed status */
00141     unsigned char          SlotStatus;
00142 
00143 } CCIDDriver;
00144 
00145 /*------------------------------------------------------------------------------
00146  *         Local variables
00147  *------------------------------------------------------------------------------*/
00148 
00149 /** Static instance of the CCID device driver. */
00150 static CCIDDriver ccidDriver;
00151 
00152 /** Standard USB device descriptor. */
00153 static const USBDeviceDescriptor deviceDescriptor = {
00154 
00155     sizeof(USBDeviceDescriptor),
00156     USBGenericDescriptor_DEVICE,
00157     USBDeviceDescriptor_USB2_00,
00158     0,
00159     0,
00160     0,
00161     CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
00162     CCIDDriverDescriptors_VENDORID,
00163     CCIDDriverDescriptors_PRODUCTID,
00164     CCIDDriverDescriptors_RELEASE,
00165     1, /* Index of manufacturer description */
00166     2, /* Index of product description */
00167     3, /* Index of serial number description */
00168     1  /* One possible configuration */
00169 
00170 };
00171 
00172 
00173 /** List of configuration descriptors. */
00174 static const CCIDDriverConfigurationDescriptors configurationDescriptorsFS = {
00175 
00176     /* Standard USB configuration descriptor */
00177     {
00178         sizeof(USBConfigurationDescriptor),
00179         USBGenericDescriptor_CONFIGURATION,
00180         sizeof(CCIDDriverConfigurationDescriptors),
00181         1, /* One interface in this configuration */
00182         1, /* This is configuration #1 */
00183         0, /* No associated string descriptor */
00184         USBD_BMATTRIBUTES,
00185         USBConfigurationDescriptor_POWER(100)
00186     },
00187     /* CCID interface descriptor */
00188     /* Table 4.3-1 Interface Descriptor */
00189     /* Interface descriptor */
00190     {
00191         sizeof(USBInterfaceDescriptor),
00192         USBGenericDescriptor_INTERFACE,
00193         0,                       /* Interface 0 */
00194         0,                       /* No alternate settings */
00195         3,                       /* uses bulk-IN, bulk-OUT and interrupt–IN */
00196         SMART_CARD_DEVICE_CLASS,
00197         0,                       /* Subclass code */
00198         0,                       /* bulk transfers optional interrupt-IN */
00199         0                        /* No associated string descriptor */
00200 
00201     },
00202     {
00203         sizeof(CCIDDescriptor), /* bLength: Size of this descriptor in bytes */
00204         CCID_DECRIPTOR_TYPE,    /* bDescriptorType:Functional descriptor type */
00205         CCID1_10,               /* bcdCCID: CCID version */
00206         0,               /* bMaxSlotIndex: Value 0 indicates that one slot is supported */
00207         VOLTS_5_0,       /* bVoltageSupport */
00208         PROTOCOL_TO,     /* dwProtocols */
00209         3580,            /* dwDefaultClock */
00210         3580,            /* dwMaxClock */
00211         0,               /* bNumClockSupported */
00212         9600,            /* dwDataRate : 9600 bauds */
00213         9600,            /* dwMaxDataRate : 9600 bauds */
00214         0,               /* bNumDataRatesSupported */
00215         0xfe,            /* dwMaxIFSD */
00216         0,               /* dwSynchProtocols */
00217         0,               /* dwMechanical */
00218         /*0x00010042,     dwFeatures: Short APDU level exchanges */
00219         CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
00220         0x0000010F,      /* dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 */
00221         0xFF,            /* bClassGetResponse: Echoes the class of the APDU */
00222         0xFF,            /* bClassEnvelope: Echoes the class of the APDU */
00223         0,               /* wLcdLayout: no LCD */
00224         0,               /* bPINSupport: No PIN */
00225         1                /* bMaxCCIDBusySlot */
00226     },
00227     /* Bulk-OUT endpoint descriptor */
00228 
00229     {
00230         sizeof(USBEndpointDescriptor),
00231         USBGenericDescriptor_ENDPOINT,
00232         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT),
00233         USBEndpointDescriptor_BULK,
00234         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
00235         USBEndpointDescriptor_MAXBULKSIZE_FS),
00236         0x00                               /* Does not apply to Bulk endpoints */
00237 
00238     },
00239     /* Bulk-IN endpoint descriptor */
00240 
00241     {
00242         sizeof(USBEndpointDescriptor),
00243         USBGenericDescriptor_ENDPOINT,
00244         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_DATA_IN),
00245         USBEndpointDescriptor_BULK,
00246         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
00247         USBEndpointDescriptor_MAXBULKSIZE_FS),
00248         0x00                               /* Does not apply to Bulk endpoints */
00249 
00250     },
00251     /* Notification endpoint descriptor */
00252 
00253     {
00254         sizeof(USBEndpointDescriptor),
00255         USBGenericDescriptor_ENDPOINT,
00256         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION),
00257         USBEndpointDescriptor_INTERRUPT,
00258         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
00259         USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
00260         0x10
00261     }
00262 };
00263 
00264 #if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
00265 static const CCIDDriverConfigurationDescriptors configurationDescriptorsHS = {
00266 
00267     /* Standard USB configuration descriptor */
00268     {
00269         sizeof(USBConfigurationDescriptor),
00270         USBGenericDescriptor_CONFIGURATION,
00271         sizeof(CCIDDriverConfigurationDescriptors),
00272         1, /* One interface in this configuration */
00273         1, /* This is configuration #1 */
00274         0, /* No associated string descriptor */
00275         USBD_BMATTRIBUTES,
00276         USBConfigurationDescriptor_POWER(100)
00277     },
00278     /* CCID interface descriptor */
00279     /* Table 4.3-1 Interface Descriptor */
00280     /* Interface descriptor */
00281     {
00282         sizeof(USBInterfaceDescriptor),
00283         USBGenericDescriptor_INTERFACE,
00284         0,                       /* Interface 0 */
00285         0,                       /* No alternate settings */
00286         3,                       /* uses bulk-IN, bulk-OUT and interrupt–IN */
00287         SMART_CARD_DEVICE_CLASS,
00288         0,                       /* Subclass code */
00289         0,                       /* bulk transfers optional interrupt-IN */
00290         0                        /* No associated string descriptor */
00291 
00292     },
00293     {
00294         sizeof(CCIDDescriptor), /* bLength: Size of this descriptor in bytes */
00295         CCID_DECRIPTOR_TYPE,    /* bDescriptorType:Functional descriptor type */
00296         CCID1_10,               /* bcdCCID: CCID version */
00297         0,               /* bMaxSlotIndex: Value 0 indicates that one slot is supported */
00298         VOLTS_5_0,       /* bVoltageSupport */
00299         PROTOCOL_TO,     /* dwProtocols */
00300         3580,            /* dwDefaultClock */
00301         3580,            /* dwMaxClock */
00302         0,               /* bNumClockSupported */
00303         9600,            /* dwDataRate : 9600 bauds */
00304         9600,            /* dwMaxDataRate : 9600 bauds */
00305         0,               /* bNumDataRatesSupported */
00306         0xfe,            /* dwMaxIFSD */
00307         0,               /* dwSynchProtocols */
00308         0,               /* dwMechanical */
00309         /*0x00010042,     dwFeatures: Short APDU level exchanges */
00310         CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
00311         0x0000010F,      /* dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 */
00312         0xFF,            /* bClassGetResponse: Echoes the class of the APDU */
00313         0xFF,            /* bClassEnvelope: Echoes the class of the APDU */
00314         0,               /* wLcdLayout: no LCD */
00315         0,               /* bPINSupport: No PIN */
00316         1                /* bMaxCCIDBusySlot */
00317     },
00318     /* Bulk-OUT endpoint descriptor */
00319     {
00320         sizeof(USBEndpointDescriptor),
00321         USBGenericDescriptor_ENDPOINT,
00322         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT),
00323         USBEndpointDescriptor_BULK,
00324         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
00325         USBEndpointDescriptor_MAXBULKSIZE_HS),
00326         0x00                               /* Does not apply to Bulk endpoints */
00327 
00328     },
00329     /* Bulk-IN endpoint descriptor */
00330 
00331     {
00332         sizeof(USBEndpointDescriptor),
00333         USBGenericDescriptor_ENDPOINT,
00334         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_DATA_IN),
00335         USBEndpointDescriptor_BULK,
00336         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
00337         USBEndpointDescriptor_MAXBULKSIZE_HS),
00338         0x00                               /* Does not apply to Bulk endpoints */
00339 
00340     },
00341     /* Notification endpoint descriptor */
00342 
00343     {
00344         sizeof(USBEndpointDescriptor),
00345         USBGenericDescriptor_ENDPOINT,
00346         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION),
00347         USBEndpointDescriptor_INTERRUPT,
00348         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
00349         USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
00350         0x10
00351     }
00352 };
00353 
00354 /** Qualifier descriptor */
00355 
00356 const USBDeviceQualifierDescriptor deviceQualifierDescriptor = {
00357 
00358     sizeof(USBDeviceQualifierDescriptor),  /* Size of this descriptor in bytes */
00359     USBGenericDescriptor_DEVICEQUALIFIER,  /* Qualifier Descriptor Type */
00360     USBDeviceDescriptor_USB2_00,           /* USB specification 2.00 */
00361     0x00,                                  /* Class is specified in interface */
00362     0x00,                                  /* Subclass is specified in interface */
00363     0x00,                                  /* Protocol is specified in interface */
00364     CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
00365     0x01,                                  /* One possible configuration */
00366     0x00                                   /* Reserved for future use, must be zero */
00367 
00368 };
00369 
00370 /** OtherSpeed configuration descriptor in Full Speed mode */
00371 
00372 static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationFS = {
00373 
00374     /* Standard USB configuration descriptor */
00375 
00376     {
00377         sizeof(USBConfigurationDescriptor),
00378         USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
00379         sizeof(CCIDDriverConfigurationDescriptors),
00380         1, /* One interface in this configuration */
00381         1, /* This is configuration #1 */
00382         0, /* No associated string descriptor */
00383         USBD_BMATTRIBUTES,
00384         USBConfigurationDescriptor_POWER(100)
00385     },
00386     /* CCID interface descriptor */
00387     /* Table 4.3-1 Interface Descriptor */
00388     /* Interface descriptor */
00389     {
00390         sizeof(USBInterfaceDescriptor),
00391         USBGenericDescriptor_INTERFACE,
00392         0,                       /* Interface 0 */
00393         0,                       /* No alternate settings */
00394         3,                       /* uses bulk-IN, bulk-OUT and interrupt–IN */
00395         SMART_CARD_DEVICE_CLASS,
00396         0,                       /* Subclass code */
00397         0,                       /* bulk transfers optional interrupt-IN */
00398         0                        /* No associated string descriptor */
00399     },
00400     {
00401         sizeof(CCIDDescriptor), /* bLength: Size of this descriptor in bytes */
00402         CCID_DECRIPTOR_TYPE,    /* bDescriptorType:Functional descriptor type */
00403         CCID1_10,               /* bcdCCID: CCID version */
00404         0,               /* bMaxSlotIndex: Value 0 indicates that one slot is supported */
00405         VOLTS_5_0,       /* bVoltageSupport */
00406         PROTOCOL_TO,     /* dwProtocols */
00407         3580,            /* dwDefaultClock */
00408         3580,            /* dwMaxClock */
00409         0,               /* bNumClockSupported */
00410         9600,            /* dwDataRate : 9600 bauds */
00411         9600,            /* dwMaxDataRate : 9600 bauds */
00412         0,               /* bNumDataRatesSupported */
00413         0xfe,            /* dwMaxIFSD */
00414         0,               /* dwSynchProtocols */
00415         0,               /* dwMechanical */
00416         /*0x00010042,     dwFeatures: Short APDU level exchanges */
00417         CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
00418         0x0000010F,      /* dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 */
00419         0xFF,            /* bClassGetResponse: Echoes the class of the APDU */
00420         0xFF,            /* bClassEnvelope: Echoes the class of the APDU */
00421         0,               /* wLcdLayout: no LCD */
00422         0,               /* bPINSupport: No PIN */
00423         1                /* bMaxCCIDBusySlot */
00424     },
00425     /* Bulk-OUT endpoint descriptor */
00426 
00427     {
00428         sizeof(USBEndpointDescriptor),
00429         USBGenericDescriptor_ENDPOINT,
00430         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT),
00431         USBEndpointDescriptor_BULK,
00432         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
00433         USBEndpointDescriptor_MAXBULKSIZE_FS),
00434         0x00                               /* Does not apply to Bulk endpoints */
00435 
00436     },
00437     /* Bulk-IN endpoint descriptor */
00438 
00439     {
00440         sizeof(USBEndpointDescriptor),
00441         USBGenericDescriptor_ENDPOINT,
00442         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_DATA_IN),
00443         USBEndpointDescriptor_BULK,
00444         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
00445         USBEndpointDescriptor_MAXBULKSIZE_FS),
00446         0x00                               /* Does not apply to Bulk endpoints */
00447 
00448     },
00449     /* Notification endpoint descriptor */
00450 
00451     {
00452         sizeof(USBEndpointDescriptor),
00453         USBGenericDescriptor_ENDPOINT,
00454         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION),
00455         USBEndpointDescriptor_INTERRUPT,
00456         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
00457         USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
00458         0x10
00459     }
00460 };
00461 
00462 /** OtherSpeed configuration descriptor in High Speed mode */
00463 
00464 static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationHS = {
00465 
00466     /* Standard USB configuration descriptor */
00467 
00468     {
00469         sizeof(USBConfigurationDescriptor),
00470         USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
00471         sizeof(CCIDDriverConfigurationDescriptors),
00472         1, /* One interface in this configuration */
00473         1, /* This is configuration #1 */
00474         0, /* No associated string descriptor */
00475         USBD_BMATTRIBUTES,
00476         USBConfigurationDescriptor_POWER(100)
00477     },
00478     /* CCID interface descriptor */
00479     /* Table 4.3-1 Interface Descriptor */
00480     /* Interface descriptor */
00481     {
00482         sizeof(USBInterfaceDescriptor),
00483         USBGenericDescriptor_INTERFACE,
00484         0,                       /* Interface 0 */
00485         0,                       /* No alternate settings */
00486         3,                       /* uses bulk-IN, bulk-OUT and interrupt–IN */
00487         SMART_CARD_DEVICE_CLASS,
00488         0,                       /* Subclass code */
00489         0,                       /* bulk transfers optional interrupt-IN */
00490         0                        /* No associated string descriptor */
00491     },
00492     {
00493         sizeof(CCIDDescriptor), /* bLength: Size of this descriptor in bytes */
00494         CCID_DECRIPTOR_TYPE,    /* bDescriptorType:Functional descriptor type */
00495         CCID1_10,               /* bcdCCID: CCID version */
00496         0,               /* bMaxSlotIndex: Value 0 indicates that one slot is supported */
00497         VOLTS_5_0,       /* bVoltageSupport */
00498         PROTOCOL_TO,     /* dwProtocols */
00499         3580,            /* dwDefaultClock */
00500         3580,            /* dwMaxClock */
00501         0,               /* bNumClockSupported */
00502         9600,            /* dwDataRate : 9600 bauds */
00503         9600,            /* dwMaxDataRate : 9600 bauds */
00504         0,               /* bNumDataRatesSupported */
00505         0xfe,            /* dwMaxIFSD */
00506         0,               /* dwSynchProtocols */
00507         0,               /* dwMechanical */
00508         /*0x00010042,      // dwFeatures: Short APDU level exchanges */
00509         CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
00510         0x0000010F,      /* dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10 */
00511         0xFF,            /* bClassGetResponse: Echoes the class of the APDU */
00512         0xFF,            /* bClassEnvelope: Echoes the class of the APDU */
00513         0,               /* wLcdLayout: no LCD */
00514         0,               /* bPINSupport: No PIN */
00515         1                /* bMaxCCIDBusySlot */
00516     },
00517     /* Bulk-OUT endpoint descriptor */
00518     {
00519         sizeof(USBEndpointDescriptor),
00520         USBGenericDescriptor_ENDPOINT,
00521         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT),
00522         USBEndpointDescriptor_BULK,
00523         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
00524         USBEndpointDescriptor_MAXBULKSIZE_HS),
00525         0x00                               /* Does not apply to Bulk endpoints */
00526 
00527     },
00528     /* Bulk-IN endpoint descriptor */
00529     {
00530         sizeof(USBEndpointDescriptor),
00531         USBGenericDescriptor_ENDPOINT,
00532         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_DATA_IN),
00533         USBEndpointDescriptor_BULK,
00534         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
00535         USBEndpointDescriptor_MAXBULKSIZE_HS),
00536         0x00                               /* Does not apply to Bulk endpoints */
00537 
00538     },
00539     /* Notification endpoint descriptor */
00540     {
00541         sizeof(USBEndpointDescriptor),
00542         USBGenericDescriptor_ENDPOINT,
00543         USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION),
00544         USBEndpointDescriptor_INTERRUPT,
00545         MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
00546         USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
00547         0x10
00548     }
00549 };
00550 #endif
00551 
00552 /** Language ID string descriptor. */
00553 static const unsigned char languageIdDescriptor[] = {
00554 
00555     USBStringDescriptor_LENGTH(1),
00556     USBGenericDescriptor_STRING,
00557     USBStringDescriptor_ENGLISH_US
00558 };
00559 
00560 /** Manufacturer name. */
00561 static const unsigned char manufacturerDescriptor[] = {
00562 
00563     USBStringDescriptor_LENGTH(5),
00564     USBGenericDescriptor_STRING,
00565     USBStringDescriptor_UNICODE('A'),
00566     USBStringDescriptor_UNICODE('T'),
00567     USBStringDescriptor_UNICODE('M'),
00568     USBStringDescriptor_UNICODE('E'),
00569     USBStringDescriptor_UNICODE('L')
00570 };
00571 
00572 /** Product name. */
00573 static const unsigned char productDescriptor[] = {
00574 
00575     USBStringDescriptor_LENGTH(23),
00576     USBGenericDescriptor_STRING,
00577     USBStringDescriptor_UNICODE('A'),
00578     USBStringDescriptor_UNICODE('T'),
00579     USBStringDescriptor_UNICODE('M'),
00580     USBStringDescriptor_UNICODE('E'),
00581     USBStringDescriptor_UNICODE('L'),
00582     USBStringDescriptor_UNICODE(' '),
00583     USBStringDescriptor_UNICODE('A'),
00584     USBStringDescriptor_UNICODE('T'),
00585     USBStringDescriptor_UNICODE('9'),
00586     USBStringDescriptor_UNICODE('1'),
00587     USBStringDescriptor_UNICODE(' '),
00588     USBStringDescriptor_UNICODE('C'),
00589     USBStringDescriptor_UNICODE('C'),
00590     USBStringDescriptor_UNICODE('I'),
00591     USBStringDescriptor_UNICODE('D'),
00592     USBStringDescriptor_UNICODE(' '),
00593     USBStringDescriptor_UNICODE('D'),
00594     USBStringDescriptor_UNICODE('R'),
00595     USBStringDescriptor_UNICODE('I'),
00596     USBStringDescriptor_UNICODE('V'),
00597     USBStringDescriptor_UNICODE('E'),
00598     USBStringDescriptor_UNICODE('R'),
00599     USBStringDescriptor_UNICODE(' ')
00600 };
00601 
00602 /** Product serial number. */
00603 static const unsigned char serialNumberDescriptor[] = {
00604 
00605     USBStringDescriptor_LENGTH(12),
00606     USBGenericDescriptor_STRING,
00607     USBStringDescriptor_UNICODE('0'),
00608     USBStringDescriptor_UNICODE('1'),
00609     USBStringDescriptor_UNICODE('2'),
00610     USBStringDescriptor_UNICODE('3'),
00611     USBStringDescriptor_UNICODE('4'),
00612     USBStringDescriptor_UNICODE('5'),
00613     USBStringDescriptor_UNICODE('6'),
00614     USBStringDescriptor_UNICODE('7'),
00615     USBStringDescriptor_UNICODE('8'),
00616     USBStringDescriptor_UNICODE('9'),
00617     USBStringDescriptor_UNICODE('A'),
00618     USBStringDescriptor_UNICODE('F')
00619 };
00620 
00621 /** Array of pointers to string descriptors. */
00622 static const unsigned char *stringDescriptors[] = {
00623 
00624     languageIdDescriptor,
00625     manufacturerDescriptor,
00626     productDescriptor,
00627     serialNumberDescriptor
00628 };
00629 
00630 
00631 /** List of standard descriptors for the serial driver. */
00632 const USBDDriverDescriptors ccidDriverDescriptors = {
00633 
00634     &deviceDescriptor, /* FS */
00635 
00636     (USBConfigurationDescriptor *) &configurationDescriptorsFS,
00637 #if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
00638     (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, /* FS */
00639     (USBConfigurationDescriptor *) &sOtherSpeedConfigurationFS,
00640     &deviceDescriptor, /* HS */
00641     (USBConfigurationDescriptor *) &configurationDescriptorsHS,
00642     (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, /* HS */
00643 
00644     (USBConfigurationDescriptor *) &sOtherSpeedConfigurationHS,
00645 #else
00646     0, /* No qualifier descriptor FS */
00647     0, /* No other-speed configuration FS */
00648     0, /* No device descriptor HS */
00649     0, /* No configuration HS */
00650     0, /* No qualifier descriptor HS */
00651     0, /* No other-speed configuration HS */
00652 #endif
00653     stringDescriptors,
00654     4 /* Four string descriptors in array */
00655 
00656 };
00657 
00658 /*------------------------------------------------------------------------------
00659  *      Internal functions
00660  *------------------------------------------------------------------------------*/
00661 
00662 /**
00663  * Response Pipe, Bulk-IN Messages
00664  * Return the Slot Status to the host
00665  * Answer to:
00666  * PC_to_RDR_IccPowerOff
00667  * PC_to_RDR_GetSlotStatus
00668  * PC_to_RDR_IccClock
00669  * PC_to_RDR_T0APDU
00670  * PC_to_RDR_Mechanical
00671  * PC_to_RDR_Abort and Class specific ABORT request
00672  */
00673 
00674 static void RDRtoPCSlotStatus(void)
00675 {
00676     TRACE_DEBUG("RDRtoPCSlotStatus\n\r");
00677 
00678     /* Header fields settings */
00679 
00680     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
00681     ccidDriver.sCcidMessage.wLength   = 0;
00682     ccidDriver.sCcidMessage.bStatus   = ccidDriver.SlotStatus;
00683     ccidDriver.sCcidMessage.bError    = 0;
00684     /* 00h Clock running */
00685 
00686     /* 01h Clock stopped in state L */
00687 
00688     /* 02h Clock stopped in state H */
00689 
00690     /* 03h Clock stopped in an unknown state */
00691 
00692     /* All other values are Reserved for Future Use. */
00693 
00694     ccidDriver.sCcidMessage.bSpecific = 0;
00695 }
00696 
00697 /**
00698  * Response Pipe, Bulk-IN Messages
00699  * Answer to PC_to_RDR_IccPowerOn
00700  */
00701 static void RDRtoPCDatablock_ATR(void)
00702 {
00703     unsigned char i;
00704     unsigned char Atr[ATR_SIZE_MAX];
00705     unsigned char length;
00706 
00707     /*TRACE_DEBUG("RDRtoPCDatablock\n\r"); */
00708 
00709 
00710     ISO7816_Datablock_ATR(Atr, &length);
00711 
00712     if (length > 5) {
00713         ccidDriver.ProtocolDataStructure[1] = Atr[5] & 0x0F; /* TD(1) */
00714 
00715         ccidDriver.bProtocol = Atr[5] & 0x0F;         /* TD(1) */
00716 
00717     }
00718 
00719     /* S_ccid_protocol_t0 */
00720 
00721     /* bmFindexDindex */
00722 
00723     ccidDriver.ProtocolDataStructure[0] = Atr[2];     /* TA(1) */
00724 
00725 
00726     /* bmTCCKST0 */
00727 
00728     /* For T=0 ,B0 ?0b, B7-2 ?000000b */
00729 
00730     /* B1 ?Convention used (b1=0 for direct, b1=1 for inverse) */
00731 
00732 
00733     /* bGuardTimeT0 */
00734 
00735     /* Extra Guardtime between two characters. Add 0 to 254 etu to the normal */
00736 
00737     /* guardtime of 12etu. FFh is the same as 00h. */
00738 
00739     ccidDriver.ProtocolDataStructure[2] = Atr[4];     /* TC(1) */
00740 
00741     /* AT91C_BASE_US0->US_TTGR = 0;  // TC1 */
00742 
00743 
00744     /* bWaitingIntegerT0 */
00745 
00746     /* WI for T=0 used to define WWT */
00747 
00748     ccidDriver.ProtocolDataStructure[3] = Atr[7];     /* TC(2) */
00749 
00750 
00751     /* bClockStop */
00752 
00753     /* ICC Clock Stop Support */
00754 
00755     /* 00 = Stopping the Clock is not allowed */
00756 
00757     /* 01 = Stop with Clock signal Low */
00758 
00759     /* 02 = Stop with Clock signal High */
00760 
00761     /* 03 = Stop with Clock either High or Low */
00762 
00763     ccidDriver.ProtocolDataStructure[4] = 0x00;       /* 0 to 3 */
00764 
00765 
00766     /* Header fields settings */
00767 
00768     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
00769     ccidDriver.sCcidMessage.wLength      = length;  /* Size of ATR */
00770 
00771     ccidDriver.sCcidMessage.bSizeToSend += length;  /* Size of ATR */
00772 
00773     /* bChainParameter: 00 the response APDU begins and ends in this command */
00774 
00775     ccidDriver.sCcidMessage.bSpecific    = 0;
00776 
00777     for (i = 0; i < length; i++)
00778 
00779         ccidDriver.sCcidMessage.abData[i]  = Atr[i];
00780 
00781     /* Set the slot to an active status */
00782 
00783     ccidDriver.sCcidMessage.bStatus = 0;
00784     ccidDriver.sCcidMessage.bError = 0;
00785 }
00786 
00787 /**
00788  * Response Pipe, Bulk-IN Messages
00789  * In other cases, the response message has the following format:
00790  * The response data will contain the optional data returned by the ICC,
00791  * followed by the 2 byte-size status words SW1-SW2.
00792  *
00793  * Answer to:
00794  *   PC_to_RDR_XfrBlock
00795  *   PC_to_RDR_Secure
00796  */
00797 static void RDRtoPCDatablock(void)
00798 {
00799     /*TRACE_DEBUG("RDRtoPCDatablock\n\r"); */
00800 
00801 
00802     /* Header fields settings */
00803 
00804     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
00805     ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
00806     /* bChainParameter: 00 the response APDU begins and ends in this command */
00807 
00808     ccidDriver.sCcidMessage.bSpecific = 0;
00809 
00810     /* Set the slot to an active status */
00811 
00812     ccidDriver.sCcidMessage.bStatus = 0;
00813     ccidDriver.sCcidMessage.bError = 0;
00814 }
00815 
00816 /**
00817  * Response Pipe, Bulk-IN Messages
00818  * Answer to:
00819  *   PC_to_RDR_GetParameters
00820  *   PC_to_RDR_ResetParameters
00821  *   PC_to_RDR_SetParameters
00822  */
00823 static void RDRtoPCParameters(void)
00824 {
00825     unsigned int i;
00826 
00827     TRACE_DEBUG("RDRtoPCParameters\n\r");
00828 
00829     /* Header fields settings */
00830 
00831     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_PARAMETERS;
00832 
00833     /*ccidDriver.sCcidMessage.bStatus = 0; */
00834 
00835     ccidDriver.sCcidMessage.bError  = 0;
00836 
00837     if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) {
00838 
00839         /* T=0 */
00840 
00841         ccidDriver.sCcidMessage.wLength   = sizeof(S_ccid_protocol_t0);
00842         ccidDriver.sCcidMessage.bSpecific = PROTOCOL_TO;
00843     } else {
00844 
00845         /* T=1 */
00846 
00847         ccidDriver.sCcidMessage.wLength   = sizeof(S_ccid_protocol_t1);
00848         ccidDriver.sCcidMessage.bSpecific = PROTOCOL_T1;
00849     }
00850 
00851     ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
00852 
00853     for (i = 0; i < ccidDriver.sCcidMessage.wLength; i++)
00854         ccidDriver.sCcidMessage.abData[i] = ccidDriver.ProtocolDataStructure[i];
00855 
00856 }
00857 
00858 /**
00859  * Response Pipe, Bulk-IN Messages
00860  * Answer to:
00861  *   PC_to_RDR_Escape
00862  */
00863 static void RDRtoPCEscape(unsigned char length,
00864                            unsigned char *data_send_from_CCID)
00865 {
00866     unsigned int i;
00867 
00868     TRACE_DEBUG("RDRtoPCEscape\n\r");
00869 
00870     /* Header fields settings */
00871 
00872     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_ESCAPE;
00873 
00874     ccidDriver.sCcidMessage.wLength = length;
00875 
00876     ccidDriver.sCcidMessage.bStatus = 0;
00877     ccidDriver.sCcidMessage.bError  = 0;
00878 
00879     ccidDriver.sCcidMessage.bSpecific = 0;  /* bRFU */
00880 
00881 
00882     for (i = 0; i < length; i++)
00883         ccidDriver.sCcidMessage.abData[i] = data_send_from_CCID[i];
00884 }
00885 
00886 /**
00887  * Response Pipe, Bulk-IN Messages
00888  * Answer to:
00889  *   PC_to_RDR_SetDataRateAndClockFrequency
00890  */
00891 static void RDRtoPCDataRateAndClockFrequency(unsigned int dwClockFrequency,
00892         unsigned int dwDataRate)
00893 {
00894     TRACE_DEBUG("RDRtoPCDataRateAndClockFrequency\n\r");
00895 
00896     /* Header fields settings */
00897 
00898     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATARATEANDCLOCKFREQUENCY;
00899 
00900     ccidDriver.sCcidMessage.wLength   = 8;
00901 
00902     ccidDriver.sCcidMessage.bStatus = 0;
00903     ccidDriver.sCcidMessage.bError  = 0;
00904 
00905     ccidDriver.sCcidMessage.bSpecific = 0;  /* bRFU */
00906 
00907 
00908     ccidDriver.sCcidMessage.abData[0] = dwClockFrequency;
00909 
00910     ccidDriver.sCcidMessage.abData[4] = dwDataRate;
00911 }
00912 
00913 /**
00914  * Command Pipe, Bulk-OUT Messages
00915  * Power On Command - Cold Reset & Warm Reset
00916  * Return the ATR to the host
00917  */
00918 static void PCtoRDRIccPowerOn(void)
00919 {
00920     TRACE_DEBUG("PCtoRDRIccPowerOn\n\r");
00921 
00922     if (CCID_FEATURES_AUTO_VOLT == (configurationDescriptorsFS.ccid.dwFeatures &
00923                                      CCID_FEATURES_AUTO_VOLT)) {
00924 
00925         /* bPowerSelect = ccidDriver.sCcidCommand.bSpecific_0; */
00926 
00927         ccidDriver.sCcidCommand.bSpecific_0 = VOLTS_AUTO;
00928     }
00929 
00930     ISO7816_cold_reset();
00931 
00932     /* for emulation only //JCB */
00933 
00934     if (ccidDriver.sCcidCommand.bSpecific_0 != VOLTS_5_0) {
00935 
00936         TRACE_ERROR("POWER_NOT_SUPPORTED\n\r");
00937     }
00938     else
00939         RDRtoPCDatablock_ATR();
00940 
00941 }
00942 
00943 /**
00944  * Command Pipe, Bulk-OUT Messages
00945  * Power Off Command - Set the ICC in an inactive state
00946  * Return the slot status to the host
00947  */
00948 static void PCtoRDRIccPowerOff(void)
00949 {
00950     unsigned char bStatus;
00951 
00952     TRACE_DEBUG("PCtoRDRIccPowerOff\n\r");
00953 
00954     ISO7816_IccPowerOff();
00955 
00956     /*JCB stub */
00957 
00958     bStatus = ICC_BS_PRESENT_NOTACTIVATED;
00959 
00960     /* Set the slot to an inactive status */
00961 
00962     ccidDriver.sCcidMessage.bStatus = 0;
00963     ccidDriver.sCcidMessage.bError = 0;
00964 
00965     /* if error, see Table 6.1-2 errors */
00966 
00967 
00968     /* Return the slot status to the host */
00969 
00970     RDRtoPCSlotStatus();
00971 }
00972 
00973 /**
00974  * Command Pipe, Bulk-OUT Messages
00975  * Get slot status
00976  */
00977 static void PCtoRDRGetSlotStatus(void)
00978 {
00979     TRACE_DEBUG("PCtoRDRGetSlotStatus\n\r");
00980 
00981     ccidDriver.sCcidMessage.bStatus = 0;
00982     ccidDriver.sCcidMessage.bError = 0;
00983 
00984     /* Return the slot status to the host */
00985 
00986     RDRtoPCSlotStatus();
00987 }
00988 
00989 /**
00990  * Command Pipe, Bulk-OUT Messages
00991  * If the command header is valid, an APDU command is received and can be read
00992  * by the application
00993  */
00994 static void PCtoRDRXfrBlock(void)
00995 {
00996     unsigned char indexMessage = 0;
00997     unsigned char i;
00998 
00999     /*TRACE_DEBUG("PCtoRDRXfrBlock\n\r"); */
01000 
01001 
01002     i = 0;
01003 
01004     /* Check the block length */
01005 
01006     if (ccidDriver.sCcidCommand.wLength >
01007          (configurationDescriptorsFS.ccid.dwMaxCCIDMessageLength - 10)) {
01008 
01009         ccidDriver.sCcidMessage.bStatus = 1;
01010         ccidDriver.sCcidMessage.bError  = 0;
01011     }
01012     /* check bBWI */
01013 
01014     else if (0 != ccidDriver.sCcidCommand.bSpecific_0) {
01015         TRACE_ERROR("Bad bBWI\n\r");
01016     }
01017     else {
01018 
01019         /* APDU or TPDU */
01020         switch (configurationDescriptorsFS.ccid.dwFeatures
01021                 & (CCID_FEATURES_EXC_TPDU | CCID_FEATURES_EXC_SAPDU | CCID_FEATURES_EXC_APDU)) {
01022 
01023         case CCID_FEATURES_EXC_TPDU:
01024             if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) {
01025 
01026                 /* Send commande APDU */
01027                 indexMessage = ISO7816_XfrBlockTPDU_T0(ccidDriver.sCcidCommand.APDU ,
01028                                                         ccidDriver.sCcidMessage.abData,
01029                                                         ccidDriver.sCcidCommand.wLength);
01030             } else {
01031                 if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_T1) {
01032                     TRACE_INFO("Not supported T=1\n\r");
01033                 }
01034                 else {
01035                     TRACE_INFO("Not supported\n\r");
01036                 }
01037             }
01038 
01039             break;
01040 
01041         case CCID_FEATURES_EXC_APDU:
01042             TRACE_INFO("Not supported\n\r");
01043             break;
01044 
01045         default:
01046             break;
01047         }
01048 
01049     }
01050 
01051     ccidDriver.sCcidMessage.wLength = indexMessage;
01052     TRACE_DEBUG("USB: 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\n\r",
01053                 ccidDriver.sCcidMessage.abData[0],
01054                 ccidDriver.sCcidMessage.abData[1],
01055                 ccidDriver.sCcidMessage.abData[2],
01056                 ccidDriver.sCcidMessage.abData[3],
01057                 ccidDriver.sCcidMessage.abData[4]);
01058     RDRtoPCDatablock();
01059 
01060 }
01061 
01062 /**
01063  * Command Pipe, Bulk-OUT Messages
01064  * return parameters by the command: RDR_to_PC_Parameters
01065  */
01066 static void PCtoRDRGetParameters(void)
01067 {
01068     TRACE_DEBUG("PCtoRDRGetParameters\n\r");
01069 
01070     /* We support only one slot */
01071 
01072 
01073     /* bmIccStatus */
01074 
01075     if (ISO7816_StatusReset()) {
01076         /* 0: An ICC is present and active (power is on and stable, RST is inactive */
01077 
01078         ccidDriver.sCcidMessage.bStatus = 0;
01079     } else {
01080         /* 1: An ICC is present and inactive (not activated or shut down by hardware error) */
01081 
01082         ccidDriver.sCcidMessage.bStatus = 1;
01083     }
01084 
01085     RDRtoPCParameters();
01086 }
01087 
01088 /**
01089  * Command Pipe, Bulk-OUT Messages
01090  * This command resets the slot parameters to their default values
01091  */
01092 static void PCtoRDRResetParameters(void)
01093 {
01094     TRACE_DEBUG("PCtoRDRResetParameters\n\r");
01095 
01096     ccidDriver.SlotStatus = ICC_NOT_PRESENT;
01097     ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
01098 
01099     RDRtoPCParameters();
01100 }
01101 
01102 /**
01103  * Command Pipe, Bulk-OUT Messages
01104  * This command is used to change the parameters for a given slot.
01105  */
01106 static void PCtoRDRSetParameters(void)
01107 {
01108     TRACE_DEBUG("PCtoRDRSetParameters\n\r");
01109 
01110     ccidDriver.SlotStatus = ccidDriver.sCcidCommand.bSlot;
01111     ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
01112     /* Not all feature supported */
01113 
01114 
01115     RDRtoPCParameters();
01116 }
01117 
01118 /**
01119  * Command Pipe, Bulk-OUT Messages
01120  * This command allows the CCID manufacturer to define and access extended
01121  * features.
01122  * Information sent via this command is processed by the CCID control logic.
01123  */
01124 static void PCtoRDREscape(void)
01125 {
01126     TRACE_DEBUG("PCtoRDREscape\n\r");
01127 
01128     /* If needed by the user */
01129 
01130     ISO7816_Escape();
01131 
01132     /* stub, return all value send */
01133 
01134     RDRtoPCEscape(ccidDriver.sCcidCommand.wLength, ccidDriver.sCcidCommand.APDU);
01135 }
01136 
01137 /**
01138  * Command Pipe, Bulk-OUT Messages
01139  * This command stops or restarts the clock.
01140  */
01141 static void PCtoRDRICCClock(void)
01142 {
01143     TRACE_DEBUG("PCtoRDRICCClock\n\r");
01144 
01145     if (0 == ccidDriver.sCcidCommand.bSpecific_0) {
01146         /* restarts the clock */
01147 
01148         ISO7816_RestartClock();
01149     } else {
01150         /* stop clock in the state shown in the bClockStop field */
01151 
01152         ISO7816_StopClock();
01153     }
01154 
01155     RDRtoPCSlotStatus();
01156 }
01157 
01158 /**
01159  * Command Pipe, Bulk-OUT Messages
01160  * This command changes the parameters used to perform the transportation of
01161  * APDU messages by the T=0 protocol.
01162  */
01163 static void PCtoRDRtoAPDU(void)
01164 {
01165     unsigned char bmChanges;
01166     unsigned char bClassGetResponse;
01167     unsigned char bClassEnvelope;
01168 
01169     TRACE_DEBUG("PCtoRDRtoAPDU\n\r");
01170 
01171     if (configurationDescriptorsFS.ccid.dwFeatures == (CCID_FEATURES_EXC_SAPDU |
01172             CCID_FEATURES_EXC_APDU)) {
01173 
01174         bmChanges = ccidDriver.sCcidCommand.bSpecific_0;
01175         bClassGetResponse = ccidDriver.sCcidCommand.bSpecific_1;
01176         bClassEnvelope = ccidDriver.sCcidCommand.bSpecific_2;
01177 
01178         ISO7816_toAPDU();
01179     }
01180 
01181     RDRtoPCSlotStatus();
01182 }
01183 
01184 /**
01185  * Command Pipe, Bulk-OUT Messages
01186  * This is a command message to allow entering the PIN for verification or
01187  * modification.
01188  */
01189 static void PCtoRDRSecure(void)
01190 {
01191     TRACE_DEBUG("PCtoRDRSecure\n\r");
01192 
01193     TRACE_DEBUG("For user\n\r");
01194 }
01195 
01196 /**
01197  * Command Pipe, Bulk-OUT Messages
01198  * This command is used to manage motorized type CCID functionality.
01199  * The Lock Card function is used to hold the ICC.
01200  * This prevents an ICC from being easily removed from the CCID.
01201  * The Unlock Card function is used to remove the hold initiated by the Lock
01202  * Card function
01203  */
01204 static void PCtoRDRMechanical(void)
01205 {
01206     TRACE_DEBUG("PCtoRDRMechanical\n\r");
01207     TRACE_DEBUG("Not implemented\n\r");
01208 
01209     RDRtoPCSlotStatus();
01210 }
01211 
01212 /**
01213  * Command Pipe, Bulk-OUT Messages
01214  * This command is used with the Control pipe Abort request to tell the CCID
01215  * to stop any current transfer at the specified slot and return to a state
01216  * where the slot is ready to accept a new command pipe Bulk-OUT message.
01217  */
01218 static void PCtoRDRAbort(void)
01219 {
01220     TRACE_DEBUG("PCtoRDRAbort\n\r");
01221 
01222     RDRtoPCSlotStatus();
01223 }
01224 
01225 /**
01226  * Command Pipe, Bulk-OUT Messages
01227  * This command is used to manually set the data rate and clock frequency of
01228  * a specific slot.
01229  */
01230 static void PCtoRDRSetDataRateAndClockFrequency(void)
01231 {
01232     unsigned int dwClockFrequency;
01233     unsigned int dwDataRate;
01234 
01235     TRACE_DEBUG("PCtoRDRSetDatarateandClockFrequency\n\r");
01236 
01237     dwClockFrequency = ccidDriver.sCcidCommand.APDU[0]
01238                        + (ccidDriver.sCcidCommand.APDU[1] << 8)
01239                        + (ccidDriver.sCcidCommand.APDU[2] << 16)
01240                        + (ccidDriver.sCcidCommand.APDU[3] << 24);
01241 
01242     dwDataRate = ccidDriver.sCcidCommand.APDU[4]
01243                  + (ccidDriver.sCcidCommand.APDU[5] << 8)
01244                  + (ccidDriver.sCcidCommand.APDU[6] << 16)
01245                  + (ccidDriver.sCcidCommand.APDU[7] << 24);
01246 
01247     ISO7816_SetDataRateandClockFrequency(dwClockFrequency, dwDataRate);
01248 
01249     RDRtoPCDataRateAndClockFrequency(dwClockFrequency, dwDataRate);
01250 
01251 }
01252 
01253 /**
01254  * Report the CMD_NOT_SUPPORTED error to the host
01255  */
01256 static void vCCIDCommandNotSupported(void)
01257 {
01258     /* Command not supported */
01259 
01260     /* vCCIDReportError(CMD_NOT_SUPPORTED); */
01261 
01262 
01263     TRACE_DEBUG("CMD_NOT_SUPPORTED\n\r");
01264 
01265     /* Header fields settings */
01266 
01267     ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
01268     ccidDriver.sCcidMessage.wLength      = 0;
01269     ccidDriver.sCcidMessage.bSpecific    = 0;
01270 
01271     ccidDriver.sCcidMessage.bStatus |= ICC_CS_FAILED;
01272 
01273     /* Send the response to the host */
01274 
01275     /*vCCIDSendResponse(); */
01276 
01277 }
01278 
01279 /**
01280  * Sent CCID response on USB
01281  */
01282 static void vCCIDSendResponse(void)
01283 {
01284     unsigned char bStatus;
01285 
01286     do {
01287         bStatus = USBD_Write(CCID_EPT_DATA_IN, (void *)&ccidDriver.sCcidMessage,
01288                               ccidDriver.sCcidMessage.bSizeToSend, 0, 0);
01289     } while (bStatus != USBD_STATUS_SUCCESS);
01290 }
01291 
01292 
01293 /**
01294  *  Description: CCID Command dispatcher
01295  */
01296 static void CCIDCommandDispatcher(void)
01297 {
01298     unsigned char MessageToSend = 0;
01299 
01300     /*TRACE_DEBUG("Command: 0x%X 0x%x 0x%X 0x%X 0x%X 0x%X 0x%X\n\r\n\r", */
01301 
01302     /*               (unsigned int)ccidDriver.sCcidCommand.bMessageType, */
01303 
01304     /*               (unsigned int)ccidDriver.sCcidCommand.wLength, */
01305 
01306     /*               (unsigned int)ccidDriver.sCcidCommand.bSlot, */
01307 
01308     /*               (unsigned int)ccidDriver.sCcidCommand.bSeq, */
01309 
01310     /*               (unsigned int)ccidDriver.sCcidCommand.bSpecific_0, */
01311 
01312     /*               (unsigned int)ccidDriver.sCcidCommand.bSpecific_1, */
01313 
01314     /*               (unsigned int)ccidDriver.sCcidCommand.bSpecific_2); */
01315 
01316 
01317     /* Check the slot number */
01318 
01319     if (ccidDriver.sCcidCommand.bSlot > 0) {
01320         TRACE_ERROR("BAD_SLOT_NUMBER\n\r");
01321     }
01322 
01323     TRACE_DEBUG("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
01324 
01325     ccidDriver.sCcidMessage.bStatus = 0;
01326 
01327     ccidDriver.sCcidMessage.bSeq  = ccidDriver.sCcidCommand.bSeq;
01328     ccidDriver.sCcidMessage.bSlot = ccidDriver.sCcidCommand.bSlot;
01329 
01330     ccidDriver.sCcidMessage.bSizeToSend = sizeof(S_ccid_bulk_in_header) -
01331                                           (ABDATA_SIZE + 1);
01332 
01333 
01334     /* Command dispatcher */
01335 
01336     switch (ccidDriver.sCcidCommand.bMessageType) {
01337 
01338     case PC_TO_RDR_ICCPOWERON:
01339         PCtoRDRIccPowerOn();
01340         MessageToSend = 1;
01341         break;
01342 
01343     case PC_TO_RDR_ICCPOWEROFF:
01344         PCtoRDRIccPowerOff();
01345         MessageToSend = 1;
01346         break;
01347 
01348     case PC_TO_RDR_GETSLOTSTATUS:
01349         PCtoRDRGetSlotStatus();
01350         MessageToSend = 1;
01351         break;
01352 
01353     case PC_TO_RDR_XFRBLOCK:
01354         PCtoRDRXfrBlock();
01355         MessageToSend = 1;
01356         break;
01357 
01358     case PC_TO_RDR_GETPARAMETERS:
01359         PCtoRDRGetParameters();
01360         MessageToSend = 1;
01361         break;
01362 
01363     case PC_TO_RDR_RESETPARAMETERS:
01364         PCtoRDRResetParameters();
01365         MessageToSend = 1;
01366         break;
01367 
01368     case PC_TO_RDR_SETPARAMETERS:
01369         PCtoRDRSetParameters();
01370         MessageToSend = 1;
01371         break;
01372 
01373     case PC_TO_RDR_ESCAPE:
01374         PCtoRDREscape();
01375         MessageToSend = 1;
01376         break;
01377 
01378     case PC_TO_RDR_ICCCLOCK:
01379         PCtoRDRICCClock();
01380         MessageToSend = 1;
01381         break;
01382 
01383     case PC_TO_RDR_T0APDU:
01384 
01385         /* Only CCIDs reporting a short or extended APDU level in the dwFeatures */
01386 
01387         /* field of the CCID class descriptor may take this command into account. */
01388 
01389         if ((CCID_FEATURES_EXC_SAPDU == (CCID_FEATURES_EXC_SAPDU &
01390                                           configurationDescriptorsFS.ccid.dwFeatures))
01391              || (CCID_FEATURES_EXC_APDU  == (CCID_FEATURES_EXC_APDU &
01392                                              configurationDescriptorsFS.ccid.dwFeatures))) {
01393 
01394             /* command supported */
01395 
01396             PCtoRDRtoAPDU();
01397         } else {
01398             /* command not supported */
01399 
01400             TRACE_DEBUG("PC_TO_RDR_T0APDU\n\r");
01401             vCCIDCommandNotSupported();
01402         }
01403 
01404         MessageToSend = 1;
01405         break;
01406 
01407     case PC_TO_RDR_SECURE:
01408         PCtoRDRSecure();
01409         MessageToSend = 1;
01410         break;
01411 
01412     case PC_TO_RDR_MECHANICAL:
01413         PCtoRDRMechanical();
01414         MessageToSend = 1;
01415         break;
01416 
01417     case PC_TO_RDR_ABORT:
01418         PCtoRDRAbort();
01419         MessageToSend = 1;
01420         break;
01421 
01422     case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
01423         PCtoRDRSetDataRateAndClockFrequency();
01424         MessageToSend = 1;
01425         break;
01426 
01427     default:
01428         TRACE_DEBUG("default: 0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
01429         vCCIDCommandNotSupported();
01430         MessageToSend = 1;
01431         break;
01432 
01433     }
01434 
01435     if (MessageToSend == 1)
01436         vCCIDSendResponse();
01437 }
01438 
01439 
01440 /**
01441  * SETUP request handler for a CCID device
01442  * \param pRequest Pointer to a USBGenericRequest instance
01443  */
01444 static void CCID_RequestHandler(const USBGenericRequest *pRequest)
01445 {
01446     TRACE_DEBUG("CCID_RHl\n\r");
01447 
01448     /* Check if this is a class request */
01449 
01450     if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_CLASS) {
01451 
01452         /* Check if the request is supported */
01453 
01454         switch (USBGenericRequest_GetRequest(pRequest)) {
01455 
01456         case CCIDGenericRequest_ABORT:
01457             TRACE_DEBUG("CCIDGenericRequest_ABORT\n\r");
01458             break;
01459 
01460         case CCIDGenericRequest_GET_CLOCK_FREQUENCIES:
01461             TRACE_DEBUG("Not supported\n\r");
01462             /* A CCID with bNumClockSupported equal to 00h does not have */
01463 
01464             /* to support this request */
01465 
01466             break;
01467 
01468         case CCIDGenericRequest_GET_DATA_RATES:
01469             TRACE_DEBUG("Not supported\n\r");
01470             /* A CCID with bNumDataRatesSupported equal to 00h does not have */
01471 
01472             /* to support this request. */
01473 
01474             break;
01475 
01476         default:
01477             TRACE_WARNING("CCIDDriver_RequestHandler: Unsupported request (%d)\n\r",
01478                            USBGenericRequest_GetRequest(pRequest));
01479             USBD_Stall(0);
01480         }
01481     }
01482 
01483     else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
01484 
01485         /* Forward request to the standard handler */
01486 
01487         USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest);
01488     } else {
01489 
01490         /* Unsupported request type */
01491         TRACE_WARNING("CCIDDriver_RequestHandler: Unsupported request type (%d)\n\r",
01492                        USBGenericRequest_GetType(pRequest));
01493         USBD_Stall(0);
01494     }
01495 }
01496 
01497 
01498 /*------------------------------------------------------------------------------
01499  *      Exported functions
01500  *------------------------------------------------------------------------------*/
01501 
01502 /**
01503  * Optional callback re-implementation
01504  */
01505 #if !defined(NOAUTOCALLBACK)
01506 /* not static function */
01507 
01508 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
01509 {
01510     CCID_RequestHandler(request);
01511 }
01512 #endif
01513 
01514 
01515 /**
01516  * Handles SmartCart request
01517  */
01518 void CCID_SmartCardRequest(void)
01519 {
01520     unsigned char bStatus;
01521 
01522     do {
01523 
01524         bStatus = CCID_Read((void *)&ccidDriver.sCcidCommand,
01525                              sizeof(S_ccid_bulk_out_header),
01526                              (TransferCallback)&CCIDCommandDispatcher,
01527                              (void *)0);
01528     } while (bStatus != USBD_STATUS_SUCCESS);
01529 
01530 }
01531 
01532 /**
01533  * Initializes the CCID device driver.
01534  */
01535 void CCIDDriver_Initialize(void)
01536 {
01537     TRACE_DEBUG("CCID_Init\n\r");
01538     USBDDriver_Initialize(&(ccidDriver.usbdDriver),
01539                           &ccidDriverDescriptors,
01540                           0); /* Multiple interface settings not supported */
01541 
01542     USBD_Init();
01543 }
01544 
01545 /**
01546  * Reads data from the Data OUT endpoint
01547  * \param pBuffer   Buffer to store the received data
01548  * \param dLength   data buffer length
01549  * \param fCallback Optional callback function
01550  * \param pArgument Optional parameter for the callback function
01551  * \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
01552  */
01553 unsigned char CCID_Read(void *pBuffer,
01554                         unsigned int dLength,
01555                         TransferCallback fCallback,
01556                         void *pArgument)
01557 {
01558     return USBD_Read(CCID_EPT_DATA_OUT, pBuffer, dLength, fCallback, pArgument);
01559 }
01560 
01561 /**
01562  * Sends data through the Data IN endpoint
01563  * \param pBuffer   Buffer holding the data to transmit
01564  * \param dLength   Length of data buffer
01565  * \param fCallback Optional callback function
01566  * \param pArgument Optional parameter for the callback function
01567  * \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
01568  */
01569 unsigned char CCID_Write(void *pBuffer,
01570                          unsigned int dLength,
01571                          TransferCallback fCallback,
01572                          void *pArgument)
01573 {
01574     return USBD_Write(CCID_EPT_DATA_IN, pBuffer, dLength, fCallback, pArgument);
01575 }
01576 
01577 /**
01578  * Sends data through the interrupt endpoint, ICC insertion event
01579  * RDR_to_PC_NotifySlotChange
01580  * \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
01581  */
01582 unsigned char CCID_Insertion(void)
01583 {
01584     TRACE_DEBUG("CCID_Insertion\n\r");
01585 
01586     /* Build the Interrupt-IN message */
01587 
01588     ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
01589     ccidDriver.BufferINT[1] = ICC_INSERTED_EVENT;
01590     ccidDriver.SlotStatus   = ICC_INSERTED_EVENT;
01591 
01592     /* Notify the host that a ICC is inserted */
01593 
01594     return USBD_Write(CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0);
01595 }
01596 
01597 /**
01598  * Sends data through the interrupt endpoint, ICC removal event
01599  * RDR_to_PC_NotifySlotChange
01600  * \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
01601  */
01602 unsigned char CCID_Removal(void)
01603 {
01604     TRACE_DEBUG("CCID_Removal\n\r");
01605 
01606     /* Build the Interrupt-IN message */
01607 
01608     ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
01609     ccidDriver.BufferINT[1] = ICC_NOT_PRESENT;
01610     ccidDriver.SlotStatus   = ICC_NOT_PRESENT;
01611 
01612     /* Notify the host that a ICC is inserted */
01613 
01614     return USBD_Write(CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0);
01615 }
01616 
01617 /**
01618  * Interrupt-IN Messages
01619  * This message is sent when any bit in the bHardwareErrorCode field is set.
01620  * If this message is sent when there is no outstanding command, the bSeq
01621  * field will be undefined.
01622  * \param bSlot ICC slot number
01623  * \param bSeq  Sequence number of the bulk OUT command when the hardware error
01624  * occured
01625  * \param bHardwareErrorCode Hardware error code
01626  * \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
01627  */
01628 unsigned char RDRtoPCHardwareError(unsigned char bSlot,
01629                                     unsigned char bSeq,
01630                                     unsigned char bHardwareErrorCode)
01631 {
01632     TRACE_DEBUG("RDRtoPCHardwareError\n\r");
01633 
01634     /* Build the Interrupt-IN message */
01635 
01636     ccidDriver.BufferINT[0] = RDR_TO_PC_HARDWAREERROR;
01637     ccidDriver.BufferINT[1] = bSlot;
01638     ccidDriver.BufferINT[2] = bSeq;
01639     ccidDriver.BufferINT[3] = bHardwareErrorCode;
01640 
01641     /* Notify the host that a ICC is inserted */
01642 
01643     return USBD_Write(CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 4, 0, 0);
01644 }
01645 
01646 
01647 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines