mirror of
https://github.com/STMicroelectronics/stm32-mw-usb-device.git
synced 2026-02-08 20:18:07 -05:00
Release v2.9.0
This commit is contained in:
473
Class/CCID/Src/usbd_ccid_sc_if_template.c
Normal file
473
Class/CCID/Src/usbd_ccid_sc_if_template.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user