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