Release v2.9.0

This commit is contained in:
slimih
2021-09-09 10:10:00 +01:00
parent 5af065de85
commit 06808a92fe
80 changed files with 10318 additions and 2098 deletions

343
Class/CCID/Inc/usbd_ccid.h Normal file
View File

@@ -0,0 +1,343 @@
/**
******************************************************************************
* @file usbd_ccid.h
* @author MCD Application Team
* @brief header file for the usbd_ccid.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_H
#define __USBD_CCID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup usbd_cdc
* @brief This file is the Header file for usbd_ccid.c
* @{
*/
/** @defgroup usbd_cdc_Exported_Defines
* @{
*/
#ifndef CCID_IN_EP
#define CCID_IN_EP 0x81U /* EP1 for data IN */
#endif /* CCID_IN_EP */
#ifndef CCID_OUT_EP
#define CCID_OUT_EP 0x01U /* EP1 for data OUT */
#endif /* CCID_OUT_EP */
#ifndef CCID_CMD_EP
#define CCID_CMD_EP 0x82U /* EP2 for CCID commands */
#endif /* CCID_CMD_EP */
#ifndef CCID_CMD_HS_BINTERVAL
#define CCID_CMD_HS_BINTERVAL 0x10U
#endif /* CCID_CMD_HS_BINTERVAL */
#ifndef CCID_CMD_FS_BINTERVAL
#define CCID_CMD_FS_BINTERVAL 0x10U
#endif /* CCID_CMD_FS_BINTERVAL */
#define CCID_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */
#define CCID_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */
#define CCID_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */
#define USB_CCID_CONFIG_DESC_SIZ 93U
#define CCID_DATA_HS_IN_PACKET_SIZE CCID_DATA_HS_MAX_PACKET_SIZE
#define CCID_DATA_HS_OUT_PACKET_SIZE CCID_DATA_HS_MAX_PACKET_SIZE
#define CCID_DATA_FS_IN_PACKET_SIZE CCID_DATA_FS_MAX_PACKET_SIZE
#define CCID_DATA_FS_OUT_PACKET_SIZE CCID_DATA_FS_MAX_PACKET_SIZE
/*---------------------------------------------------------------------*/
/* CCID definitions */
/*---------------------------------------------------------------------*/
#define CCID_SEND_ENCAPSULATED_COMMAND 0x00U
#define CCID_GET_ENCAPSULATED_RESPONSE 0x01U
#define CCID_SET_COMM_FEATURE 0x02U
#define CCID_GET_COMM_FEATURE 0x03U
#define CCID_CLEAR_COMM_FEATURE 0x04U
#define CCID_SET_LINE_CODING 0x20U
#define CCID_GET_LINE_CODING 0x21U
#define CCID_SET_CONTROL_LINE_STATE 0x22U
#define CCID_SEND_BREAK 0x23U
/*---------------------------------------------------------------------*/
#define REQUEST_ABORT 0x01U
#define REQUEST_GET_CLOCK_FREQUENCIES 0x02U
#define REQUEST_GET_DATA_RATES 0x03U
/*---------------------------------------------------------------------*/
/* The Smart Card Device Class Descriptor definitions */
/*---------------------------------------------------------------------*/
#define CCID_INTERFACE_DESC_SIZE 0x09U
#define USB_DEVICE_CLASS_CCID 0x0BU
#define CCID_CLASS_DESC_SIZE 0x36U
#define CCID_DESC_TYPE 0x21U
#ifndef CCID_VOLTAGE_SUPP
#define CCID_VOLTAGE_SUPP 0x07U
#endif
#ifndef USBD_CCID_PROTOCOL
#define USBD_CCID_PROTOCOL 0x03U
#endif
#ifndef USBD_CCID_DEFAULT_CLOCK_FREQ
#define USBD_CCID_DEFAULT_CLOCK_FREQ 3600U
#endif
#ifndef USBD_CCID_MAX_CLOCK_FREQ
#define USBD_CCID_MAX_CLOCK_FREQ USBD_CCID_DEFAULT_CLOCK_FREQ
#endif
#ifndef USBD_CCID_DEFAULT_DATA_RATE
#define USBD_CCID_DEFAULT_DATA_RATE 9677U
#endif
#ifndef USBD_CCID_MAX_DATA_RATE
#define USBD_CCID_MAX_DATA_RATE USBD_CCID_DEFAULT_DATA_RATE
#endif
#ifndef USBD_CCID_MAX_INF_FIELD_SIZE
#define USBD_CCID_MAX_INF_FIELD_SIZE 254U
#endif
#ifndef CCID_MAX_BLOCK_SIZE_HEADER
#define CCID_MAX_BLOCK_SIZE_HEADER 271U
#endif
#define TPDU_EXCHANGE 0x01U
#define SHORT_APDU_EXCHANGE 0x02U
#define EXTENDED_APDU_EXCHANGE 0x04U
#define CHARACTER_EXCHANGE 0x00U
#ifndef EXCHANGE_LEVEL_FEATURE
#define EXCHANGE_LEVEL_FEATURE TPDU_EXCHANGE
#endif
#define CCID_ENDPOINT_DESC_SIZE 0x07U
#ifndef CCID_EP0_BUFF_SIZ
#define CCID_EP0_BUFF_SIZ 64U
#endif
#ifndef CCID_BULK_EPIN_SIZE
#define CCID_BULK_EPIN_SIZE 64U
#endif
#define CCID_INT_BUFF_SIZ 2U
/*---------------------------------------------------------------------*/
/* CCID Bulk Out Command definitions */
#define PC_TO_RDR_ICCPOWERON 0x62U
#define PC_TO_RDR_ICCPOWEROFF 0x63U
#define PC_TO_RDR_GETSLOTSTATUS 0x65U
#define PC_TO_RDR_XFRBLOCK 0x6FU
#define PC_TO_RDR_GETPARAMETERS 0x6CU
#define PC_TO_RDR_RESETPARAMETERS 0x6DU
#define PC_TO_RDR_SETPARAMETERS 0x61U
#define PC_TO_RDR_ESCAPE 0x6BU
#define PC_TO_RDR_ICCCLOCK 0x6EU
#define PC_TO_RDR_T0APDU 0x6AU
#define PC_TO_RDR_SECURE 0x69U
#define PC_TO_RDR_MECHANICAL 0x71U
#define PC_TO_RDR_ABORT 0x72U
#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73U
/* CCID Bulk In Command definitions */
#define RDR_TO_PC_DATABLOCK 0x80U
#define RDR_TO_PC_SLOTSTATUS 0x81U
#define RDR_TO_PC_PARAMETERS 0x82U
#define RDR_TO_PC_ESCAPE 0x83U
#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84U
/* CCID Interrupt In Command definitions */
#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50U
#define RDR_TO_PC_HARDWAREERROR 0x51U
/* Bulk-only Command Block Wrapper */
#define ABDATA_SIZE 261U
#define CCID_CMD_HEADER_SIZE 10U
#define CCID_RESPONSE_HEADER_SIZE 10U
/* Number of SLOTS. For single card, this value is 1 */
#define CCID_NUMBER_OF_SLOTS 1U
#define CARD_SLOT_FITTED 1U
#define CARD_SLOT_REMOVED 0U
#define OFFSET_INT_BMESSAGETYPE 0x00U
#define OFFSET_INT_BMSLOTICCSTATE 0x01U
#define SLOT_ICC_PRESENT 0x01U
/* LSb : (0b = no ICC present, 1b = ICC present) */
#define SLOT_ICC_CHANGE 0x02U
/* MSb : (0b = no change, 1b = change) */
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
/**
* @}
*/
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} USBD_CCID_LineCodingTypeDef;
#pragma pack(1)
typedef struct
{
uint8_t bMessageType; /* Offset = 0*/
uint32_t dwLength; /* Offset = 1, The length field (dwLength) is the length
of the message not including the 10-byte header.*/
uint8_t bSlot; /* Offset = 5*/
uint8_t bSeq; /* Offset = 6*/
uint8_t bSpecific_0; /* Offset = 7*/
uint8_t bSpecific_1; /* Offset = 8*/
uint8_t bSpecific_2; /* Offset = 9*/
uint8_t abData [ABDATA_SIZE]; /* Offset = 10, 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.*/
} USBD_CCID_BulkOut_DataTypeDef;
#pragma pack()
#pragma pack(1)
typedef struct
{
uint8_t bMessageType; /* Offset = 0 */
uint32_t dwLength; /* Offset = 1 */
uint8_t bSlot; /* Offset = 5, Same as Bulk-OUT message */
uint8_t bSeq; /* Offset = 6, Same as Bulk-OUT message */
uint8_t bStatus; /* Offset = 7, Slot status as defined in section 6.2.6 */
uint8_t bError; /* Offset = 8, Slot error as defined in section 6.2.6 */
uint8_t bSpecific; /* Offset = 9 */
uint8_t abData[ABDATA_SIZE]; /* Offset = 10 */
uint16_t u16SizeToSend;
} USBD_CCID_BulkIn_DataTypeDef;
#pragma pack()
typedef struct
{
__IO uint8_t SlotStatus;
__IO uint8_t SlotStatusChange;
} USBD_CCID_SlotStatusTypeDef;
typedef struct
{
__IO uint8_t bAbortRequestFlag;
__IO uint8_t bSeq;
__IO uint8_t bSlot;
} USBD_CCID_ParamTypeDef;
typedef struct
{
uint8_t data[CCID_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32-bit alignment */
uint32_t UsbMessageLength;
uint8_t UsbIntData[CCID_CMD_PACKET_SIZE]; /* Buffer for the Interrupt In Data */
uint32_t alt_setting;
USBD_CCID_BulkIn_DataTypeDef UsbBlkInData; /* Buffer for the Out Data */
USBD_CCID_BulkOut_DataTypeDef UsbBlkOutData; /* Buffer for the In Data */
USBD_CCID_SlotStatusTypeDef SlotStatus;
USBD_CCID_ParamTypeDef USBD_CCID_Param;
__IO uint32_t MaxPcktLen;
__IO uint8_t blkt_state; /* Bulk transfer state */
uint16_t slot_nb;
uint16_t seq_nb;
} USBD_CCID_HandleTypeDef;
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_CCID;
#define USBD_CCID_CLASS &USBD_CCID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
typedef struct _USBD_CCID_Itf
{
uint8_t (* Init)(USBD_HandleTypeDef *pdev);
uint8_t (* DeInit)(USBD_HandleTypeDef *pdev);
uint8_t (* Control)(uint8_t req, uint8_t *pbuf, uint16_t *length);
uint8_t (* Response_SendData)(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len);
uint8_t (* Send_Process)(uint8_t *Command, uint8_t *Data);
uint8_t (* SetSlotStatus)(USBD_HandleTypeDef *pdev);
} USBD_CCID_ItfTypeDef;
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_CCID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CCID_ItfTypeDef *fops);
uint8_t USBD_CCID_IntMessage(USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_H */
/**
* @}
*/
/**
* @}
*/

View File

@@ -0,0 +1,219 @@
/**
******************************************************************************
* @file usbd_ccid_cmd.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_cmd.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_CMD_H
#define __USBD_CCID_CMD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#ifndef __USBD_CCID_IF_H
#include "usbd_ccid_if_template.h"
#endif
#ifndef __USBD_CCID_SC_IF_H
#include "usbd_ccid_sc_if_template.h"
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/******************************************************************************/
/* ERROR CODES for USB Bulk In Messages : bError */
/******************************************************************************/
#define SLOT_NO_ERROR 0x81U
#define SLOTERROR_UNKNOWN 0x82U
/*----------------------------------------------------------------------------*/
/* Index of not supported / incorrect message parameter : 7Fh to 01h */
/* These Values are used for Return Types between Firmware Layers */
/*
Failure of a command
The CCID cannot parse one parameter or the ICC is not supporting one parameter.
Then the Slot Error register contains the index of the first bad parameter as a
positive number (1-127). For instance, if the CCID receives an ICC command to
an unimplemented slot, then the Slot Error register shall be set to 5 (index of bSlot field) */
/* Following Parameters used in PC_to_RDR_XfrBlock */
#define SLOTERROR_BAD_LENTGH 0x01U
#define SLOTERROR_BAD_SLOT 0x05U
#define SLOTERROR_BAD_POWERSELECT 0x07U
#define SLOTERROR_BAD_PROTOCOLNUM 0x07U
#define SLOTERROR_BAD_CLOCKCOMMAND 0x07U
#define SLOTERROR_BAD_ABRFU_3B 0x07U
#define SLOTERROR_BAD_BMCHANGES 0x07U
#define SLOTERROR_BAD_BFUNCTION_MECHANICAL 0x07U
#define SLOTERROR_BAD_ABRFU_2B 0x08U
#define SLOTERROR_BAD_LEVELPARAMETER 0x08U
#define SLOTERROR_BAD_FIDI 0x0AU
#define SLOTERROR_BAD_T01CONVCHECKSUM 0x0BU
#define SLOTERROR_BAD_GUARDTIME 0x0CU
#define SLOTERROR_BAD_WAITINGINTEGER 0x0DU
#define SLOTERROR_BAD_CLOCKSTOP 0x0EU
#define SLOTERROR_BAD_IFSC 0x0FU
#define SLOTERROR_BAD_NAD 0x10U
#define SLOTERROR_BAD_DWLENGTH 0x08U
/*---------- Table 6.2-2 Slot error register when bmCommandStatus = 1 */
#define SLOTERROR_CMD_ABORTED 0xFFU
#define SLOTERROR_ICC_MUTE 0xFEU
#define SLOTERROR_XFR_PARITY_ERROR 0xFDU
#define SLOTERROR_XFR_OVERRUN 0xFCU
#define SLOTERROR_HW_ERROR 0xFBU
#define SLOTERROR_BAD_ATR_TS 0xF8U
#define SLOTERROR_BAD_ATR_TCK 0xF7U
#define SLOTERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xF6U
#define SLOTERROR_ICC_CLASS_NOT_SUPPORTED 0xF5U
#define SLOTERROR_PROCEDURE_BYTE_CONFLICT 0xF4U
#define SLOTERROR_DEACTIVATED_PROTOCOL 0xF3U
#define SLOTERROR_BUSY_WITH_AUTO_SEQUENCE 0xF2U
#define SLOTERROR_PIN_TIMEOUT 0xF0U
#define SLOTERROR_PIN_CANCELLED 0xEFU
#define SLOTERROR_CMD_SLOT_BUSY 0xE0U
#define SLOTERROR_CMD_NOT_SUPPORTED 0x00U
/* Following Parameters used in PC_to_RDR_ResetParameters */
/* DEFAULT_FIDI_VALUE */
#ifndef DEFAULT_FIDI
#define DEFAULT_FIDI 0x11U
#endif
#ifndef DEFAULT_T01CONVCHECKSUM
#define DEFAULT_T01CONVCHECKSUM 0x00U
#endif
#ifndef DEFAULT_EXTRA_GUARDTIME
#define DEFAULT_EXTRA_GUARDTIME 0x00U
#endif
#ifndef DEFAULT_WAITINGINTEGER
#define DEFAULT_WAITINGINTEGER 0x0AU
#endif
#ifndef DEFAULT_CLOCKSTOP
#define DEFAULT_CLOCKSTOP 0x00U
#endif
#ifndef DEFAULT_IFSC
#define DEFAULT_IFSC 0x20U
#endif
#ifndef DEFAULT_NAD
#define DEFAULT_NAD 0x00U
#endif
/* Following Parameters used in PC_to_RDR_IccPowerOn */
#define VOLTAGE_SELECTION_AUTOMATIC 0xFFU
#define VOLTAGE_SELECTION_3V 0x02U
#define VOLTAGE_SELECTION_5V 0x01U
#define VOLTAGE_SELECTION_1V8 0x03U
/*
Offset=0 bmICCStatus 2 bit 0, 1, 2
0 - An ICC is present and active (power is on and stable, RST is inactive)
1 - An ICC is present and inactive (not activated or shut down by hardware error)
2 - No ICC is present
3 - RFU
Offset=0 bmRFU 4 bits 0 RFU
Offset=6 bmCommandStatus 2 bits 0, 1, 2
0 - Processed without error
1 - Failed (error code provided by the error register)
2 - Time Extension is requested
3 - RFU
*/
#define BM_ICC_PRESENT_ACTIVE 0x00U
#define BM_ICC_PRESENT_INACTIVE 0x01U
#define BM_ICC_NO_ICC_PRESENT 0x02U
#define BM_COMMAND_STATUS_OFFSET 0x06U
#define BM_COMMAND_STATUS_NO_ERROR 0x00U
#define BM_COMMAND_STATUS_FAILED (0x01U << BM_COMMAND_STATUS_OFFSET)
#define BM_COMMAND_STATUS_TIME_EXTN (0x02 << BM_COMMAND_STATUS_OFFSET)
#if (ATR_T01 == 0)
#define SIZE_OF_ATR 19U
#else
#define SIZE_OF_ATR 15U
#endif
/* defines for the CCID_CMD Layers */
#define LEN_RDR_TO_PC_SLOTSTATUS 10U
#define LEN_PROTOCOL_STRUCT_T0 5U
#define LEN_PROTOCOL_STRUCT_T1 7U
#define BPROTOCOL_NUM_T0 0U
#define BPROTOCOL_NUM_T1 1U
/************************************************************************************/
/* ERROR CODES for RDR_TO_PC_HARDWAREERROR Message : bHardwareErrorCode */
/************************************************************************************/
#define HARDWAREERRORCODE_OVERCURRENT 0x01U
#define HARDWAREERRORCODE_VOLTAGEERROR 0x02U
#define HARDWAREERRORCODE_OVERCURRENT_IT 0x04U
#define HARDWAREERRORCODE_VOLTAGEERROR_IT 0x08U
#define CHK_PARAM_SLOT 0x01U
#define CHK_PARAM_DWLENGTH 0x02U
#define CHK_PARAM_abRFU2 0x04U
#define CHK_PARAM_abRFU3 0x08U
#define CHK_PARAM_CARD_PRESENT 0x10U
#define CHK_PARAM_ABORT 0x20U
#define CHK_ACTIVE_STATE 0x40U
/* Exported functions ------------------------------------------------------- */
uint8_t PC_to_RDR_IccPowerOn(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_IccPowerOff(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_GetSlotStatus(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_XfrBlock(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_GetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_ResetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_SetParameters(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_Escape(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_IccClock(USBD_HandleTypeDef *pdev);
uint8_t PC_to_RDR_Abort(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_T0Apdu(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_Mechanical(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_SetDataRateAndClockFrequency(USBD_HandleTypeDef *pdev);
uint8_t PC_TO_RDR_Secure(USBD_HandleTypeDef *pdev);
void RDR_to_PC_DataBlock(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_NotifySlotChange(USBD_HandleTypeDef *pdev);
void RDR_to_PC_SlotStatus(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_Parameters(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_Escape(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void RDR_to_PC_DataRateAndClockFrequency(uint8_t errorCode, USBD_HandleTypeDef *pdev);
void CCID_UpdSlotStatus(USBD_HandleTypeDef *pdev, uint8_t slotStatus);
void CCID_UpdSlotChange(USBD_HandleTypeDef *pdev, uint8_t changeStatus);
uint8_t CCID_IsSlotStatusChange(USBD_HandleTypeDef *pdev);
uint8_t CCID_CmdAbort(uint8_t slot, uint8_t seq);
uint8_t USBD_CCID_Transfer_Data_Request(USBD_HandleTypeDef *pdev,
uint8_t *dataPointer, uint16_t dataLen);
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_CMD_H */

View File

@@ -0,0 +1,76 @@
/**
******************************************************************************
* @file usbd_ccid_if_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_IF_TEMPLATE_H
#define __USBD_CCID_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#ifndef __USBD_CCID_SMARTCARD_H
#include "usbd_ccid_smartcard_template.h"
#endif
/* Exported defines ----------------------------------------------------------*/
/*****************************************************************************/
/*********************** CCID Bulk Transfer State machine ********************/
/*****************************************************************************/
#define CCID_STATE_IDLE 0U
#define CCID_STATE_DATA_OUT 1U
#define CCID_STATE_RECEIVE_DATA 2U
#define CCID_STATE_SEND_RESP 3U
#define CCID_STATE_DATAIN 4U
#define CCID_STATE_UNCORRECT_LENGTH 5U
#define DIR_IN 0U
#define DIR_OUT 1U
#define BOTH_DIR 2U
/************ Value of the Interrupt transfer status to set ******************/
#define IntrStatus_Complete 1U
#define IntrStatus_Reset 0U
/************** slot change status *******************************************/
#define SlotStatus_Changed 1U
#define SlotStatus_Reset 0U
/* Exported types ------------------------------------------------------------*/
extern USBD_HandleTypeDef USBD_Device;
/* CCID Interface callback */
extern USBD_CCID_ItfTypeDef USBD_CCID_If_fops;
/* Exported macros -----------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_IF_TEMPLATE_H */

View File

@@ -0,0 +1,100 @@
/**
******************************************************************************
* @file usbd_ccid_sc_if_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_sc_if_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_SC_IF_TEMPLATE_H
#define __USBD_CCID_SC_IF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#ifndef __USBD_CCID_SMARTCARD_H
#include "usbd_ccid_smartcard_template.h"
#endif
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
typedef struct
{
uint8_t voltage; /* Voltage for the Card Already Selected */
uint8_t USART_GuardTime;
uint8_t SC_A2R_FiDi;
uint8_t SC_hostFiDi;
uint8_t USART_DefaultGuardTime;
uint32_t USART_BaudRate;
} SC_Param_t;
#pragma pack(1)
typedef struct
{
uint8_t bmFindexDindex;
uint8_t bmTCCKST0;
uint8_t bGuardTimeT0;
uint8_t bWaitingIntegerT0;
uint8_t bClockStop;
uint8_t bIfsc;
uint8_t bNad;
} Protocol_01_DataTypeDef;
#pragma pack()
extern Protocol_01_DataTypeDef ProtocolData;
extern SC_Param_t SC_Param;
/* Exported macro ------------------------------------------------------------*/
#define MAX_EXTRA_GUARD_TIME (0xFF - DEFAULT_EXTRA_GUARDTIME)
/* Following macros are used for SC_XferBlock command */
#define XFER_BLK_SEND_DATA 1U /* Command is for issuing the data */
#define XFER_BLK_RECEIVE_DATA 2U /* Command is for receiving the data */
#define XFER_BLK_NO_DATA 3U /* Command type is No data exchange */
/* Exported functions ------------------------------------------------------- */
/* APPLICATION LAYER ---------------------------------------------------------*/
void SC_Itf_InitParams(void);
void SC_Itf_IccPowerOn(uint8_t voltage);
void SC_Itf_IccPowerOff(void);
uint8_t SC_GetState(void);
uint8_t SC_Itf_XferBlock(uint8_t *ptrBlock, uint32_t blockLen,
uint16_t expectedLen,
USBD_CCID_BulkIn_DataTypeDef *CCID_BulkIn_Data);
uint8_t SC_Itf_SetParams(Protocol_01_DataTypeDef *pPtr, uint8_t T_01);
uint8_t SC_Itf_Escape(uint8_t *escapePtr, uint32_t escapeLen,
uint8_t *responseBuff, uint32_t *responseLen);
uint8_t SC_Itf_SetClock(uint8_t bClockCommand);
uint8_t SC_Itf_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
uint8_t bClassEnvelope);
uint8_t SC_Itf_Mechanical(uint8_t bFunction);
uint8_t SC_Itf_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
uint32_t dwDataRate);
uint8_t SC_Itf_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
uint8_t *pbuf, uint32_t *returnLen);
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_SC_IF_TEMPLATE_H */

View File

@@ -0,0 +1,279 @@
/**
******************************************************************************
* @file usbd_ccid_smartcard_template.h
* @author MCD Application Team
* @brief header file for the usbd_ccid_smartcard_template.c file.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CCID_SMARTCARD_TEMPLATE_H
#define __USBD_CCID_SMARTCARD_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#ifndef __USBD_CCID_IF_H
#include "usbd_ccid_if_template.h"
#endif
/* Exported constants --------------------------------------------------------*/
#define T0_PROTOCOL 0x00U /* T0 protocol */
#define T1_PROTOCOL 0x01U /* T1 protocol */
#define DIRECT 0x3BU /* Direct bit convention */
#define INDIRECT 0x3FU /* Indirect bit convention */
#define SETUP_LENGTH 20U
#define HIST_LENGTH 20U
#define SC_TRANSMIT_TIMEOUT 200U /* Direction to transmit */
#define MAX_PROTOCOLLEVEL 7U /* Maximum levels of protocol */
#define MAX_INTERFACEBYTE 4U /* Maximum number of interface bytes per protocol */
#define LC_MAX 24U
#define SC_RECEIVE_TIMEOUT 0x8000U /* Direction to reader */
/* T=1 protocol constants */
#define T1_I_BLOCK 0x00U /* PCB (I-block: b8 = 0) */
#define T1_R_BLOCK 0x80U /* PCB (R-block: b8 b7 = 10) */
#define T1_S_BLOCK 0xC0U /* PCB (S-block: b8 b7 = 11) */
/* I block */
#define T1_I_SEQ_SHIFT 6U /* N(S) position (bit 7) */
/* R block */
#define T1_IS_ERROR(pcb) ((pcb) & 0x0FU)
#define T1_EDC_ERROR 0x01U /* [b6..b1] = 0-N(R)-0001 */
#define T1_OTHER_ERROR 0x02U /* [b6..b1] = 0-N(R)-0010 */
#define T1_R_SEQ_SHIFT 4U /* N(R) position (b5) */
/* S block */
#define T1_S_RESPONSE 0x20U /* If response: set bit b6, if request reset b6 in PCB S-Block */
#define T1_S_RESYNC 0x00U /* RESYNCH: b6->b1: 000000 of PCB S-Block */
#define T1_S_IFS 0x01U /* IFS: b6->b1: 000001 of PCB S-Block */
#define T1_S_ABORT 0x02U /* ABORT: b6->b1: 000010 of PCB S-Block */
#define T1_S_WTX 0x03U /* WTX: b6->b1: 000011 of PCB S-Block */
#define NAD 0U /* NAD byte position in the block */
#define PCB 1U /* PCB byte position in the block */
#define LEN 2U /* LEN byte position in the block */
#define DATA 3U /* The position of the first byte of INF field in the block */
/* Modifiable parameters */
#define SAD 0x0U /* Source address: reader (allowed values 0 -> 7) */
#define DAD 0x0U /* Destination address: card (allowed values 0 -> 7) */
#define IFSD_VALUE 254U /* Max length of INF field Supported by the reader */
#define SC_FILE_SIZE 0x100U /* File size */
#define SC_FILE_ID 0x0001U /* File identifier */
#define SC_CLASS 0x00U
/* Constant parameters */
#define INS_SELECT_FILE 0xA4U /* Select file instruction */
#define INS_READ_FILE 0xB0U /* Read file instruction */
#define INS_WRITE_FILE 0xD6U /* Write file instruction */
#define TRAILER_LENGTH 2U /* Trailer length (SW1 and SW2: 2 bytes) */
#define SC_T1_RECEIVE_SUCCESS 0U
#define SC_T1_BWT_TIMEOUT 1U
#define SC_T1_CWT_TIMEOUT 2U
#define DEFAULT_FIDI_VALUE 0x11U
#define PPS_REQUEST 0xFFU
/* SC Tree Structure -----------------------------------------------------------
MasterFile
________|___________
| | |
System UserData Note
------------------------------------------------------------------------------*/
/* SC ADPU Command: Operation Code -------------------------------------------*/
#define SC_CLA_NAME 0x00U
/*------------------------ Data Area Management Commands ---------------------*/
#define SC_SELECT_FILE 0xA4U
#define SC_GET_RESPONCE 0xC0U
#define SC_STATUS 0xF2U
#define SC_UPDATE_BINARY 0xD6U
#define SC_READ_BINARY 0xB0U
#define SC_WRITE_BINARY 0xD0U
#define SC_UPDATE_RECORD 0xDCU
#define SC_READ_RECORD 0xB2U
/*-------------------------- Administrative Commands -------------------------*/
#define SC_CREATE_FILE 0xE0U
/*-------------------------- Safety Management Commands ----------------------*/
#define SC_VERIFY 0x20U
#define SC_CHANGE 0x24U
#define SC_DISABLE 0x26U
#define SC_ENABLE 0x28U
#define SC_UNBLOCK 0x2CU
#define SC_EXTERNAL_AUTH 0x82U
#define SC_GET_CHALLENGE 0x84U
/*-------------------------- Smartcard Interface Byte-------------------------*/
#define SC_INTERFACEBYTE_TA 0U /* Interface byte TA(i) */
#define SC_INTERFACEBYTE_TB 1U /* Interface byte TB(i) */
#define SC_INTERFACEBYTE_TC 2U /* Interface byte TC(i) */
#define SC_INTERFACEBYTE_TD 3U /* Interface byte TD(i) */
/*-------------------------- Answer to reset Commands ------------------------*/
#define SC_GET_A2R 0x00U
/* SC STATUS: Status Code ----------------------------------------------------*/
#define SC_EF_SELECTED 0x9FU
#define SC_DF_SELECTED 0x9FU
#define SC_OP_TERMINATED 0x9000U
/* Smartcard Voltage */
#define SC_VOLTAGE_5V 0x00U
#define SC_VOLTAGE_3V 0x01U
#define SC_VOLTAGE_NOINIT 0xFFU
/*----------------- ATR Protocole supported ----------------------------------*/
#define ATR_T01 0x00U
/* Exported types ------------------------------------------------------------*/
typedef enum
{
SC_POWER_ON = 0x00,
SC_RESET_LOW = 0x01,
SC_RESET_HIGH = 0x02,
SC_ACTIVE = 0x03,
SC_ACTIVE_ON_T0 = 0x04,
SC_ACTIVE_ON_T1 = 0x05,
SC_POWER_OFF = 0x06,
SC_NO_INIT = 0x07
} SC_State;
/* Interface Byte structure - TA(i), TB(i), TC(i) and TD(i) ------------------*/
typedef struct
{
uint8_t Status; /* The Presence of the Interface byte */
uint8_t Value; /* The Value of the Interface byte */
} SC_InterfaceByte;
/* Protocol Level structure - ------------------------------------------------*/
typedef struct
{
SC_InterfaceByte InterfaceByte[MAX_INTERFACEBYTE]; /* The Values of the Interface byte TA(i), TB(i), TC(i)and TD(i) */
} SC_ProtocolLevel;
/* ATR structure - Answer To Reset -------------------------------------------*/
typedef struct
{
uint8_t TS; /* Bit Convention Direct/Indirect */
uint8_t T0; /* Each bit in the high nibble = Presence of the further interface byte;
Low nibble = Number of historical byte */
SC_ProtocolLevel T[MAX_PROTOCOLLEVEL]; /* Setup array */
uint8_t H[HIST_LENGTH]; /* Historical array */
uint8_t Tlength; /* Setup array dimension */
uint8_t Hlength; /* Historical array dimension */
uint8_t TCK;
} SC_ATR;
/* ADPU-Header command structure ---------------------------------------------*/
typedef struct
{
uint8_t CLA; /* Command class */
uint8_t INS; /* Operation code */
uint8_t P1; /* Selection Mode */
uint8_t P2; /* Selection Option */
} SC_Header;
/* ADPU-Body command structure -----------------------------------------------*/
typedef struct
{
uint8_t LC; /* Data field length */
uint8_t Data[LC_MAX]; /* Command parameters */
uint8_t LE; /* Expected length of data to be returned */
} SC_Body;
/* ADPU Command structure ----------------------------------------------------*/
typedef struct
{
SC_Header Header;
SC_Body Body;
} SC_ADPU_Commands;
/* SC response structure -----------------------------------------------------*/
typedef struct
{
uint8_t Data[LC_MAX]; /* Data returned from the card */
uint8_t SW1; /* Command Processing status */
uint8_t SW2; /* Command Processing qualification */
} SC_ADPU_Response;
/* SC Command Status -----------------------------------------------------*/
typedef enum
{
SC_CS_FAILED = 0x00,
SC_CS_PIN_ENABLED = 0x01,
SC_CS_PIN_VERIFIED = 0x02,
SC_CS_READ = 0x03,
SC_CS_PIN_CHANGED = 0x04
} SC_Command_State;
/* SC Response Status -----------------------------------------------------*/
typedef enum
{
REP_OK = 0x00,
REP_NOT_OK = 0x01,
REP_NOT_SUPP = 0x02,
REP_ENABLED = 0x03,
REP_CHANGE = 0x04
} REP_Command_t;
/* Conforming of Command with ICC APP -----------------------------------------------------*/
typedef enum
{
Command_OK = 0x00,
Command_NOT_OK = 0x01,
} Command_State_t;
typedef enum
{
SC_DISABLED = 0U,
SC_ENABLED = !SC_DISABLED
} SCPowerState;
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/* APPLICATION LAYER ---------------------------------------------------------*/
void SC_Handler(SC_State *SCState, SC_ADPU_Commands *SC_ADPU, SC_ADPU_Response *SC_Response);
void SC_PowerCmd(SCPowerState NewState);
void SC_ParityErrorHandler(void);
void SC_PTSConfig(void);
uint8_t SC_Detect(void);
uint32_t SC_GetDTableValue(uint32_t idx);
void SC_VoltageConfig(uint32_t SC_Voltage);
void SC_SetState(SC_State scState);
void SC_IOConfig(void);
extern uint8_t SC_ATR_Table[40];
extern SC_ATR SC_A2R;
extern SC_ADPU_Response SC_Response;
extern uint8_t ProtocolNUM_OUT;
extern SC_ADPU_Commands SC_ADPU;
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CCID_SMARTCARD_TEMPLATE_H */

968
Class/CCID/Src/usbd_ccid.c Normal file
View File

@@ -0,0 +1,968 @@
/**
******************************************************************************
* @file usbd_ccid.c
* @author MCD Application Team
* @brief This file provides the high layer firmware functions to manage
* all the functionalities of the USB CCID Class:
*
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
* @verbatim
*
* ===================================================================
* CCID Class Driver Description
* ===================================================================
* This module manages the Specification for Integrated Circuit(s)
* Cards Interface Revision 1.1
* This driver implements the following aspects of the specification:
* - Device descriptor management
* - Configuration descriptor management
* - Enumeration as CCID device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
* and enumeration for each implemented memory interface
* - Bulk OUT/IN data Transfers
* - Requests management
*
* @endverbatim
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_cmd.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CCID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CCID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CCID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_CCID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CCID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_CCID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_CCID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CCID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_CCID_DispatchCommand(USBD_HandleTypeDef *pdev);
static uint8_t USBD_CCID_ReceiveCmdHeader(USBD_HandleTypeDef *pdev,
uint8_t *pDst, uint16_t u8length);
static uint8_t *USBD_CCID_GetHSCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetFSCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetOtherSpeedCfgDesc(uint16_t *length);
static uint8_t *USBD_CCID_GetDeviceQualifierDescriptor(uint16_t *length);
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Variables
* @{
*/
/* CCID interface class callbacks structure */
USBD_ClassTypeDef USBD_CCID =
{
USBD_CCID_Init,
USBD_CCID_DeInit,
USBD_CCID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_CCID_DataIn,
USBD_CCID_DataOut,
NULL, /*SOF */
NULL, /*ISOIn*/
NULL, /*ISOOut*/
USBD_CCID_GetHSCfgDesc,
USBD_CCID_GetFSCfgDesc,
USBD_CCID_GetOtherSpeedCfgDesc,
USBD_CCID_GetDeviceQualifierDescriptor,
};
/* USB CCID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CCID_CfgHSDesc[USB_CCID_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CCID_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: */
0x00, /* iConfiguration: */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif
USBD_MAX_POWER, /* MaxPower (mA) */
/******************** CCID **** interface ********************/
CCID_INTERFACE_DESC_SIZE, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
USB_DEVICE_CLASS_CCID, /* bInterfaceClass: user's interface for CCID */
0x00, /* bInterfaceSubClass : No subclass, can be changed but no description in USB 2.0 Spec */
0x00, /* nInterfaceProtocol : None */
0x00, /* iInterface */
/******************* CCID class descriptor ********************/
CCID_CLASS_DESC_SIZE, /* bLength: CCID Descriptor size */
CCID_DESC_TYPE, /* bDescriptorType: Functional Descriptor type. */
0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.1) */
0x01, /* bcdCCID(MSB) */
0x00, /* bMaxSlotIndex :highest available slot on this device */
CCID_VOLTAGE_SUPP, /* bVoltageSupport: bVoltageSupport: 5v, 3v and 1.8v */
LOBYTE(USBD_CCID_PROTOCOL), /* dwProtocols: supports T=0 and T=1 */
HIBYTE(USBD_CCID_PROTOCOL),
0x00,
0x00,
LOBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ), /* dwDefaultClock: 3.6Mhz */
HIBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_CLOCK_FREQ), /* dwMaximumClock */
HIBYTE(USBD_CCID_MAX_CLOCK_FREQ),
0x00,
0x00,
0x00, /* bNumClockSupported */
LOBYTE(USBD_CCID_DEFAULT_DATA_RATE), /* dwDataRate: 9677 bps */
HIBYTE(USBD_CCID_DEFAULT_DATA_RATE),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_DATA_RATE), /* dwMaxDataRate: */
HIBYTE(USBD_CCID_MAX_DATA_RATE),
0x00,
0x00,
0x35, /* bNumDataRatesSupported */
LOBYTE(USBD_CCID_MAX_INF_FIELD_SIZE), /* dwMaxIFSD: maximum IFSD supported for T=1 */
HIBYTE(USBD_CCID_MAX_INF_FIELD_SIZE),
0x00,
0x00,
0x00, 0x00, 0x00, 0x00, /* dwSynchProtocols */
0x00, 0x00, 0x00, 0x00, /* dwMechanical: no special characteristics */
0xBA, 0x04, EXCHANGE_LEVEL_FEATURE, 0x00, /* dwFeatures */
LOBYTE(CCID_MAX_BLOCK_SIZE_HEADER), /* dwMaxCCIDMessageLength: Maximum block size + header*/
HIBYTE(CCID_MAX_BLOCK_SIZE_HEADER),
0x00,
0x00,
0x00, /* bClassGetResponse*/
0x00, /* bClassEnvelope */
0x00, 0x00, /* wLcdLayout : 0000h no LCD. */
0x03, /* bPINSupport : PIN verification and PIN modification */
0x01, /* bMaxCCIDBusySlots */
/******************** CCID Endpoints ********************/
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_IN_EP, /* Endpoint address (IN, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_HS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_HS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_OUT_EP, /* Endpoint address (OUT, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_HS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_HS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
CCID_CMD_EP, /* bEndpointAddress: Endpoint Address (IN) */
USBD_EP_TYPE_INTR, /* bmAttributes: Interrupt endpoint */
LOBYTE(CCID_CMD_PACKET_SIZE),
HIBYTE(CCID_CMD_PACKET_SIZE),
CCID_CMD_HS_BINTERVAL /* Polling interval in milliseconds */
};
/* USB CCID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CCID_CfgFSDesc[USB_CCID_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CCID_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: */
0x00, /* iConfiguration: */
#if (USBD_SELF_POWERED == 1U)
0xC0, /* bmAttributes: Bus Powered according to user configuration */
#else
0x80, /* bmAttributes: Bus Powered according to user configuration */
#endif
USBD_MAX_POWER, /* MaxPower (mA) */
/******************** CCID **** interface ********************/
CCID_INTERFACE_DESC_SIZE, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
USB_DEVICE_CLASS_CCID, /* bInterfaceClass: user's interface for CCID */
0x00, /* bInterfaceSubClass : No subclass, can be changed but no description in USB 2.0 Spec */
0x00, /* nInterfaceProtocol : None */
0x00, /* iInterface */
/******************* CCID class descriptor ********************/
CCID_CLASS_DESC_SIZE, /* bLength: CCID Descriptor size */
CCID_DESC_TYPE, /* bDescriptorType: Functional Descriptor type. */
0x10, /* bcdCCID(LSB): CCID Class Spec release number (1.1) */
0x01, /* bcdCCID(MSB) */
0x00, /* bMaxSlotIndex :highest available slot on this device */
CCID_VOLTAGE_SUPP, /* bVoltageSupport: bVoltageSupport: 5v, 3v and 1.8v */
LOBYTE(USBD_CCID_PROTOCOL), /* dwProtocols: supports T=0 and T=1 */
HIBYTE(USBD_CCID_PROTOCOL),
0x00,
0x00,
LOBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ), /* dwDefaultClock: 3.6Mhz */
HIBYTE(USBD_CCID_DEFAULT_CLOCK_FREQ),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_CLOCK_FREQ), /* dwMaximumClock */
HIBYTE(USBD_CCID_MAX_CLOCK_FREQ),
0x00,
0x00,
0x00, /* bNumClockSupported */
LOBYTE(USBD_CCID_DEFAULT_DATA_RATE), /* dwDataRate: 9677 bps */
HIBYTE(USBD_CCID_DEFAULT_DATA_RATE),
0x00,
0x00,
LOBYTE(USBD_CCID_MAX_DATA_RATE), /* dwMaxDataRate */
HIBYTE(USBD_CCID_MAX_DATA_RATE),
0x00,
0x00,
0x35, /* bNumDataRatesSupported */
LOBYTE(USBD_CCID_MAX_INF_FIELD_SIZE), /* dwMaxIFSD: maximum IFSD supported for T=1 */
HIBYTE(USBD_CCID_MAX_INF_FIELD_SIZE),
0x00,
0x00,
0x00, 0x00, 0x00, 0x00, /* dwSynchProtocols */
0x00, 0x00, 0x00, 0x00, /* dwMechanical: no special characteristics */
0xBA, 0x04, EXCHANGE_LEVEL_FEATURE, 0x00, /* dwFeatures */
LOBYTE(CCID_MAX_BLOCK_SIZE_HEADER), /* dwMaxCCIDMessageLength: Maximum block size + header*/
HIBYTE(CCID_MAX_BLOCK_SIZE_HEADER),
0x00,
0x00,
0x00, /* bClassGetResponse*/
0x00, /* bClassEnvelope */
0x00, 0x00, /* wLcdLayout : 0000h no LCD. */
0x03, /* bPINSupport : PIN verification and PIN modification */
0x01, /* bMaxCCIDBusySlots */
/******************** CCID Endpoints ********************/
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_IN_EP, /* Endpoint address (IN, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* Endpoint descriptor length = 7 */
USB_DESC_TYPE_ENDPOINT, /* Endpoint descriptor type */
CCID_OUT_EP, /* Endpoint address (OUT, address 1) */
USBD_EP_TYPE_BULK, /* Bulk endpoint type */
LOBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
HIBYTE(CCID_DATA_FS_MAX_PACKET_SIZE),
0x00, /* Polling interval in milliseconds */
CCID_ENDPOINT_DESC_SIZE, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/
CCID_CMD_EP, /* bEndpointAddress: Endpoint Address (IN) */
USBD_EP_TYPE_INTR, /* bmAttributes: Interrupt endpoint */
LOBYTE(CCID_CMD_PACKET_SIZE),
HIBYTE(CCID_CMD_PACKET_SIZE),
CCID_CMD_FS_BINTERVAL /* Polling interval in milliseconds */
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CCID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/**
* @}
*/
/** @defgroup USBD_CCID_Private_Functions
* @{
*/
/**
* @brief USBD_CCID_Init
* Initialize the CCID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CCID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
USBD_CCID_HandleTypeDef *hccid;
UNUSED(cfgidx);
/* Allocate CCID structure */
hccid = (USBD_CCID_HandleTypeDef *)USBD_malloc(sizeof(USBD_CCID_HandleTypeDef));
if (hccid == NULL)
{
pdev->pClassData = NULL;
return (uint8_t)USBD_EMEM;
}
pdev->pClassData = (void *)hccid;
/* Init the CCID parameters into a state where it can receive a new command message */
hccid->USBD_CCID_Param.bAbortRequestFlag = 0U;
hccid->USBD_CCID_Param.bSeq = 0U;
hccid->USBD_CCID_Param.bSlot = 0U;
hccid->MaxPcktLen = (pdev->dev_speed == USBD_SPEED_HIGH) ? \
CCID_DATA_HS_MAX_PACKET_SIZE : CCID_DATA_FS_MAX_PACKET_SIZE;
/* Open EP IN */
(void)USBD_LL_OpenEP(pdev, CCID_IN_EP, USBD_EP_TYPE_BULK, (uint16_t)hccid->MaxPcktLen);
pdev->ep_in[CCID_IN_EP & 0xFU].is_used = 1U;
/* Open EP OUT */
(void)USBD_LL_OpenEP(pdev, CCID_OUT_EP, USBD_EP_TYPE_BULK, (uint16_t)hccid->MaxPcktLen);
pdev->ep_out[CCID_OUT_EP & 0xFU].is_used = 1U;
/* Open INTR EP IN */
(void)USBD_LL_OpenEP(pdev, CCID_CMD_EP,
USBD_EP_TYPE_INTR, CCID_CMD_PACKET_SIZE);
pdev->ep_in[CCID_CMD_EP & 0xFU].is_used = 1U;
/* Init physical Interface components */
((USBD_CCID_ItfTypeDef *)pdev->pUserData)->Init(pdev);
/* Prepare Out endpoint to receive next packet */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DeInit
* DeInitialize the CCID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_CCID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Close EP IN */
(void)USBD_LL_CloseEP(pdev, CCID_IN_EP);
pdev->ep_in[CCID_IN_EP & 0xFU].is_used = 0U;
/* Close EP OUT */
(void)USBD_LL_CloseEP(pdev, CCID_OUT_EP);
pdev->ep_out[CCID_OUT_EP & 0xFU].is_used = 0U;
/* Close EP Command */
(void)USBD_LL_CloseEP(pdev, CCID_CMD_EP);
pdev->ep_in[CCID_CMD_EP & 0xFU].is_used = 0U;
/* DeInit physical Interface components */
if (pdev->pClassData != NULL)
{
((USBD_CCID_ItfTypeDef *)pdev->pUserData)->DeInit(pdev);
(void)USBD_free(pdev->pClassData);
pdev->pClassData = NULL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_Setup
* Handle the CCID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_CCID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
USBD_CCID_ItfTypeDef *hCCIDitf = (USBD_CCID_ItfTypeDef *)pdev->pUserData;
USBD_StatusTypeDef ret = USBD_OK;
uint8_t ifalt = 0U;
uint16_t status_info = 0U;
uint16_t len;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
/* Class request */
case USB_REQ_TYPE_CLASS :
if (req->wLength != 0U)
{
len = MIN(CCID_EP0_BUFF_SIZ, req->wLength);
if ((req->bmRequest & 0x80U) != 0U)
{
hCCIDitf->Control(req->bRequest, hccid->data, &len);
(void)USBD_CtlSendData(pdev, hccid->data, len);
}
else
{
(void)USBD_CtlPrepareRx(pdev, hccid->data, len);
}
}
else
{
len = 0U;
hCCIDitf->Control(req->bRequest, (uint8_t *)&req->wValue, &len);
}
break;
/* Interface & Endpoint request */
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_INTERFACE:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
(void)USBD_CtlSendData(pdev, &ifalt, 1U);
}
else
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE:
if (pdev->dev_state != USBD_STATE_CONFIGURED)
{
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_CLEAR_FEATURE:
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError(pdev, req);
ret = USBD_FAIL;
break;
}
return (uint8_t)ret;
}
/**
* @brief USBD_CCID_DataIn
* Data sent on non-control IN endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CCID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
if (epnum == (CCID_IN_EP & 0x7FU))
{
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
/*************** Handle Bulk Transfer IN data completion *****************/
switch (hccid->blkt_state)
{
case CCID_STATE_SEND_RESP:
/* won't wait ack to avoid missing a command */
hccid->blkt_state = CCID_STATE_IDLE;
/* Prepare EP to Receive Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, CCID_DATA_FS_MAX_PACKET_SIZE);
break;
default:
break;
}
}
else if (epnum == (CCID_CMD_EP & 0x7FU))
{
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
/*************** Handle Interrupt Transfer IN data completion *****************/
(void)USBD_CCID_IntMessage(pdev);
}
else
{
return (uint8_t)USBD_FAIL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DataOut
* Data received on non-control Out endpoint
* @param pdev: device instance
* @param epnum: endpoint number
* @retval status
*/
static uint8_t USBD_CCID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
uint16_t CurrPcktLen;
if (hccid == NULL)
{
return (uint8_t)USBD_EMEM;
}
if (epnum == CCID_OUT_EP)
{
CurrPcktLen = (uint16_t)USBD_GetRxCount(pdev, epnum);
switch (hccid->blkt_state)
{
case CCID_STATE_IDLE:
if (CurrPcktLen >= (uint16_t)CCID_CMD_HEADER_SIZE)
{
hccid->UsbMessageLength = CurrPcktLen; /* Store for future use */
/* Fill CCID_BulkOut Data Buffer from USB Buffer */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
/*
Refer : 6 CCID Messages
The response messages always contain the exact same slot number,
and sequence number fields from the header that was contained in
the Bulk-OUT command message.
*/
hccid->UsbBlkInData.bSlot = hccid->UsbBlkOutData.bSlot;
hccid->UsbBlkInData.bSeq = hccid->UsbBlkOutData.bSeq;
if (CurrPcktLen < hccid->MaxPcktLen)
{
/* Short message, less than the EP Out Size, execute the command,
if parameter like dwLength is too big, the appropriate command will
give an error */
(void)USBD_CCID_DispatchCommand(pdev);
}
else
{
/* Check if length of data to be sent by host is > buffer size */
if (hccid->UsbBlkOutData.dwLength > (uint32_t)ABDATA_SIZE)
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
else
{
/* Expect more data on OUT EP */
hccid->blkt_state = CCID_STATE_RECEIVE_DATA;
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
} /* if (CurrPcktLen == CCID_DATA_MAX_PACKET_SIZE) ends */
} /* if (CurrPcktLen >= CCID_DATA_MAX_PACKET_SIZE) ends */
} /* if (CurrPcktLen >= CCID_CMD_HEADER_SIZE) ends */
else
{
if (CurrPcktLen == 0x00U) /* Zero Length Packet Received */
{
hccid->blkt_state = CCID_STATE_IDLE;
}
}
break;
case CCID_STATE_RECEIVE_DATA:
hccid->UsbMessageLength += CurrPcktLen;
if (CurrPcktLen < hccid->MaxPcktLen)
{
/* Short message, less than the EP Out Size, execute the command,
if parameter like dwLength is too big, the appropriate command will
give an error */
/* Full command is received, process the Command */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
(void)USBD_CCID_DispatchCommand(pdev);
}
else if (CurrPcktLen == hccid->MaxPcktLen)
{
if (hccid->UsbMessageLength < (hccid->UsbBlkOutData.dwLength + (uint32_t)CCID_CMD_HEADER_SIZE))
{
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen); /* Copy data */
/* Prepare EP to Receive next Cmd */
(void)USBD_LL_PrepareReceive(pdev, CCID_OUT_EP,
hccid->data, hccid->MaxPcktLen);
}
else if (hccid->UsbMessageLength == (hccid->UsbBlkOutData.dwLength + (uint32_t)CCID_CMD_HEADER_SIZE))
{
/* Full command is received, process the Command */
(void)USBD_CCID_ReceiveCmdHeader(pdev, (uint8_t *)&hccid->UsbBlkOutData.bMessageType,
(uint16_t)CurrPcktLen);
(void)USBD_CCID_DispatchCommand(pdev);
}
else
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
}
else
{
/* Too long data received.... Error ! */
hccid->blkt_state = CCID_STATE_UNCORRECT_LENGTH;
}
break;
case CCID_STATE_UNCORRECT_LENGTH:
hccid->blkt_state = CCID_STATE_IDLE;
break;
default:
break;
}
}
else
{
return (uint8_t)USBD_FAIL;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_DispatchCommand
* Parse the commands and Process command
* @param pdev: device instance
* @retval status value
*/
static uint8_t USBD_CCID_DispatchCommand(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
uint8_t errorCode;
switch (hccid->UsbBlkOutData.bMessageType)
{
case PC_TO_RDR_ICCPOWERON:
errorCode = PC_to_RDR_IccPowerOn(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
case PC_TO_RDR_ICCPOWEROFF:
errorCode = PC_to_RDR_IccPowerOff(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_GETSLOTSTATUS:
errorCode = PC_to_RDR_GetSlotStatus(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_XFRBLOCK:
errorCode = PC_to_RDR_XfrBlock(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
case PC_TO_RDR_GETPARAMETERS:
errorCode = PC_to_RDR_GetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_RESETPARAMETERS:
errorCode = PC_to_RDR_ResetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_SETPARAMETERS:
errorCode = PC_to_RDR_SetParameters(pdev);
RDR_to_PC_Parameters(errorCode, pdev);
break;
case PC_TO_RDR_ESCAPE:
errorCode = PC_to_RDR_Escape(pdev);
RDR_to_PC_Escape(errorCode, pdev);
break;
case PC_TO_RDR_ICCCLOCK:
errorCode = PC_to_RDR_IccClock(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_ABORT:
errorCode = PC_to_RDR_Abort(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_T0APDU:
errorCode = PC_TO_RDR_T0Apdu(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_MECHANICAL:
errorCode = PC_TO_RDR_Mechanical(pdev);
RDR_to_PC_SlotStatus(errorCode, pdev);
break;
case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
errorCode = PC_TO_RDR_SetDataRateAndClockFrequency(pdev);
RDR_to_PC_DataRateAndClockFrequency(errorCode, pdev);
break;
case PC_TO_RDR_SECURE:
errorCode = PC_TO_RDR_Secure(pdev);
RDR_to_PC_DataBlock(errorCode, pdev);
break;
default:
RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED, pdev);
break;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_Transfer_Data_Request
* Prepare the request response to be sent to the host
* @param pdev: device instance
* @param dataPointer: Pointer to the data buffer to send
* @param dataLen : number of bytes to send
* @retval status value
*/
uint8_t USBD_CCID_Transfer_Data_Request(USBD_HandleTypeDef *pdev,
uint8_t *dataPointer, uint16_t dataLen)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
USBD_CCID_ItfTypeDef *hCCIDitf = (USBD_CCID_ItfTypeDef *)pdev->pUserData;
UNUSED(dataPointer);
hccid->blkt_state = CCID_STATE_SEND_RESP;
hccid->UsbMessageLength = hccid->UsbBlkInData.dwLength + (uint32_t)dataLen; /* Store for future use */
/* use the header declared size packet must be well formed */
hCCIDitf->Response_SendData(pdev, (uint8_t *)&hccid->UsbBlkInData,
(uint16_t)MIN(CCID_DATA_FS_MAX_PACKET_SIZE, hccid->UsbMessageLength));
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_ReceiveCmdHeader
* Receive the Data from USB BulkOut Buffer to Pointer
* @param pdev: device instance
* @param pDst: destination address to copy the buffer
* @param u8length: length of data to copy
* @retval status
*/
static uint8_t USBD_CCID_ReceiveCmdHeader(USBD_HandleTypeDef *pdev,
uint8_t *pDst, uint16_t u8length)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
uint8_t *pdst = pDst;
uint32_t Counter;
for (Counter = 0U; Counter < u8length; Counter++)
{
*pdst = hccid->data[Counter];
pdst++;
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_IntMessage
* Send the Interrupt-IN data to the host
* @param pdev: device instance
* @retval None
*/
uint8_t USBD_CCID_IntMessage(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
/* Check if there is change in Smartcard Slot status */
if (CCID_IsSlotStatusChange(pdev) != 0U)
{
/* Check Slot Status is changed. Card is Removed/Fitted */
RDR_to_PC_NotifySlotChange(pdev);
/* Set the Slot status */
((USBD_CCID_ItfTypeDef *)pdev->pUserData)->SetSlotStatus(pdev);
(void)USBD_LL_Transmit(pdev, CCID_CMD_EP, hccid->UsbIntData, 2U);
}
else
{
/* Set the Slot status */
((USBD_CCID_ItfTypeDef *)pdev->pUserData)->SetSlotStatus(pdev);
}
return (uint8_t)USBD_OK;
}
/**
* @brief USBD_CCID_GetHSCfgDesc
* Return configuration descriptor
* @param length pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetHSCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CCID_CfgHSDesc);
return USBD_CCID_CfgHSDesc;
}
/**
* @brief USBD_CCID_GetFSCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetFSCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CCID_CfgFSDesc);
return USBD_CCID_CfgFSDesc;
}
/**
* @brief USBD_CCID_GetOtherSpeedCfgDesc
* Return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetOtherSpeedCfgDesc(uint16_t *length)
{
*length = (uint16_t)sizeof(USBD_CCID_CfgFSDesc);
return USBD_CCID_CfgFSDesc;
}
/**
* @brief USBD_CCID_GetDeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_CCID_GetDeviceQualifierDescriptor(uint16_t *length)
{
*length = (uint16_t)(sizeof(USBD_CCID_DeviceQualifierDesc));
return USBD_CCID_DeviceQualifierDesc;
}
/**
* @brief USBD_CCID_RegisterInterface
* @param pdev: device instance
* @param fops: CD Interface callback
* @retval status
*/
uint8_t USBD_CCID_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CCID_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData = fops;
return (uint8_t)USBD_OK;
}
/**
* @}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,254 @@
/**
******************************************************************************
* @file usbd_ccid_if_template.c
* @author MCD Application Team
* @brief This file provides all the functions for USB Interface for CCID
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid.h"
#include "usbd_ccid_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static REP_Command_t REP_command;
/* Private function prototypes -----------------------------------------------*/
static uint8_t CCID_Init(USBD_HandleTypeDef *pdev);
static uint8_t CCID_DeInit(USBD_HandleTypeDef *pdev);
static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length);
static uint8_t CCID_Response_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len);
static uint8_t CCID_Send_Process(uint8_t *Command, uint8_t *Data);
static uint8_t CCID_Response_Process(void);
static uint8_t CCID_SetSlotStatus(USBD_HandleTypeDef *pdev);
/* Private functions ---------------------------------------------------------*/
/**
* @}
*/
USBD_CCID_ItfTypeDef USBD_CCID_If_fops =
{
CCID_Init,
CCID_DeInit,
CCID_ControlReq,
CCID_Response_SendData,
CCID_Send_Process,
CCID_SetSlotStatus,
};
/**
* @brief CCID_Init
* Initialize the CCID USB Layer
* @param pdev: device instance
* @retval status value
*/
uint8_t CCID_Init(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
/* CCID Related Initialization */
hccid->blkt_state = CCID_STATE_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_DeInit
* Uninitialize the CCID Machine
* @param pdev: device instance
* @retval status value
*/
uint8_t CCID_DeInit(USBD_HandleTypeDef *pdev)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
hccid->blkt_state = CCID_STATE_IDLE;
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_ControlReq
* Manage the CCID class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_ControlReq(uint8_t req, uint8_t *pbuf, uint16_t *length)
{
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)(USBD_Device.pClassData);
UNUSED(length);
switch (req)
{
case REQUEST_ABORT:
/* The wValue field contains the slot number (bSlot) in the low byte
and the sequence number (bSeq) in the high byte.*/
hccid->slot_nb = ((uint16_t) * pbuf & 0x0fU);
hccid->seq_nb = (((uint16_t) * pbuf & 0xf0U) >> 8);
if (CCID_CmdAbort((uint8_t)hccid->slot_nb, (uint8_t)hccid->seq_nb) != 0U)
{
/* If error is returned by lower layer :
Generally Slot# may not have matched */
return (int8_t)USBD_FAIL;
}
break;
case REQUEST_GET_CLOCK_FREQUENCIES:
/* User have to fill the pbuf with the GetClockFrequency data buffer */
break;
case REQUEST_GET_DATA_RATES:
/* User have to fill the pbuf with the GetDataRates data buffer */
break;
default:
break;
}
UNUSED(pbuf);
return ((int8_t)USBD_OK);
}
/**
* @brief CCID_Response_SendData
* Send the data on bulk-in EP
* @param pdev: device instance
* @param buf: pointer to data buffer
* @param len: Data Length
* @retval status value
*/
uint8_t CCID_Response_SendData(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len)
{
(void)USBD_LL_Transmit(pdev, CCID_IN_EP, buf, len);
return (uint8_t)USBD_OK;
}
/**
* @brief CCID_SEND_Process
* @param Command: pointer to a buffer containing command header
* @param Data: pointer to a buffer containing data sent from Host
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_Send_Process(uint8_t *Command, uint8_t *Data)
{
Command_State_t Command_State = Command_NOT_OK;
/* Initialize ICC APP header */
uint8_t SC_Command[5] = {0};
UNUSED(Data);
UNUSED(Command_State);
UNUSED(SC_Command);
/* Start SC Demo ---------------------------------------------------------*/
switch (Command[1]) /* type of instruction */
{
case SC_ENABLE:
/* Add your code here */
break;
case SC_VERIFY:
/* Add your code here */
break;
case SC_READ_BINARY :
/* Add your code here */
break;
case SC_CHANGE :
/* Add your code here */
break;
default:
break;
}
/* check if Command header is OK */
(void)CCID_Response_Process(); /* Get ICC response */
return ((uint8_t)USBD_OK);
}
/**
* @brief CCID_Response_Process
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static uint8_t CCID_Response_Process(void)
{
switch (REP_command)
{
case REP_OK:
/* Add your code here */
break;
case REP_NOT_OK :
/* Add your code here */
break;
case REP_NOT_SUPP :
/* Add your code here */
break;
case REP_ENABLED :
/* Add your code here */
break;
case REP_CHANGE :
/* Add your code here */
break;
default:
break;
}
return ((uint8_t)USBD_OK);
}
/**
* @brief CCID_SetSlotStatus
* Set Slot Status of the Interrupt Transfer
* @param pdev: device instance
* @retval status
*/
uint8_t CCID_SetSlotStatus(USBD_HandleTypeDef *pdev)
{
/* Get the CCID handler pointer */
USBD_CCID_HandleTypeDef *hccid = (USBD_CCID_HandleTypeDef *)pdev->pClassData;
if ((hccid->SlotStatus.SlotStatus) == 1U) /* Transfer Complete Status
of previous Interrupt transfer */
{
/* Add your code here */
}
else
{
/* Add your code here */
}
return (uint8_t)USBD_OK;
}

View File

@@ -0,0 +1,473 @@
/**
******************************************************************************
* @file usbd_ccid_sc_if_template.c
* @author MCD Application Team
* @brief SmartCard Interface file
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid_sc_if_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* State Machine for the SmartCard Interface */
static SC_State SCState = SC_POWER_OFF;
/* APDU Transport Structures */
SC_ADPU_Commands SC_ADPU;
SC_ADPU_Response SC_Response;
SC_Param_t SC_Param;
Protocol_01_DataTypeDef ProtocolData;
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void SC_SaveVoltage(uint8_t voltage);
static void SC_Itf_UpdateParams(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief SC_Itf_IccPowerOn Manages the Warm and Cold Reset
and get the Answer to Reset from ICC
* @param voltage: required by host
* @retval None
*/
void SC_Itf_IccPowerOn(uint8_t voltage)
{
SCState = SC_POWER_ON;
SC_ADPU.Header.CLA = 0x00U;
SC_ADPU.Header.INS = SC_GET_A2R;
SC_ADPU.Header.P1 = 0x00U;
SC_ADPU.Header.P2 = 0x00U;
SC_ADPU.Body.LC = 0x00U;
/* Power ON the card */
SC_PowerCmd(SC_ENABLED);
/* Configure the Voltage, Even if IO is still not configured */
SC_VoltageConfig(voltage);
while ((SCState != SC_ACTIVE_ON_T0) && (SCState != SC_ACTIVE_ON_T1)
&& (SCState != SC_NO_INIT))
{
/* If Either The Card has become Active or Become De-Active */
SC_Handler(&SCState, &SC_ADPU, &SC_Response);
}
if ((SCState == SC_ACTIVE_ON_T0) || (SCState == SC_ACTIVE_ON_T1))
{
SC_Itf_UpdateParams();
/* Apply the Procedure Type Selection (PTS) */
SC_PTSConfig();
/* Save Voltage for Future use */
SC_SaveVoltage(voltage);
}
return;
}
/**
* @brief SC_Itf_IccPowerOff Power OFF the card
* @param None
* @retval None
*/
void SC_Itf_IccPowerOff(void)
{
SC_PowerCmd(SC_DISABLED);
SC_SetState(SC_POWER_OFF);
return;
}
/**
* @brief Initialize the parameters structures to the default value
* @param None
* @retval None
*/
void SC_Itf_InitParams(void)
{
/*
FI, the reference to a clock rate conversion factor
over the bits b8 to b5
- DI, the reference to a baud rate adjustment factor
over the bits b4 to bl
*/
SC_Param.SC_A2R_FiDi = DEFAULT_FIDI;
SC_Param.SC_hostFiDi = DEFAULT_FIDI;
ProtocolData.bmFindexDindex = DEFAULT_FIDI;
/* Placeholder, Ignored */
/* 0 = Direct, first byte of the ICC ATR data. */
ProtocolData.bmTCCKST0 = DEFAULT_T01CONVCHECKSUM;
/* Extra GuardTime = 0 etu */
ProtocolData.bGuardTimeT0 = DEFAULT_EXTRA_GUARDTIME;
ProtocolData.bWaitingIntegerT0 = DEFAULT_WAITINGINTEGER;
ProtocolData.bClockStop = 0U; /* Stopping the Clock is not allowed */
/*T=1 protocol */
ProtocolData.bIfsc = DEFAULT_IFSC;
ProtocolData.bNad = DEFAULT_NAD;
return;
}
/**
* @brief Save the A2R Parameters for further usage
* @param None
* @retval None
*/
static void SC_Itf_UpdateParams(void)
{
/*
FI, the reference to a clock rate conversion factor
over the bits b8 to b5
DI, the reference to a baud rate adjustment factor
over the bits b4 to bl
*/
SC_Param.SC_A2R_FiDi = SC_A2R.T[0].InterfaceByte[0].Value;
SC_Param.SC_hostFiDi = SC_A2R.T[0].InterfaceByte[0].Value;
ProtocolData.bmFindexDindex = SC_A2R.T[0].InterfaceByte[0].Value;
return;
}
/**
* @brief SC_Itf_SetParams
* Set the parameters for CCID/USART interface
* @param pPtr: pointer to buffer containing the
* parameters to be set in USART
* @param T_01: type of protocol, T=1 or T=0
* @retval status value
*/
uint8_t SC_Itf_SetParams(Protocol_01_DataTypeDef *pPtr, uint8_t T_01)
{
/* uint16_t guardTime; */ /* Keep it 16b for handling 8b additions */
uint32_t fi_new;
uint32_t di_new;
Protocol_01_DataTypeDef New_DataStructure;
fi_new = pPtr->bmFindexDindex;
di_new = pPtr->bmFindexDindex;
New_DataStructure.bmTCCKST0 = pPtr->bmTCCKST0;
New_DataStructure.bGuardTimeT0 = pPtr->bGuardTimeT0;
New_DataStructure.bWaitingIntegerT0 = pPtr->bWaitingIntegerT0;
New_DataStructure.bClockStop = pPtr->bClockStop;
if (T_01 == 0x01U)
{
New_DataStructure.bIfsc = pPtr->bIfsc;
New_DataStructure.bNad = pPtr->bNad;
}
else
{
New_DataStructure.bIfsc = 0x00U;
New_DataStructure.bNad = 0x00U;
}
/* Check for the FIDI Value set by Host */
di_new &= (uint8_t)0x0F;
if (SC_GetDTableValue(di_new) == 0U)
{
return SLOTERROR_BAD_FIDI;
}
fi_new >>= 4U;
fi_new &= 0x0FU;
if (SC_GetDTableValue(fi_new) == 0U)
{
return SLOTERROR_BAD_FIDI;
}
if ((T_01 == 0x00U)
&& (New_DataStructure.bmTCCKST0 != 0x00U)
&& (New_DataStructure.bmTCCKST0 != 0x02U))
{
return SLOTERROR_BAD_T01CONVCHECKSUM;
}
if ((T_01 == 0x01U)
&& (New_DataStructure.bmTCCKST0 != 0x10U)
&& (New_DataStructure.bmTCCKST0 != 0x11U)
&& (New_DataStructure.bmTCCKST0 != 0x12U)
&& (New_DataStructure.bmTCCKST0 != 0x13U))
{
return SLOTERROR_BAD_T01CONVCHECKSUM;
}
if ((New_DataStructure.bWaitingIntegerT0 >= 0xA0U)
&& ((New_DataStructure.bmTCCKST0 & 0x10U) == 0x10U))
{
return SLOTERROR_BAD_WAITINGINTEGER;
}
if ((New_DataStructure.bClockStop != 0x00U)
&& (New_DataStructure.bClockStop != 0x03U))
{
return SLOTERROR_BAD_CLOCKSTOP;
}
if (New_DataStructure.bNad != 0x00U)
{
return SLOTERROR_BAD_NAD;
}
/* Put Total GuardTime in USART Settings */
/* USART_SetGuardTime(SC_USART, (uint8_t)(guardTime + DEFAULT_EXTRA_GUARDTIME)); */
/* Save Extra GuardTime Value */
ProtocolData.bGuardTimeT0 = New_DataStructure.bGuardTimeT0;
ProtocolData.bmTCCKST0 = New_DataStructure.bmTCCKST0;
ProtocolData.bWaitingIntegerT0 = New_DataStructure.bWaitingIntegerT0;
ProtocolData.bClockStop = New_DataStructure.bClockStop;
ProtocolData.bIfsc = New_DataStructure.bIfsc;
ProtocolData.bNad = New_DataStructure.bNad;
/* Save New bmFindexDindex */
SC_Param.SC_hostFiDi = pPtr->bmFindexDindex;
SC_PTSConfig();
ProtocolData.bmFindexDindex = pPtr->bmFindexDindex;
return SLOT_NO_ERROR;
}
/**
* @brief SC_Itf_Escape function from the host
* This is user implementable
* @param ptrEscape: pointer to buffer containing the Escape data
* @param escapeLen: length of escaped data
* @param responseBuff: pointer containing escape buffer response
* @param responseLen: length of escape response buffer
* @retval status value
*/
uint8_t SC_Itf_Escape(uint8_t *ptrEscape, uint32_t escapeLen,
uint8_t *responseBuff, uint32_t *responseLen)
{
UNUSED(ptrEscape);
UNUSED(escapeLen);
UNUSED(responseBuff);
UNUSED(responseLen);
/* Manufacturer specific implementation ... */
/*
uint32_t idx;
uint8_t *pResBuff = responseBuff;
uint8_t *pEscape = ptrEscape;
for(idx = 0; idx < escapeLen; idx++)
{
*pResBuff = *pEscape;
pResBuff++;
pEscape++;
}
*responseLen = escapeLen;
*/
return SLOT_NO_ERROR;
}
/**
* @brief SC_Itf_SetClock function to define Clock Status request from the host.
* This is user implementable
* @param bClockCommand: Clock status from the host
* @retval status value
*/
uint8_t SC_Itf_SetClock(uint8_t bClockCommand)
{
/* bClockCommand
00h restarts Clock
01h Stops Clock in the state shown in the bClockStop
field of the PC_to_RDR_SetParameters command
and RDR_to_PC_Parameters message.*/
if (bClockCommand == 0U)
{
/* 00h restarts Clock : Since Clock is always running, PASS this command */
return SLOT_NO_ERROR;
}
else
{
if (bClockCommand == 1U)
{
return SLOTERROR_BAD_CLOCKCOMMAND;
}
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_XferBlock function from the host.
* This is user implementable
* @param ptrBlock : Pointer containing the data from host
* @param blockLen : length of block data for the data transfer
* @param expectedLen: expected length of data transfer
* @param CCID_BulkIn_Data: Pointer containing the CCID Bulk In Data Structure
* @retval status value
*/
uint8_t SC_Itf_XferBlock(uint8_t *ptrBlock, uint32_t blockLen, uint16_t expectedLen,
USBD_CCID_BulkIn_DataTypeDef *CCID_BulkIn_Data)
{
uint8_t ErrorCode = SLOT_NO_ERROR;
UNUSED(CCID_BulkIn_Data);
UNUSED(expectedLen);
UNUSED(blockLen);
UNUSED(ptrBlock);
if (ProtocolNUM_OUT == 0x00U)
{
/* Add your code here */
}
if (ProtocolNUM_OUT == 0x01U)
{
/* Add your code here */
}
if (ErrorCode != SLOT_NO_ERROR)
{
return ErrorCode;
}
return ErrorCode;
}
/**
* @brief SC_Itf_T0Apdu
Class Specific Request from the host to provide supported data rates
* This is Optional function & user implementable
* @param bmChanges : value specifying which parameter is valid in
* command among next bClassGetResponse, bClassEnvelope
* @param bClassGetResponse : Value to force the class byte of the
* header in a Get Response command.
* @param bClassEnvelope : Value to force the class byte of the header
* in a Envelope command.
* @retval status value
*/
uint8_t SC_Itf_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
uint8_t bClassEnvelope)
{
UNUSED(bClassEnvelope);
UNUSED(bClassGetResponse);
/* User have to fill the pbuf with the GetDataRates data buffer */
if (bmChanges == 0U)
{
/* Bit cleared indicates that the associated field is not significant and
that default behaviour defined in CCID class descriptor is selected */
return SLOT_NO_ERROR;
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_Mechanical
Mechanical Function being requested by Host
* This is Optional function & user implementable
* @param bFunction : value corresponds to the mechanical function
* being requested by host
* @retval status value
*/
uint8_t SC_Itf_Mechanical(uint8_t bFunction)
{
UNUSED(bFunction);
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_SetDataRateAndClockFrequency
* Set the Clock and data Rate of the Interface
* This is Optional function & user implementable
* @param dwClockFrequency : value of clock in kHz requested by host
* @param dwDataRate : value of data rate requested by host
* @retval status value
*/
uint8_t SC_Itf_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
uint32_t dwDataRate)
{
/* User have to fill the pbuf with the GetDataRates data buffer */
if ((dwDataRate == USBD_CCID_DEFAULT_DATA_RATE) &&
(dwClockFrequency == USBD_CCID_DEFAULT_CLOCK_FREQ))
{
return SLOT_NO_ERROR;
}
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_Itf_Secure
* Process the Secure command
* This is Optional function & user implementable
* @param dwLength : length of data from the host
* @param bBWI : Block Waiting Timeout sent by host
* @param wLevelParameter : Parameters sent by host
* @param pbuf : buffer containing the data
* @param returnLen : Length of data expected to return
* @retval status value
*/
uint8_t SC_Itf_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
uint8_t *pbuf, uint32_t *returnLen)
{
UNUSED(pbuf);
UNUSED(wLevelParameter);
UNUSED(bBWI);
UNUSED(dwLength);
*returnLen = 0U;
return SLOTERROR_CMD_NOT_SUPPORTED;
}
/**
* @brief SC_SaveVoltage
Saves the voltage value to be saved for further usage
* @param voltage: voltage value to be saved for further usage
* @retval None
*/
static void SC_SaveVoltage(uint8_t voltage)
{
SC_Param.voltage = voltage;
return;
}
/**
* @brief Provides the value of SCState variable
* @param None
* @retval uint8_t SCState
*/
uint8_t SC_GetState(void)
{
return (uint8_t)SCState;
}
/**
* @brief Set the value of SCState variable to Off
* @param scState: value of SCState to be updated
* @retval None
*/
void SC_SetState(SC_State scState)
{
SCState = scState;
return;
}

View File

@@ -0,0 +1,482 @@
/**
******************************************************************************
* @file usbd_ccid_smartcard_template.c
* @author MCD Application Team
* @brief This file provides all the Smartcard firmware functions.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup usbd_ccid_Smartcard
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_ccid_smartcard_template.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Directories & Files ID */
/*The following Directories & Files ID can take any of following Values and can
be used in the smartcard application */
/*
const uint8_t MasterRoot[2] = {0x3F, 0x00};
const uint8_t GSMDir[2] = {0x7F, 0x20};
const uint8_t ICCID[2] = {0x2F, 0xE2};
const uint8_t IMSI[2] = {0x6F, 0x07};
__IO uint8_t ICCID_Content[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint32_t CHV1Status = 0U;
uint8_t CHV1[8] = {'0', '0', '0', '0', '0', '0', '0', '0'};
__IO uint8_t IMSI_Content[9] = {0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
*/
/* F Table: Clock Rate Conversion Table from ISO/IEC 7816-3 */
/* static uint32_t F_Table[16] = {372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768,
1024, 1536, 2048, 0, 0
}; */
/* D Table: Baud Rate Adjustment Factor Table from ISO/IEC 7816-3 */
static uint32_t D_Table[16] = {0, 1, 2, 4, 8, 16, 32, 64, 12, 20, 0, 0, 0, 0, 0, 0};
/* Global variables definition and initialization ----------------------------*/
SC_ATR SC_A2R;
uint8_t SC_ATR_Table[40];
uint8_t ProtocolNUM_OUT;
/* Private function prototypes -----------------------------------------------*/
static void SC_Init(void);
static void SC_DeInit(void);
static void SC_AnswerReq(SC_State *SC_state, uint8_t *card, uint8_t length); /* Ask ATR */
static uint8_t SC_decode_Answer2reset(uint8_t *card); /* Decode ATR */
static void SC_SendData(SC_ADPU_Commands *SCADPU, SC_ADPU_Response *SC_ResponseStatus);
/* static void SC_Reset(GPIO_PinState ResetState); */
/* Private functions ---------------------------------------------------------*/
/**
* @brief Handles all Smartcard states and serves to send and receive all
* communication data between Smartcard and reader.
* @param SCState: pointer to an SC_State enumeration that will contain the
* Smartcard state.
* @param SC_ADPU: pointer to an SC_ADPU_Commands structure that will be initialized.
* @param SC_Response: pointer to a SC_ADPU_Response structure which will be initialized.
* @retval None
*/
void SC_Handler(SC_State *SCState, SC_ADPU_Commands *SC_ADPU, SC_ADPU_Response *SC_Response)
{
uint32_t i, j;
switch (*SCState)
{
case SC_POWER_ON:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
/* Smartcard initialization */
SC_Init();
/* Reset Data from SC buffer */
for (i = 0U; i < 40U; i++)
{
SC_ATR_Table[i] = 0;
}
/* Reset SC_A2R Structure */
SC_A2R.TS = 0U;
SC_A2R.T0 = 0U;
for (i = 0U; i < MAX_PROTOCOLLEVEL; i++)
{
for (j = 0U; j < MAX_INTERFACEBYTE; j++)
{
SC_A2R.T[i].InterfaceByte[j].Status = 0U;
SC_A2R.T[i].InterfaceByte[j].Value = 0U;
}
}
for (i = 0U; i < HIST_LENGTH; i++)
{
SC_A2R.H[i] = 0U;
}
SC_A2R.Tlength = 0U;
SC_A2R.Hlength = 0U;
/* Next State */
*SCState = SC_RESET_LOW;
}
break;
case SC_RESET_LOW:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
/* If card is detected then Power ON, Card Reset and wait for an answer) */
if (SC_Detect() != 0U)
{
while (((*SCState) != SC_POWER_OFF) && ((*SCState) != SC_ACTIVE))
{
SC_AnswerReq(SCState, &SC_ATR_Table[0], 40U); /* Check for answer to reset */
}
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
uint8_t protocol = SC_decode_Answer2reset(&SC_ATR_Table[0]);
if (protocol == T0_PROTOCOL)
{
(*SCState) = SC_ACTIVE_ON_T0;
ProtocolNUM_OUT = T0_PROTOCOL;
}
else if (protocol == T1_PROTOCOL)
{
(*SCState) = SC_ACTIVE_ON_T1;
ProtocolNUM_OUT = T1_PROTOCOL;
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE_ON_T0:
/* process commands other than ATR */
SC_SendData(SC_ADPU, SC_Response);
break;
case SC_ACTIVE_ON_T1:
/* process commands other than ATR */
SC_SendData(SC_ADPU, SC_Response);
break;
case SC_POWER_OFF:
SC_DeInit(); /* Disable Smartcard interface */
break;
default:
(*SCState) = SC_POWER_OFF;
break;
}
}
/**
* @brief Enables or disables the power to the Smartcard.
* @param NewState: new state of the Smartcard power supply.
* This parameter can be: SC_ENABLED or SC_DISABLED.
* @retval None
*/
void SC_PowerCmd(SCPowerState NewState)
{
UNUSED(NewState);
/* enable or disable smartcard pin */
return;
}
/**
* @brief Sets or clears the Smartcard reset pin.
* @param ResetState: this parameter specifies the state of the Smartcard
* reset pin. BitVal must be one of the BitAction enum values:
* @arg Bit_RESET: to clear the port pin.
* @arg Bit_SET: to set the port pin.
* @retval None
*/
/* static void SC_Reset(GPIO_PinState ResetState)
{
UNUSED(ResetState);
return;
}
*/
/**
* @brief Resends the byte that failed to be received (by the Smartcard) correctly.
* @param None
* @retval None
*/
void SC_ParityErrorHandler(void)
{
/* Add your code here */
return;
}
/**
* @brief Configures the IO speed (BaudRate) communication.
* @param None
* @retval None
*/
void SC_PTSConfig(void)
{
/* Add your code here */
return;
}
/**
* @brief Manages the Smartcard transport layer: send APDU commands and receives
* the APDU response.
* @param SC_ADPU: pointer to a SC_ADPU_Commands structure which will be initialized.
* @param SC_Response: pointer to a SC_ADPU_Response structure which will be initialized.
* @retval None
*/
static void SC_SendData(SC_ADPU_Commands *SCADPU, SC_ADPU_Response *SC_ResponseStatus)
{
uint8_t i;
uint8_t SC_Command[5];
uint8_t SC_DATA[LC_MAX];
UNUSED(SCADPU);
/* Reset response buffer */
for (i = 0U; i < LC_MAX; i++)
{
SC_ResponseStatus->Data[i] = 0U;
SC_DATA[i] = 0U;
}
/* User to add code here */
/* send command to ICC and get response status */
USBD_CCID_If_fops.Send_Process((uint8_t *)&SC_Command, (uint8_t *)&SC_DATA);
}
/**
* @brief SC_AnswerReq
Requests the reset answer from card.
* @param SC_state: pointer to an SC_State enumeration that will contain the Smartcard state.
* @param atr_buffer: pointer to a buffer which will contain the card ATR.
* @param length: maximum ATR length
* @retval None
*/
static void SC_AnswerReq(SC_State *SC_state, uint8_t *atr_buffer, uint8_t length)
{
UNUSED(length);
UNUSED(atr_buffer);
/* to be implemented by USER */
switch (*SC_state)
{
case SC_RESET_LOW:
/* Check response with reset low */
(*SC_state) = SC_ACTIVE;
break;
case SC_ACTIVE:
break;
case SC_RESET_HIGH:
/* Check response with reset high */
break;
case SC_POWER_OFF:
/* Close Connection if no answer received */
break;
default:
(*SC_state) = SC_RESET_LOW;
break;
}
return;
}
/**
* @brief SC_decode_Answer2reset
Decodes the Answer to reset received from card.
* @param card: pointer to the buffer containing the card ATR.
* @retval None
*/
static uint8_t SC_decode_Answer2reset(uint8_t *card)
{
uint32_t i, flag = 0U, protocol;
uint8_t index = 0U, level = 0U;
/******************************TS/T0 Decode************************************/
index++;
SC_A2R.TS = card[index]; /* Initial character */
index++;
SC_A2R.T0 = card[index]; /* Format character */
/*************************Historical Table Length Decode***********************/
SC_A2R.Hlength = SC_A2R.T0 & 0x0FU;
/******************************Protocol Level(1) Decode************************/
/* Check TD(1) if present */
if ((SC_A2R.T0 & 0x80U) == 0x80U)
{
flag = 1U;
}
/* Each bits in the T0 high nibble(b8 to b5) equal to 1 indicates the presence
of a further interface byte */
for (i = 0U; i < 4U; i++)
{
if ((((SC_A2R.T0 & 0xF0U) >> (4U + i)) & 0x1U) != 0U)
{
SC_A2R.T[level].InterfaceByte[i].Status = 1U;
index++;
SC_A2R.T[level].InterfaceByte[i].Value = card[index];
SC_A2R.Tlength++;
}
}
/*****************************T Decode*****************************************/
if (SC_A2R.T[level].InterfaceByte[3].Status == 1U)
{
/* Only the protocol(parameter T) present in TD(1) is detected
if two or more values of parameter T are present in TD(1), TD(2)..., so the
firmware should be updated to support them */
protocol = (uint8_t)(SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0x0FU);
}
else
{
protocol = 0U;
}
/* Protocol Level Increment */
/******************************Protocol Level(n>1) Decode**********************/
while (flag != 0U)
{
if ((SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0x80U) == 0x80U)
{
flag = 1U;
}
else
{
flag = 0U;
}
/* Each bits in the high nibble(b8 to b5) for the TD(i) equal to 1 indicates
the presence of a further interface byte */
for (i = 0U; i < 4U; i++)
{
if ((((SC_A2R.T[level].InterfaceByte[SC_INTERFACEBYTE_TD].Value & 0xF0U) >> (4U + i)) & 0x1U) != 0U)
{
SC_A2R.T[level + 1U].InterfaceByte[i].Status = 1U;
index++;
SC_A2R.T[level + 1U].InterfaceByte[i].Value = card[index];
SC_A2R.Tlength++;
}
}
level++;
}
for (i = 0U; i < SC_A2R.Hlength; i++)
{
SC_A2R.H[i] = card[i + 2U + SC_A2R.Tlength];
}
/*************************************TCK Decode*******************************/
SC_A2R.TCK = card[SC_A2R.Hlength + 2U + SC_A2R.Tlength];
return (uint8_t)protocol;
}
/**
* @brief Initializes all peripheral used for Smartcard interface.
* @param None
* @retval None
*/
static void SC_Init(void)
{
/*
Add your initialization code here
*/
return;
}
/**
* @brief Deinitializes all resources used by the Smartcard interface.
* @param None
* @retval None
*/
static void SC_DeInit(void)
{
/*
Add your deinitialization code here
*/
return;
}
/**
* @brief Configures the card power voltage.
* @param SC_Voltage: specifies the card power voltage.
* This parameter can be one of the following values:
* @arg SC_VOLTAGE_5V: 5V cards.
* @arg SC_VOLTAGE_3V: 3V cards.
* @retval None
*/
void SC_VoltageConfig(uint32_t SC_Voltage)
{
UNUSED(SC_Voltage);
/* Add your code here */
return;
}
/**
* @brief Configures GPIO hardware resources used for Samrtcard.
* @param None
* @retval None
*/
void SC_IOConfig(void)
{
/* Add your code here */
return;
}
/**
* @brief Detects whether the Smartcard is present or not.
* @param None.
* @retval 1 - Smartcard inserted
* 0 - Smartcard not inserted
*/
uint8_t SC_Detect(void)
{
uint8_t PIN_State = 0U;
/* Add your code here */
return PIN_State;
}
/**
* @brief Get the Right Value from the D_Table Index
* @param idx : Index to Read from the Table
* @retval Value read from the Table
*/
uint32_t SC_GetDTableValue(uint32_t idx)
{
return D_Table[idx];
}