SAMV71 Xplained Ultra Software Package 1.3

cciddriver.c

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