AN1527 APPLICATION NOTE DEVELOPING A USB SMARTCARD READER WITH ST7SCR by Microcontroller Division Applications INTRODUCTION This document describes a firmware implementation developed by STMicroelectronics for a USB Smart Card Reader. This firmware is for the ST7SCR microcontroller and can be used with the associated Smart Card Reader board available from STMicroelectronics. It is divided into 4 parts: – Universal Serial Bus (USB) management: This is the USB library which manages the USB hardware. – Chip Card Interface Device (CCID) implementation: This contains high level functions for using the USB in compliance with CCID specifications (messages for Bulk-in, Bulk-out, interrupt and class requests) – Interface Device (IFD) implementation: This contains high level functions for ISO 7816 specification implementation and the smartcard-specific command interpreter. – 7816 UART Smartcard Interface (CRD) management: This contains low level functions for the hardware management of the 7816 UART Smartcard Interface (CRD). The main loop polls USB transactions (functions in Ccid_usb.c) using a state machine process: – USB_Polling() function from library for USB low level and endpoint 0 management. – Receive USB Bulk-out message (CCID part). – Execute the function corresponding to the Bulk-out message (IFD part). – Send USB interrupt in message (CCID part) if necessary. – Send USB Bulk-in response (CCID part). The Bulk-out/in messages are managed by a state machine. When the Bulk-out message reception is completed, the message function is executed and returns only after the completion of the action to be done in the IFD part. As this may take several 10 ms (e.g. ATR reading), the response is sent to the host by Bulk-in message. The Bulk-in/out messages are received in several transactions with a single transaction at every main loop if the USB endpoint is available. If there are any interrupt messages, they are sent just before the Bulk-in message is sent. Specific CCID class requests are managed by the setup management function in the USB library (USER_USB_setup() function). AN1527/0702 1/14 1 DEVELOPING A USB SMARTCARD READER WITH ST7SCR 1 CCID IMPLEMENTATION 1.1 GENERALITIES The Chip Card Interface Device (CCID) firmware implementation conforms to the “Universal Serial Bus Device Class Specification for USB Chip/Smart Card Interface Devices” revision 1.0. It contains two files: – Ccid_usb.c: This file contains the USB - CCID interface functions used to manage the state machine that generates Bulk-in/Bulk-out messages. – Ifd_ccid.c: This file contains the PC_to_RDR_xxx() and RDR_to_PC_xxx() message functions for the CCID. The following commands are not supported but can be added easily: – PC_To_RDR_Secure, – PC_To_RDR_SetDataRateAndClockFrequency, – PC_To_RDR_ToAPDU, – PC_To_RDR_Mechanical. This CCID part uses a 271-byte buffer for all messages. Messages are composed of two parts: – header (10 bytes: fixed size) – data (up to 261 bytes). The size is based on the largest message managed at the short APDU transaction level. Due to this large size, the ST7SCR can have only 1 buffer and cannot store more than one message at a given time. The CCID_BulkOutMessage() function uses several Bulk-out USB transactions to verify the message header and store the entire message in the buffer. When the message reception is completed, the CCID_DispatchMessage() function identifies the message type and calls the corresponding function (PC_to_RDR_xxx()) for processing. Then, the IFD part of the firmware executes a command on the ICC if necessary. This command is included in the data field of the buffer. The PC_to_RDR_xxx() function receives from the IFD the answer to the message in the buffer data field and returns an error code to be included in the Bulk-in response. The RDR_to_PC_xxx() function, which corresponds to the PC_to_RDR_xxx() previously executed, is launched and enters the correct values for error and status codes in the header. At this time, the Bulk-in message is ready to be sent. But before the sending, the CCID_IntMessage() function is executed to detect any hardware problems or if a slot change has occurred. In this case, the corresponding interrupt message is sent to the host. 2/14 2 DEVELOPING A USB SMARTCARD READER WITH ST7SCR To finish the main loop, the CCID_BulkInMessage() function sends the Bulk-in message as an answer to the previous Bulk-out message. The message is sent in a process that requires several Bulk-in transactions (same concept as for the Bulk-out process). In addition, the Abort request is implemented through the CCIDClassRequestAbort() function called in the USB_Polling() function. For this purpose, the USB_Polling() function is called in the PC_to_RDR_xxx() function. When this request is received from endpoint 0, a flag is set and the command sequence number is memorized. All commands are aborted until the next PC_to_RDR_Abort command with the correct sequence number is received. 1.2 FUNCTION DESCRIPTION ■ void CCID_Init(void) This function initializes the flags and status variables for the state machine process. ■ void CCID_Init_IT(void) This function initializes the state machine and switches off the VccCard after a USB reset done by the PC Host. It can only be called by an interrupt routine. ■ void CCID_Suspend_IT(void) This function initializes the state machine and the card interface hardware after a resume from USB suspend mode. ■ void CCID_BulkOutMessage(void) This function manages the state machine during USB Bulk Out message reception. It fills the message buffer with a maximum of 271 bytes. ■ void CCID_BulkInMessage(void) This function manages the state machine during the USB Bulk In message transmission. It sends the buffer content as a message with a maximum of 271 bytes. ■ void CCID_DispatchMessage(void) This function identifies the USB Bulk Out received message and calls the corresponding functions to process it : PC_to_RDR_xxx() and RDR_to_PC_xxx(). ■ void CCID_IntMessage(void) This function verifies the slot status and sends an interrupt In message if needed. 3/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ void CcidClassRequestAbort(void) This function is called from the USER_USB_Setup() function to process an Abort request. ■ unsigned char PC_to_RDR_IccPowerOn(void) This function verifies the PC_TO_RDR_ICCPOWERON command format and calls the IFD_IccPowerOn() function (from Interface Device level). If IFD_IccPowerOn() returns no error, the message header is filled with the ATR length. This PC_to_RDR function returns an error code. ■ unsigned char PC_to_RDR_IccPowerOff(void) This function verifies the PC_TO_RDR_ICCPOWEROFF command format, switches off the smartcard power supply and returns the NOERROR code. ■ unsigned char PC_to_RDR_GetSlotStatus(void) This function verifies the PC_TO_RDR_GETSLOTSTATUS command format, verifies the slot hardware state and returns the corresponding error code. ■ unsigned char PC_to_RDR_XfrBlock(void) This function verifies the PC_TO_RDR_XFRBLOCK command format, checks the slot status and returns an error if needed. If there is no error, it calls the IFD_XfrBlock() function (from the Interface Device level). The message buffer contains the data to be transferred and is updated by this IFD function. This PC_to_RDR function returns an error code. ■ unsigned char PC_to_RDR_GetParameters(void) This function verifies the PC_TO_RDR_GETPARAMETERS command format, checks the slot hardware state and returns the corresponding error code. ■ unsigned char PC_to_RDR_ResetParameters(void) This function verifies the PC_TO_RDR_RESETPARAMETERS command format, fills the m essage buffer w ith the default v alues of the r eader par am eters and c alls the IFD_SetParameters() function (from the Interface Device level). This PC_to_RDR function returns an error code. ■ unsigned char PC_to_RDR_SetParameters(void) This function verifies the PC_TO_RDR_SETPARAMETERS command format and calls the IFD_SetParameters() function (from the Interface Device level). This PC_to_RDR function returns an error code. 4/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ unsigned char PC_to_RDR_Escape(void) This function verifies the PC_T O_RD R_ESCAPE com mand format and calls the IFD_Escape() function (from the Interface Device level). This PC_to_RDR function returns an error code (from IFD_Escape(), for example). ■ unsigned char PC_to_RDR_IccClock(void) This function verifies the PC_TO_RDR_ICCCLOCK command format and calls the IFD_SetClock() function (from the Interface Device level). This PC_to_RDR function returns an error code (from IFD_SetClock(), for example). ■ unsigned char PC_to_RDR_Abort(void) This function verifies the PC_TO_RDR_ABORT command format, checks the abort conditions and sets the corresponding flag. It returns the corresponding error code. ■ void RDR_to_PC_DataBlock(unsigned char ErrorCode) This function fills the whole command buffer header including the error code given as input to prepare the RDR_TO_PC_DATABLOCK message. ■ void RDR_to_PC_SlotStatus(unsigned char ErrorCode) This function fills the whole command buffer header including the error code given as input to prepare the RDR_TO_PC_SLOTSTATUS message. ■ void RDR_to_PC_Parameters(unsigned char ErrorCode) This function fills the whole command buffer header including the error code given as input to prepare the RDR_TO_PC_PARAMETERS message and call the IFD_GetParameters() function to fill the message data field. ■ void RDR_to_PC_Escape(unsigned char ErrorCode) This function fills the whole command buffer header including the error code given as input to prepare the RDR_TO_PC_ESCAPE message. 5/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR 2 IFD IMPLEMENTATION The Interface Device (IFD) implementation firmware contains one file: – Ifd_protocol.c: This is the ISO 7816 implementation for Protocol types T=0 and T=1 and for character, TPDU and short APDU levels. The protocol type is also managed at the CRD level by the interrupt system for data reception from the ICC. For this release, only the T=0 with character level has been implemented in the current firmware. This part has to be modified in depth to integrate the secure function and other communication types and levels. All the functions in this part are called by a CCID function. These functions are typically those where the reader interprets the messages sent to/from the ICC and manages the parameters for ICC communication (speed, type, etc....). An IFD structure is used to save all the current parameters in compliance with CCID specifications. The following functions are used for ICC and parameter management: – IFD_Init(): This sets the parameter structure to the default value. – IFD_GetParameters(): This returns the current parameters in a buffer. – IFD_SetParameters(): This enters the new parameters in the IFD structure and programs the CRD for use with the new configuration. – IFD_ApplyParametersStructure(): This programs the CRD to use the configuration described by the IFD structure. – IFD_UpdateConvParameterStructure(): This changes the convention parameter of the structure with the value programmed in the CRD. – IFD_IccPowerOn(): This switches ON the VCC Card with automatic voltage selection and returns the Answer to Reset (ATR) variable. – IFD_XfrBlock(): This sends a command and receives the answer with current parameters. – IFD_XfrCharT0(): This is given by the IFD structure. (Character level and T=0 type). – IFD_Escape(): This is dedicated to specific communication between reader and PC. (see CCID spec). – IFD_SetClock(): This changes the clock state as configured in the IFD structure. 6/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR 3 ISO 7816 UART LIBRARY (CRD) 3.1 GENERAL INTRODUCTION The aim of this library is to provide the user with a set of functions for using the Smartcard Interface (ISO7816-3 UART Interface) to directly access the hardware and to communicate with an Integrated Circuit Card (ICC) through a few simple functions. This library is composed of 4 files: – crd.c – crd.h – int_crd.c – int_crd.h The crd.x files provide the general functions for the main loop program. The int_crd.x files are used for interrupt management. The transactions between the ST7 microcontroller and the ICC are performed by the ICC_xxx functions. These functions poll flags waiting for the end of the transaction. The transaction itself and the flag settings are managed by interrupts. 3.2 SMARTCARD INTERFACE FUNCTIONS The Smartcard Interface (CRD) functions described below are very low level functions used to interact directly with the hardware. ■ void CRD_Init(void) This function resets and initialize the CRD and the local software flags. ■ unsigned char CRD_GetHwError(unsigned char * pHwErrorCode) This function checks the hardware state and returns one of the following error codes: – Slot_No_Error – SlotError_HW_Error – SlotError_ICC_Mute (no card present) If the function returns SlotError_HW_Error, pHwErrorCode will contain one of the following error codes: – HardwareErrorCode_OverCurrent – HardwareErrorCode_VoltageError – HardwareErrorCode_OverCurrent_IT – HardwareErrorCode_VoltageError_IT Note: In case of a hardware error, the slot is inactivated (VCC Card off). 7/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ unsigned char CRD_VccOn(unsigned char Voltage) This function switches ON the VCC Card with value given by the Voltage variable. There are three possible voltage values: – CRD_Voltage18V (for 1.8 volts) – CRD_Voltage3V (for 3.0 volts) – CRD_Voltage5V (for 5.0 volts) This function returns one of the following error codes: – Slot_No_Error – SlotError_HW_Error – SlotError_ICC_Mute (no card present) ■ void CRD_VccOff(void) This function switches OFF the VCC Card. The inactivating sequence is managed by hardware. ■ void CRD_SetMode(unsigned char Mode) This function sets the operating mode of the CRD. There are two operating modes: – CRD_ManualMode – CRD_UARTMode ■ void CRD_SetConvention(unsigned char Convention) This function sets the convention used by the CRD to communicate with the ICC. There are two conventions: – CRD_DirectConv – CRD_InverseConv ■ unsigned char CRD_GetSlotStatus(void) This function returns the current status of the slot (only 1 slot is possible with this device). There are three possible states for the slot: – CRD_NotPresent – CRD_PresentInactive – CRD_PresentActive 8/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ unsigned char CRD_GetConvention(void) This function returns the convention currently in use in the CRD. There are two conventions: – CRD_DirectConv – CRD_InverseConv ■ unsigned char CRD_GetClockStatus(void) This function returns the status of the CRD clock signal. There are three possible states for the clock signal: – CRD_ClockRunning – CRD_ClockStoppedLow – CRD_ClockStoppedHigh ■ unsigned char CRD_SetClock(unsigned char ClockState) This function modifies the state of the CRD clock signal. ClockState can be one of the following ones: – CRD_ClockRunning – CRD_ClockStoppedLow – CRD_ClockStoppedHigh – CRD_ClockStoppedLowOrHigh This function returns one of the following error codes: – Slot_No_Error – SlotError_ICC_Mute ■ unsigned char CRD_SetEtu(unsigned int Etu, unsigned char Comp) This function sets the Elementary Time Unit registers to the value of the Etu variable. The value of this variable must be a positive integer between 12 and 2048. If the Etu value is 2048, the hardware registers are cleared and the CRD behaves as if it was set to 2048. The Comp value can be 0 or 1. It is written to the COMP bit of register CRDETU1. For more information, please refer to the ST7SCR datasheet. This function will return 0 if the CRDETU registers are correct and 0xFF if the input values are incorrect. ■ void CRD_SetGuardTime(unsigned int GuardTime) void CRD_SetWaitingTime(unsigned long WaitingTime) These functions enter positive integer values in the hardware timer registers. 9/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ void CRD_StartWaitingTime(void) This function starts the Waiting Timer. The bWaitingTimeFlag software flag is set by an interrupt when the count is finished. For more information, please refer to the crd.h file. This counter is used by the ICC level functions to determine the end of the transmission. ■ void CRD_StopWaitingTime(void) This function stops the Waiting Timer and resets the corresponding flag. ■ void CRD_WaitingTime(unsigned long WaitingTimeInEtu) This function creates a wait loop for WaitingTimeInEtu. The waiting time is: – WaitingTimeInEtu * Etu This function is used to set the VCC card stabilization delay or delays during the reset procedure. The Etu value is set by the CRD_SetEtu function. ■ void CRD_InitReceive(unsigned int ReceiveBufSize, unsigned char * pBuffer) This function will configure the CRD for reception and begin the process. – pBuffer is the address of the buffer where the data will be copied. – ReceiveBufSize is the size of the buffer. If the ICC transmits more bytes than the number specified in the ReceiveBufSize variable, data saving is stopped and a flag is set. This reception is done entirely by interrupt processing. ■ unsigned int CRD_NumberOfBytesReceived(void) This function returns the number of bytes already received during the reception process. ■ unsigned int CRD_EndReceive(void) This function stops the reception process and returns the number of bytes received and copied in the buffer. ■ void CRD_InitTransmit(unsigned int TransmitBufSize, unsigned char * pBuffer) This function configures the CRD for transmission and begins the process. – pBuffer is the address of the buffer containing the data to be transmitted. – TransmitBufSize is the number of bytes to be transmitted. This transmission is entirely done by interrupt processing. ■ unsigned int CRD_NumberOfBytesToTransmit(void) This function returns the remaining number of bytes to be transmitted. 10/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR ■ unsigned int CRD_EndTransmit(void) This function finishes the transmission by disabling the interrupt. This function returns the remaining number of bytes to be transmitted. 3.3 INTERRUPT FUNCTIONS The following two functions are executed when an interrupt occurs: ■ void INT_UART(void) This function is used for all CRD interrupts: parity, receive, transmit, waitingtime, voltage_error, over_current and transmit_empty. – PARITY: A flag is set if 4 automatic retries have failed. – WAITINGTIME: A flag is set when a counter overflow is detected. – VOLTAGE and CURRENT: The corresponding flags are set, the corresponding interrupt is invalidated and the VCC Card is switched OFF. – TRANSMIT: The transmit register is loaded with the next byte to be sent. If the last byte is sent, the interrupt is disabled and a flag is set. – RECEIVE: This function uses a Protocol Type Flag (software) to identify the received bytes and manage the T=0 and the T=1 special cases. – TRANSMITEMPTY: Not used. ■ void INT_CARDDET(void) This function will set a flag with Rebound Management (see the Time Base Unit (TBU) function). 3.4 ICC FUNCTIONS The following functions execute a global action on the ICC. ■ unsigned char ICC_PowerOnAsync(unsigned char Voltage) This function executes the Power-on sequence in compliance with ISO 7816 specifications for asynchronous ICCs, including the generation of the rising edge for the reset signal. The VCC Card voltage is either 1.8 volts, 3.0 volts or 5.0 volts depending on the value of the Voltage variable: – CRD_Voltage18V (for 1.8 volts) – CRD_Voltage3V (for 3.0 volts) – CRD_Voltage5V (for 5.0 volts) This function returns one of the following error codes: 11/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR – Slot_No_Error – SlotError_HW_Error – SlotError_ICC_Mute Note: At the end of this function, the CRD is in Manual mode. ■ void ICC_ResetAsync(void) This function executes a warm reset sequence in compliance with ISO 7816 specifications for asynchronous ICCs. Note: At the end of this function, the CRD is in Manual mode. ■ unsigned char ICC_GetAtrAsync(unsigned char Voltage, unsigned char * pReceiveBuffer, unsigned int * pAtrSize) This function executes the Power-on or Reset sequence and answer to reset reading for an asynchronous ICC. The “voltage” variable can be: – CRD_Voltage18V (for 1.8 volts) – CRD_Voltage3V (for 3.0 volts) – CRD_Voltage5V (for 5.0 volts) Note: The “voltage” variable is used only if the slot status is inactive at the beginning of the function. In this case, the cold Answer to Reset (ATR) is returned. If the ICC is already active, a simple reset is generated and a warm ATR is returned. – pReceiveBuffer is the address of the buffer to fill with the ATR. – pAtrSize is the address of the data containing: – Input: the size of the ReceiveBuffer in bytes. – Output: the length of the ATR written in the ReceiveBuffer in bytes. This function returns one of the following error codes: – Slot_No_Error – SlotError_HW_Error – SlotError_ICC_Mute – SlotError_BAD_ATR_TS – SlotError_XFR_Overrun ■ unsigned char ICC_SendCommandAsync(unsigned char * pTransmitBuffer, unsigned int CommandSize, unsigned char ProtocolType) This function sends a packet of bytes to the ICC with the Guard Time currently in use. – pTransmitBuffer is the address of the buffer containing the data to be sent. 12/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR – CommandSize is the size of the buffer in bytes. – ProtocolType is 0 (for T=0) or 1 (for T=1). This variable is used to set a flag tested in the interrupt process at transmission and reception levels. This function will return one of the following error codes: – Slot_No_Error – SlotError_ICC_Mute (if transfer not completed) ■ unsigned char ICC_ReceiveAnswerAsync(unsigned char * pReceiveBuffer, unsigned int * pAnswerSize) This function will receive a packet of bytes from the ICC with its waiting time already programmed. – pReceiveBuffer is the address of the buffer to fill with the received data. – pAnswerSize is the address of the data containing: – Input: the size of the ReceiveBuffer in bytes. – Output: the length in bytes of the received data written in the ReceiveBuffer. This function will return one of the following error codes: – Slot_No_Error – SlotError_XFR_Overrun – SlotError_ICC_Mute 13/14 DEVELOPING A USB SMARTCARD READER WITH ST7SCR “THE PRESENT NOTE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH A NOTE AND/OR THE USE MADE BY CUSTOMERS OF THE INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.” Information furnished is believed to be accurate and reliable. However, STMicroelectronics assumes no responsibility for the consequences of use of such information nor for any infringement of patents or other rights of third parties which may result from its use. No license is granted by implication or otherwise under any patent or patent rights of STMicroelectronics. Specifications mentioned in this publication are subject to change without notice. This publication supersedes and replaces all information previously supplied. STMicroelectronics products are not authorized for use as critical components in life support devices or systems without the express written approval of STMicroelectronics. The ST logo is a registered trademark of STMicroelectronics 2002 STMicroelectronics - All Rights Reserved. Purchase of I2C Components by STMicroelectronics conveys a license under the Philips I2C Patent. Rights to use these components in an I2C system is granted provided that the system conforms to the I2C Standard Specification as defined by Philips. STMicroelectronics Group of Companies Australia - Brazil - Canada - China - Finland - France - Germany - Hong Kong - India - Israel - Italy - Japan Malaysia - Malta - Morocco - Singapore - Spain - Sweden - Switzerland - United Kingdom - U.S.A. http://www.st.com 14/14