/* ----------------------------------------------------------------------------
 *         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

