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

/**------------------------------------------------------------------------------
 * \file
 *
 * \section Purpose
 *
 * Definition of methods for using a CCID device driver.
 *
 * \section Usage
 *
 * -# CCIDDriver_Initialize
 * -# CCID_Read
 * -# CCID_Write
 * -# CCID_SmartCardRequest
 * -# CCID_Insertion
 * -# CCID_Removal
 * -# RDRtoPCHardwareError
 */

#ifndef CCID_DRIVER_H
#define CCID_DRIVER_H

/** \addtogroup usbd_ccid
 *@{
 */
/** 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                                                                

 *------------------------------------------------------------------------------*/

/**
 * \typedef S_ccid_bulk_in_header
 * \brief Bulk CCID Message header structure 
 */
typedef struct _S_ccid_bulk_in_header
{
   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;

/**
 * \typedef S_ccid_bulk_out_header
 * \brief  6.1 Bulk Transfers 
 */
typedef struct _S_ccid_bulk_out_header
{
   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;


/**
 * \typedef S_ccid_PIN_Verification
 * \brief 6.1.11.2 PIN Verification Data Structure 
 */
typedef struct _S_ccid_PIN_Verification
{
    /** 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;


/**
 * \typedef S_ccid_PIN_Modification
 * \brief 6.1.11.7 PIN Modification Data Structure 
 */
typedef struct _S_ccid_PIN_Modification
{
    /** 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;

/** 
 * \typedef S_ccid_protocol_t0 
 * \brief Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h) 
 */
typedef struct _S_ccid_protocol_t0
{
    /** 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;


/** 
 * \typedef S_ccid_protocol_t1
 * \brief Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h) 
 */
typedef struct _S_ccid_protocol_t1
{
    /** 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;


/** 
 * \typedef CCIDDescriptor
 * \brief Identifies the length of type of subordinate descriptors of a CCID device 
 * Table 5.1-1 Smart Card Device Class descriptors 
 */
typedef struct _CCIDDescriptor
{
   /** 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 */


