📄 smartcard.c
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : smartcard.c
* Author : MCD Application Team
* Version : V1.1.1
* Date : 06/13/2008
* Description : This file provides all the Smartcard firmware functions.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "smartcard.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variables definition and initialization ----------------------------*/
SC_ATR SC_A2R;
static u8 SC_ATR_Table[40];
static vu8 SCData = 0;
static u32 F_Table[16] = {0, 372, 558, 744, 1116, 1488, 1860, 0,
0, 512, 768, 1024, 1536, 2048, 0, 0};
static u32 D_Table[8] = {0, 1, 2, 4, 8, 16, 0, 0};
/* Private function prototypes -----------------------------------------------*/
/* Transport Layer -----------------------------------------------------------*/
/*--------------APDU-----------*/
static void SC_SendData(SC_ADPU_Commands *SC_ADPU, SC_ADPU_Responce *SC_ResponceStatus);
/*------------ ATR ------------*/
static void SC_AnswerReq(SC_State *SCState, u8 *card, u8 length); /* Ask ATR */
static u8 SC_decode_Answer2reset(u8 *card); /* Decode ATR */
/* Physical Port Layer -------------------------------------------------------*/
static void SC_Init(void);
static void SC_DeInit(void);
static void SC_VoltageConfig(u32 SC_Voltage);
static u8 SC_Detect(void);
static ErrorStatus USART_ByteReceive(u8 *Data, u32 TimeOut);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : SC_Handler
* Description : Handles all Smartcard states and serves to send and receive all
* communication data between Smartcard and reader.
* Input : - SCState: pointer to an SC_State enumeration that will contain
* the Smartcard state.
* - SC_ADPU: pointer to an SC_ADPU_Commands structure that will be
* initialized.
* - SC_Response: pointer to a SC_ADPU_Responce structure which will
* be initialized.
* Output : None
* Return : None
*******************************************************************************/
void SC_Handler(SC_State *SCState, SC_ADPU_Commands *SC_ADPU, SC_ADPU_Responce *SC_Response)
{
u32 i = 0;
switch(*SCState)
{
case SC_POWER_ON:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
/* Smartcard intialization ------------------------------------------*/
SC_Init();
/* Reset Data from SC buffer -----------------------------------------*/
for (i = 0; i < 40; i++)
{
SC_ATR_Table[i] = 0;
}
/* Reset SC_A2R Structure --------------------------------------------*/
SC_A2R.TS = 0;
SC_A2R.T0 = 0;
for (i = 0; i < SETUP_LENGTH; i++)
{
SC_A2R.T[i] = 0;
}
for (i = 0; i < HIST_LENGTH; i++)
{
SC_A2R.H[i] = 0;
}
SC_A2R.Tlength = 0;
SC_A2R.Hlength = 0;
/* 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())
{
while(((*SCState) != SC_POWER_OFF) && ((*SCState) != SC_ACTIVE))
{
SC_AnswerReq(SCState, &SC_ATR_Table[0], 40); /* Check for answer to reset */
}
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE:
if (SC_ADPU->Header.INS == SC_GET_A2R)
{
if(SC_decode_Answer2reset(&SC_ATR_Table[0]) == T0_PROTOCOL)
{
(*SCState) = SC_ACTIVE_ON_T0;
}
else
{
(*SCState) = SC_POWER_OFF;
}
}
break;
case SC_ACTIVE_ON_T0:
SC_SendData(SC_ADPU, SC_Response);
break;
case SC_POWER_OFF:
SC_DeInit(); /* Disable Smartcard interface */
break;
default: (*SCState) = SC_POWER_OFF;
}
}
/*******************************************************************************
* Function Name : SC_PowerCmd
* Description : Enables or disables the power to the Smartcard.
* Input : NewState: new state of the Smartcard power supply.
* This parameter can be: ENABLE or DISABLE.
* Output : None
* Return : None
*******************************************************************************/
void SC_PowerCmd(FunctionalState NewState)
{
if(NewState != DISABLE)
{
GPIO_SetBits(GPIO_CMDVCC, SC_CMDVCC);
}
else
{
GPIO_ResetBits(GPIO_CMDVCC, SC_CMDVCC);
}
}
/*******************************************************************************
* Function Name : SC_Reset
* Description : Sets or clears the Smartcard reset pin.
* Input : - ResetState: this parameter specifies the state of the Smartcard
* reset pin.
* BitVal must be one of the BitAction enum values:
* - Bit_RESET: to clear the port pin.
* - Bit_SET: to set the port pin.
* Output : None
* Return : None
*******************************************************************************/
void SC_Reset(BitAction ResetState)
{
GPIO_WriteBit(GPIO_RESET, SC_RESET, ResetState);
}
/*******************************************************************************
* Function Name : SC_ParityErrorHandler
* Description : Resends the byte that failed to be received (by the Smartcard)
* correctly.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SC_ParityErrorHandler(void)
{
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
}
/*******************************************************************************
* Function Name : SC_PTSConfig
* Description : Configures the IO speed (BaudRate) communication.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SC_PTSConfig(void)
{
RCC_ClocksTypeDef RCC_ClocksStatus;
u32 workingbaudrate = 0, apbclock = 0;
u8 locData = 0, PTSConfirmStatus = 1;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
/* Reconfigure the USART Baud Rate -------------------------------------------*/
RCC_GetClocksFreq(&RCC_ClocksStatus);
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
apbclock /= ((USART3->GTPR & (u16)0x00FF) * 2);
/* Enable the DMA Receive (Set DMAR bit only) to enable interrupt generation
in case of a framing error FE */
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
if((SC_A2R.T0 & (u8)0x10) == 0x10)
{
if(SC_A2R.T[0] != 0x11)
{
/* Send PTSS */
SCData = 0xFF;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
/* Send PTS0 */
SCData = 0x10;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
/* Send PTS1 */
SCData = SC_A2R.T[0];
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
/* Send PCK */
SCData = (u8)0xFF^(u8)0x10^(u8)SC_A2R.T[0];
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
/* Disable the DMA Receive (Reset DMAR bit only) */
USART_DMACmd(USART3, USART_DMAReq_Rx, DISABLE);
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
if(locData != 0xFF)
{
PTSConfirmStatus = 0x00;
}
}
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
if(locData != 0x10)
{
PTSConfirmStatus = 0x00;
}
}
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
if(locData != SC_A2R.T[0])
{
PTSConfirmStatus = 0x00;
}
}
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
if(locData != ((u8)0xFF^(u8)0x10^(u8)SC_A2R.T[0]))
{
PTSConfirmStatus = 0x00;
}
}
else
{
PTSConfirmStatus = 0x00;
}
/* PTS Confirm */
if(PTSConfirmStatus == 0x01)
{
workingbaudrate = apbclock * D_Table[(SC_A2R.T[0] & (u8)0x0F)];
workingbaudrate /= F_Table[((SC_A2R.T[0] >> 4) & (u8)0x0F)];
USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Enable;
USART_ClockInit(USART3, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = workingbaudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART3, &USART_InitStructure);
}
}
}
}
/*******************************************************************************
* Function Name : SC_SendData
* Description : Manages the Smartcard transport layer: send APDU commands and
* receives the APDU responce.
* Input : - SC_ADPU: pointer to a SC_ADPU_Commands structure which
* will be initialized.
* - SC_Response: pointer to a SC_ADPU_Responce structure which
* will be initialized.
* Output : None
* Return : None
*******************************************************************************/
static void SC_SendData(SC_ADPU_Commands *SC_ADPU, SC_ADPU_Responce *SC_ResponceStatus)
{
u32 i = 0;
u8 locData = 0;
/* Reset responce buffer ---------------------------------------------------*/
for(i = 0; i < LCmax; i++)
{
SC_ResponceStatus->Data[i] = 0;
}
SC_ResponceStatus->SW1 = 0;
SC_ResponceStatus->SW2 = 0;
/* Enable the DMA Receive (Set DMAR bit only) to enable interrupt generation
in case of a framing error FE */
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
/* Send header -------------------------------------------------------------*/
SCData = SC_ADPU->Header.CLA;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
SCData = SC_ADPU->Header.INS;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
SCData = SC_ADPU->Header.P1;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
SCData = SC_ADPU->Header.P2;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
/* Send body length to/from SC ---------------------------------------------*/
if(SC_ADPU->Body.LC)
{
SCData = SC_ADPU->Body.LC;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
}
else if(SC_ADPU->Body.LE)
{
SCData = SC_ADPU->Body.LE;
USART_SendData(USART3, SCData);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{
}
}
/* Flush the USART3 DR */
(void)USART_ReceiveData(USART3);
/* --------------------------------------------------------
Wait Procedure byte from card:
1 - ACK
2 - NULL
3 - SW1; SW2
-------------------------------------------------------- */
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
if(((locData & (u8)0xF0) == 0x60) || ((locData & (u8)0xF0) == 0x90))
{
/* SW1 received */
SC_ResponceStatus->SW1 = locData;
if((USART_ByteReceive(&locData, SC_Receive_Timeout)) == SUCCESS)
{
/* SW2 received */
SC_ResponceStatus->SW2 = locData;
}
}
else if (((locData & (u8)0xFE) == (((u8)~(SC_ADPU->Header.INS)) & (u8)0xFE))||((locData & (u8)0xFE) == (SC_ADPU->Header.INS & (u8)0xFE)))
{
SC_ResponceStatus->Data[0] = locData;/* ACK received */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -