678 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			678 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
/**
 | 
						|
  ******************************************************************************
 | 
						|
  * @file    SMARTCARD_T0/Src/smartcard.c
 | 
						|
  * @author  MCD Application Team
 | 
						|
  * @brief   This file provides all the Smartcard firmware functions.
 | 
						|
  ******************************************************************************
 | 
						|
  * @attention
 | 
						|
  *
 | 
						|
  * <h2><center>© Copyright (c) 2016 STMicroelectronics.
 | 
						|
  * All rights reserved.</center></h2>
 | 
						|
  *
 | 
						|
  * This software component is licensed by ST under BSD 3-Clause license,
 | 
						|
  * the "License"; You may not use this file except in compliance with the
 | 
						|
  * License. You may obtain a copy of the License at:
 | 
						|
  *                        opensource.org/licenses/BSD-3-Clause
 | 
						|
  *
 | 
						|
  ******************************************************************************
 | 
						|
  */
 | 
						|
 | 
						|
/** @addtogroup STM32F1xx_HAL_Examples
 | 
						|
  * @{
 | 
						|
  */
 | 
						|
 | 
						|
/** @addtogroup SMARTCARD_T0
 | 
						|
  * @{
 | 
						|
  */
 | 
						|
 | 
						|
/* Includes ------------------------------------------------------------------*/
 | 
						|
#include "smartcard.h"
 | 
						|
 | 
						|
/* Private typedef -----------------------------------------------------------*/
 | 
						|
/* Private define ------------------------------------------------------------*/
 | 
						|
/* Private macro -------------------------------------------------------------*/
 | 
						|
/* Private variables ---------------------------------------------------------*/
 | 
						|
/* Global variables definition and initialization ----------------------------*/
 | 
						|
SC_ATR SC_A2R;
 | 
						|
uint8_t SC_ATR_Table[40] = {0};
 | 
						|
static __IO uint8_t SCData = 0;
 | 
						|
static uint32_t F_Table[16] = {372, 372, 558, 744, 1116, 1488, 1860, 0,
 | 
						|
                               0, 512, 768, 1024, 1536, 2048, 0, 0};
 | 
						|
static uint32_t D_Table[16] = {0, 1, 2, 4, 8, 16, 32, 0, 12, 20, 0, 0, 0, 0, 0, 0};
 | 
						|
SMARTCARD_HandleTypeDef SCHandle;
 | 
						|
 | 
						|
/* Private function prototypes -----------------------------------------------*/
 | 
						|
/* Transport Layer -----------------------------------------------------------*/
 | 
						|
/*--------------APDU-----------*/
 | 
						|
void SC_SendData(SC_ADPU_Commands *SC_ADPU, SC_ADPU_Response *SC_ResponseStatus);
 | 
						|
 | 
						|
/*------------ ATR ------------*/
 | 
						|
static void SC_AnswerReq(SC_State *SCState, uint8_t *card, uint8_t length);  /* Ask ATR */
 | 
						|
static uint8_t SC_decode_Answer2reset(uint8_t *card);  /* Decode ATR */
 | 
						|
 | 
						|
/* Physical Port Layer -------------------------------------------------------*/
 | 
						|
static void SC_Init(void);
 | 
						|
static void SC_DeInit(void);
 | 
						|
static void SC_VoltageConfig(uint32_t SC_Voltage);
 | 
						|
static uint8_t SC_Detect(void);
 | 
						|
 | 
						|
/* 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 = 0;
 | 
						|
  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 = 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, (uint8_t *)&SC_ATR_Table, 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;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Enables or disables the power to the Smartcard.
 | 
						|
  * @param  NewState: new state of the Smartcard power supply.
 | 
						|
  *         This parameter can be: ENABLE or DISABLE.
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_PowerCmd(FunctionalState NewState)
 | 
						|
{
 | 
						|
  if(NewState != DISABLE)
 | 
						|
  {
 | 
						|
    HAL_GPIO_WritePin(SC_CMDVCC_GPIO_PORT, SC_CMDVCC_PIN, GPIO_PIN_RESET);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    HAL_GPIO_WritePin(SC_CMDVCC_GPIO_PORT, SC_CMDVCC_PIN, GPIO_PIN_SET);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @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 GPIO_PinState enum values:
 | 
						|
  *                 @arg GPIO_PIN_RESET: to clear the port pin.
 | 
						|
  *                 @arg GPIO_PIN_SET: to set the port pin.
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_Reset(GPIO_PinState ResetState)
 | 
						|
{
 | 
						|
  HAL_GPIO_WritePin(SC_RESET_GPIO_PORT, SC_RESET_PIN, ResetState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Resends the byte that failed to be received (by the Smartcard) correctly.
 | 
						|
  * @param  None
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_ParityErrorHandler(void)
 | 
						|
{
 | 
						|
  HAL_SMARTCARD_Transmit(&SCHandle, (uint8_t *)&SCData, 1, SC_TRANSMIT_TIMEOUT);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Configures the IO speed (BaudRate) communication.
 | 
						|
  * @param  None
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_PTSConfig(void)
 | 
						|
{
 | 
						|
  uint32_t workingbaudrate = 0, apbclock = 0;
 | 
						|
  uint8_t PPSConfirmStatus = 1;
 | 
						|
  uint8_t ptscmd[4] = {0x00};
 | 
						|
  uint8_t ptsanswer[4] = {0x00};
 | 
						|
 | 
						|
  /* Reconfigure the USART Baud Rate -----------------------------------------*/
 | 
						|
  apbclock = HAL_RCC_GetPCLK1Freq();
 | 
						|
  apbclock /= ((SC_USART->GTPR & (uint16_t)0x00FF) * 2);
 | 
						|
 | 
						|
  /* Enable the DMA Receive (Set DMAR bit only) to enable interrupt generation
 | 
						|
  in case of a framing error FE */
 | 
						|
  __HAL_SMARTCARD_DMA_REQUEST_ENABLE(&SCHandle, SMARTCARD_DMAREQ_RX);
 | 
						|
 | 
						|
  if((SC_A2R.T0 & (uint8_t)0x10) == 0x10)
 | 
						|
  {
 | 
						|
    if(SC_A2R.T[0] != 0x11)
 | 
						|
    {
 | 
						|
      /* PPSS identifies the PPS request or response and is equal to 0xFF */
 | 
						|
      ptscmd[0] = 0xFF;
 | 
						|
 | 
						|
      /* PPS0 indicates by the bits b5, b6, b7 equal to 1 the presence of the optional
 | 
						|
      bytes PPSI1, PPS2, PPS3 respectively */
 | 
						|
      ptscmd[1] = 0x10;
 | 
						|
 | 
						|
      /* PPS1 allows the interface device to propose value of F and D to the card */
 | 
						|
      ptscmd[2] = SC_A2R.T[0];
 | 
						|
 | 
						|
      /* PCK check character */
 | 
						|
      ptscmd[3] = (uint8_t)0xFF^(uint8_t)0x10^(uint8_t)SC_A2R.T[0];
 | 
						|
 | 
						|
      /* Start the receive IT process: to receive the command answer from the card */
 | 
						|
      HAL_SMARTCARD_Receive_IT(&SCHandle, (uint8_t *)ptsanswer, 4);
 | 
						|
 | 
						|
      /* Send command */
 | 
						|
      HAL_SMARTCARD_Transmit(&SCHandle, (uint8_t *)ptscmd, 4, SC_TRANSMIT_TIMEOUT);
 | 
						|
 | 
						|
      /* Disable the DMA Receive Request */
 | 
						|
      __HAL_SMARTCARD_DMA_REQUEST_DISABLE(&SCHandle, SMARTCARD_DMAREQ_RX);
 | 
						|
 | 
						|
      /* Wait until receiving the answer from the card */
 | 
						|
      while(HAL_SMARTCARD_GetState(&SCHandle) != HAL_SMARTCARD_STATE_READY)
 | 
						|
      {}
 | 
						|
 | 
						|
      /* Check the received command answer */
 | 
						|
      if((ptsanswer[0] != 0xFF) || (ptsanswer[1] != 0x10) || (ptsanswer[2] != SC_A2R.T[0]) || (ptsanswer[3] != ((uint8_t)0xFF^(uint8_t)0x10^(uint8_t)SC_A2R.T[0])))
 | 
						|
      {
 | 
						|
        /* PPSS, PPS0, PPS1 and PCK exchange unsuccessful */
 | 
						|
        PPSConfirmStatus = 0x00;
 | 
						|
      }
 | 
						|
 | 
						|
      /* PPS exchange successful */
 | 
						|
      if(PPSConfirmStatus == 0x01)
 | 
						|
      {
 | 
						|
        workingbaudrate = apbclock * D_Table[(SC_A2R.T[0] & (uint8_t)0x0F)];
 | 
						|
        workingbaudrate /= F_Table[((SC_A2R.T[0] >> 4) & (uint8_t)0x0F)];
 | 
						|
 | 
						|
        SCHandle.Init.BaudRate = workingbaudrate;
 | 
						|
        SCHandle.Init.WordLength = SMARTCARD_WORDLENGTH_9B;
 | 
						|
        SCHandle.Init.StopBits = SMARTCARD_STOPBITS_1_5;
 | 
						|
        SCHandle.Init.Parity = SMARTCARD_PARITY_EVEN;
 | 
						|
        SCHandle.Init.Mode = SMARTCARD_MODE_TX_RX;
 | 
						|
        SCHandle.Init.CLKPolarity = SMARTCARD_POLARITY_LOW;
 | 
						|
        SCHandle.Init.CLKPhase = SMARTCARD_PHASE_1EDGE;
 | 
						|
        SCHandle.Init.CLKLastBit = SMARTCARD_LASTBIT_ENABLE;
 | 
						|
        SCHandle.Init.Prescaler = SMARTCARD_PRESCALER_SYSCLK_DIV10;
 | 
						|
        SCHandle.Init.GuardTime = 16;
 | 
						|
        SCHandle.Init.NACKState = SMARTCARD_NACK_ENABLE;
 | 
						|
        SCHandle.Instance = SC_USART;
 | 
						|
 | 
						|
        if(HAL_SMARTCARD_Init(&SCHandle) != HAL_OK)
 | 
						|
        {
 | 
						|
          while (1);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @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_ADPU_Response: pointer to a SC_ADPU_Response structure which will be initialized.
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_SendData(SC_ADPU_Commands *SC_ADPU, SC_ADPU_Response *SC_ResponseStatus)
 | 
						|
{
 | 
						|
  uint32_t i = 0;
 | 
						|
 | 
						|
  uint8_t command[5] = {0x00};
 | 
						|
  uint8_t answer[40] = {0x00};
 | 
						|
 | 
						|
  /* Reset response buffer ---------------------------------------------------*/
 | 
						|
  for(i = 0; i < LC_MAX; i++)
 | 
						|
  {
 | 
						|
    SC_ResponseStatus->Data[i] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  SC_ResponseStatus->SW1 = 0;
 | 
						|
  SC_ResponseStatus->SW2 = 0;
 | 
						|
 | 
						|
  /* Enable the DMA Receive (Set DMAR bit only) to enable interrupt generation
 | 
						|
     in case of a framing error FE */
 | 
						|
  __HAL_SMARTCARD_DMA_REQUEST_ENABLE(&SCHandle, SMARTCARD_DMAREQ_RX);
 | 
						|
 | 
						|
  /* Send header -------------------------------------------------------------*/
 | 
						|
  command[0] = SC_ADPU->Header.CLA;
 | 
						|
  command[1] = SC_ADPU->Header.INS;
 | 
						|
  command[2] = SC_ADPU->Header.P1;
 | 
						|
  command[3] = SC_ADPU->Header.P2;
 | 
						|
 | 
						|
  /* Send body length to/from SC ---------------------------------------------*/
 | 
						|
  if(SC_ADPU->Body.LC)
 | 
						|
  {
 | 
						|
    command[4] = SC_ADPU->Body.LC;
 | 
						|
    HAL_SMARTCARD_Transmit(&SCHandle, (uint8_t *)command, 5, SC_TRANSMIT_TIMEOUT);
 | 
						|
  }
 | 
						|
  else if(SC_ADPU->Body.LE)
 | 
						|
  {
 | 
						|
    command[4] = SC_ADPU->Body.LE;
 | 
						|
    HAL_SMARTCARD_Transmit(&SCHandle, (uint8_t *)command, 5, SC_TRANSMIT_TIMEOUT);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Flush the SC_USART DR */
 | 
						|
  __HAL_SMARTCARD_FLUSH_DRREGISTER(&SCHandle);
 | 
						|
 | 
						|
  /* Start the receive IT process: to receive the command answer from the card */
 | 
						|
  HAL_SMARTCARD_Receive_IT(&SCHandle, (uint8_t *)&answer[0], 1);
 | 
						|
 | 
						|
  /* Wait until receiving the answer from the card */
 | 
						|
  while(HAL_SMARTCARD_GetState(&SCHandle) != HAL_SMARTCARD_STATE_READY)
 | 
						|
  {}
 | 
						|
 | 
						|
  /* --------------------------------------------------------
 | 
						|
    Wait Procedure byte from card:
 | 
						|
    1 - ACK
 | 
						|
    2 - NULL
 | 
						|
    3 - SW1; SW2
 | 
						|
  -------------------------------------------------------- */
 | 
						|
  if(((answer[0] & (uint8_t)0xF0) == 0x60) || ((answer[0] & (uint8_t)0xF0) == 0x90))
 | 
						|
  {
 | 
						|
    /* SW1 received */
 | 
						|
    SC_ResponseStatus->SW1 = answer[0];
 | 
						|
 | 
						|
    if(HAL_SMARTCARD_Receive_IT(&SCHandle, (uint8_t *)&answer[1], 1) == HAL_OK)
 | 
						|
    {
 | 
						|
      /* SW2 received */
 | 
						|
      SC_ResponseStatus->SW2 = answer[1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else if(((answer[0] & (uint8_t)0xFE) == (((uint8_t)~(SC_ADPU->Header.INS)) & (uint8_t)0xFE)) || \
 | 
						|
    ((answer[0] & (uint8_t)0xFE) == (SC_ADPU->Header.INS & (uint8_t)0xFE)))
 | 
						|
  {
 | 
						|
    SC_ResponseStatus->Data[0] = answer[0];/* ACK received */
 | 
						|
  }
 | 
						|
 | 
						|
  /* If no status bytes received ---------------------------------------------*/
 | 
						|
  if(SC_ResponseStatus->SW1 == 0x00)
 | 
						|
  {
 | 
						|
    /* Send body data to SC --------------------------------------------------*/
 | 
						|
    if(SC_ADPU->Body.LC)
 | 
						|
    {
 | 
						|
      /* Send body data */
 | 
						|
      HAL_SMARTCARD_Transmit(&SCHandle, (uint8_t *)&SC_ADPU->Body.Data[0], SC_ADPU->Body.LC, SC_TRANSMIT_TIMEOUT);
 | 
						|
 | 
						|
      /* Flush the SC_USART DR */
 | 
						|
      __HAL_SMARTCARD_FLUSH_DRREGISTER(&SCHandle);
 | 
						|
 | 
						|
      /* Disable the DMA Receive (Reset DMAR bit only) */
 | 
						|
      __HAL_SMARTCARD_DMA_REQUEST_DISABLE(&SCHandle, SMARTCARD_DMAREQ_RX);
 | 
						|
 | 
						|
      /* Start the receive IT process: to receive the command answer from the card */
 | 
						|
      HAL_SMARTCARD_Receive_IT(&SCHandle, (uint8_t *)&answer[0], 2);
 | 
						|
 | 
						|
      /* Wait until receiving the answer from the card */
 | 
						|
      while(HAL_SMARTCARD_GetState(&SCHandle) != HAL_SMARTCARD_STATE_READY)
 | 
						|
      {}
 | 
						|
 | 
						|
      /* Decode the SW1 */
 | 
						|
      SC_ResponseStatus->SW1 = answer[0];
 | 
						|
 | 
						|
      /* Decode the SW2 */
 | 
						|
      SC_ResponseStatus->SW2 = answer[1];
 | 
						|
    }
 | 
						|
 | 
						|
    /* Or receive body data from SC ------------------------------------------*/
 | 
						|
    else if(SC_ADPU->Body.LE)
 | 
						|
    {
 | 
						|
      /* Start the receive IT process: to receive the command answer from the card */
 | 
						|
      HAL_SMARTCARD_Receive_IT(&SCHandle, (uint8_t *)&answer[0], (SC_ADPU->Body.LE +2));
 | 
						|
 | 
						|
      /* Wait until receiving the answer from the card */
 | 
						|
      while(HAL_SMARTCARD_GetState(&SCHandle) != HAL_SMARTCARD_STATE_READY)
 | 
						|
      {}
 | 
						|
 | 
						|
      /* Decode the body data */
 | 
						|
      for(i = 0; i < SC_ADPU->Body.LE; i++)
 | 
						|
      {
 | 
						|
        SC_ResponseStatus->Data[i] = answer[i];
 | 
						|
      }
 | 
						|
 | 
						|
      /* Decode the SW1 */
 | 
						|
      SC_ResponseStatus->SW1 = answer[SC_ADPU->Body.LE];
 | 
						|
 | 
						|
      /* Decode the SW2 */
 | 
						|
      SC_ResponseStatus->SW2 = answer[SC_ADPU->Body.LE +1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Requests the reset answer from card.
 | 
						|
  * @param  SCState: pointer to an SC_State enumeration that will contain the Smartcard state.
 | 
						|
  * @param  card: pointer to a buffer which will contain the card ATR.
 | 
						|
  * @param  length: maximum ATR length
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
static void SC_AnswerReq(SC_State *SCState, uint8_t *card, uint8_t length)
 | 
						|
{
 | 
						|
  switch(*SCState)
 | 
						|
  {
 | 
						|
  case SC_RESET_LOW:
 | 
						|
    /* Check response with reset low -----------------------------------------*/
 | 
						|
    HAL_SMARTCARD_Receive(&SCHandle, card, length, SC_RECEIVE_TIMEOUT);
 | 
						|
 | 
						|
    if(card[0] != 0x00)
 | 
						|
    {
 | 
						|
      (*SCState) = SC_ACTIVE;
 | 
						|
      SC_Reset(GPIO_PIN_SET);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      (*SCState) = SC_RESET_HIGH;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case SC_RESET_HIGH:
 | 
						|
    /* Check response with reset high ----------------------------------------*/
 | 
						|
    SC_Reset(GPIO_PIN_SET); /* Reset High */
 | 
						|
    HAL_SMARTCARD_Receive(&SCHandle, card, length, SC_RECEIVE_TIMEOUT);
 | 
						|
 | 
						|
    if(card[0])
 | 
						|
    {
 | 
						|
      (*SCState) = SC_ACTIVE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      (*SCState) = SC_POWER_OFF;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case SC_ACTIVE:
 | 
						|
    break;
 | 
						|
 | 
						|
  case SC_POWER_OFF:
 | 
						|
    /* Close Connection if no answer received --------------------------------*/
 | 
						|
    SC_Reset(GPIO_PIN_SET); /* Reset high - a bit is used as level shifter from 3.3 to 5 V */
 | 
						|
    SC_PowerCmd(DISABLE);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    (*SCState) = SC_RESET_LOW;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Decodes the Answer to reset received from card.
 | 
						|
  * @param  card: pointer to the buffer containing the card ATR.
 | 
						|
  * @retval Smartcard communication Protocol
 | 
						|
  */
 | 
						|
static uint8_t SC_decode_Answer2reset(uint8_t *card)
 | 
						|
{
 | 
						|
 uint32_t i = 0, flag = 0, buf = 0, protocol = 0;
 | 
						|
 | 
						|
  SC_A2R.TS = card[0];  /* Initial character */
 | 
						|
  SC_A2R.T0 = card[1];  /* Format character */
 | 
						|
 | 
						|
  SC_A2R.Hlength = SC_A2R.T0 & (uint8_t)0x0F;
 | 
						|
 | 
						|
  if ((SC_A2R.T0 & (uint8_t)0x80) == 0x80)
 | 
						|
  {
 | 
						|
    flag = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = 0; i < 4; i++)
 | 
						|
  {
 | 
						|
    SC_A2R.Tlength = SC_A2R.Tlength + (((SC_A2R.T0 & (uint8_t)0xF0) >> (4 + i)) & (uint8_t)0x1);
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = 0; i < SC_A2R.Tlength; i++)
 | 
						|
  {
 | 
						|
    SC_A2R.T[i] = card[i + 2];
 | 
						|
  }
 | 
						|
 | 
						|
  if ((SC_A2R.T0 & (uint8_t)0x80) == 0x00)
 | 
						|
  {
 | 
						|
    protocol = 0;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    protocol = SC_A2R.T[SC_A2R.Tlength - 1] & (uint8_t)0x0F;
 | 
						|
  }
 | 
						|
 | 
						|
  while (flag)
 | 
						|
  {
 | 
						|
    if ((SC_A2R.T[SC_A2R.Tlength - 1] & (uint8_t)0x80) == 0x80)
 | 
						|
    {
 | 
						|
      flag = 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      flag = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    buf = SC_A2R.Tlength;
 | 
						|
    SC_A2R.Tlength = 0;
 | 
						|
 | 
						|
    for (i = 0; i < 4; i++)
 | 
						|
    {
 | 
						|
      SC_A2R.Tlength = SC_A2R.Tlength + (((SC_A2R.T[buf - 1] & (uint8_t)0xF0) >> (4 + i)) & (uint8_t)0x1);
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0;i < SC_A2R.Tlength; i++)
 | 
						|
    {
 | 
						|
      SC_A2R.T[buf + i] = card[i + 2 + buf];
 | 
						|
    }
 | 
						|
    SC_A2R.Tlength += (uint8_t)buf;
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = 0; i < SC_A2R.Hlength; i++)
 | 
						|
  {
 | 
						|
    SC_A2R.H[i] = card[i + 2 + SC_A2R.Tlength];
 | 
						|
  }
 | 
						|
 | 
						|
  return (uint8_t)protocol;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Initializes all peripheral used for Smartcard interface.
 | 
						|
  * @param  None
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
static void SC_Init(void)
 | 
						|
{
 | 
						|
  /* SC_USART configuration --------------------------------------------------*/
 | 
						|
  /* SC_USART configured as follows:
 | 
						|
  - Word Length = 9 Bits
 | 
						|
  - 1.5 Stop Bit
 | 
						|
  - Even parity
 | 
						|
  - BaudRate = 8064 baud
 | 
						|
  - Hardware flow control disabled (RTS and CTS signals)
 | 
						|
  - Tx and Rx enabled
 | 
						|
  - USART Clock enabled
 | 
						|
  */
 | 
						|
  /* USART Clock set to 3 MHz (PCLK1 (36 MHz) / 12) => prescaler set to 0x06 */
 | 
						|
  SCHandle.Instance = SC_USART;
 | 
						|
  SCHandle.Init.BaudRate = 9408;  /* Starting baudrate = 3MHz / 372etu */
 | 
						|
  SCHandle.Init.WordLength = SMARTCARD_WORDLENGTH_9B;
 | 
						|
  SCHandle.Init.StopBits = SMARTCARD_STOPBITS_1_5;
 | 
						|
  SCHandle.Init.Parity = SMARTCARD_PARITY_EVEN;
 | 
						|
  SCHandle.Init.Mode = SMARTCARD_MODE_TX_RX;
 | 
						|
  SCHandle.Init.CLKPolarity = SMARTCARD_POLARITY_LOW;
 | 
						|
  SCHandle.Init.CLKPhase = SMARTCARD_PHASE_1EDGE;
 | 
						|
  SCHandle.Init.CLKLastBit = SMARTCARD_LASTBIT_ENABLE;
 | 
						|
  SCHandle.Init.Prescaler = SMARTCARD_PRESCALER_SYSCLK_DIV10;
 | 
						|
  SCHandle.Init.GuardTime = 16;
 | 
						|
  SCHandle.Init.NACKState = SMARTCARD_NACK_ENABLE;
 | 
						|
  HAL_SMARTCARD_Init(&SCHandle);
 | 
						|
 | 
						|
  /* Set RSTIN HIGH */
 | 
						|
  SC_Reset(GPIO_PIN_SET);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Deinitializes all resources used by the Smartcard interface.
 | 
						|
  * @param  None
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
static void SC_DeInit(void)
 | 
						|
{
 | 
						|
  /* Disable CMDVCC */
 | 
						|
  SC_PowerCmd(DISABLE);
 | 
						|
 | 
						|
  /* Deinitializes the SCHandle */
 | 
						|
  HAL_SMARTCARD_DeInit(&SCHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @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
 | 
						|
  */
 | 
						|
static void SC_VoltageConfig(uint32_t SC_Voltage)
 | 
						|
{
 | 
						|
  if(SC_Voltage == SC_VOLTAGE_5V)
 | 
						|
  {
 | 
						|
    /* Select Smartcard 5V */
 | 
						|
    HAL_GPIO_WritePin(SC_3_5V_GPIO_PORT, SC_3_5V_PIN, GPIO_PIN_SET);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    /* Select Smartcard 3V */
 | 
						|
    HAL_GPIO_WritePin(SC_3_5V_GPIO_PORT, SC_3_5V_PIN, GPIO_PIN_RESET);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Configures GPIO hardware resources used for Samrtcard.
 | 
						|
  * @param  None
 | 
						|
  * @retval None
 | 
						|
  */
 | 
						|
void SC_IOConfig(void)
 | 
						|
{
 | 
						|
  GPIO_InitTypeDef  GPIO_InitStruct;
 | 
						|
 | 
						|
  /* Enable GPIO clocks */
 | 
						|
  SC_3_5V_CLK_ENABLE();
 | 
						|
  SC_RESET_CLK_ENABLE();
 | 
						|
  SC_CMDVCC_CLK_ENABLE();
 | 
						|
  SC_OFF_CLK_ENABLE();
 | 
						|
 | 
						|
  /* Configure Smartcard CMDVCC pin */
 | 
						|
  GPIO_InitStruct.Pin = SC_CMDVCC_PIN;
 | 
						|
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 | 
						|
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 | 
						|
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 | 
						|
  HAL_GPIO_Init(SC_CMDVCC_GPIO_PORT, &GPIO_InitStruct);
 | 
						|
 | 
						|
  /* Configure Smartcard Reset pin */
 | 
						|
  GPIO_InitStruct.Pin = SC_RESET_PIN;
 | 
						|
  HAL_GPIO_Init(SC_RESET_GPIO_PORT, &GPIO_InitStruct);
 | 
						|
 | 
						|
  /* Configure Smartcard 3/5V pin */
 | 
						|
  GPIO_InitStruct.Pin = SC_3_5V_PIN;
 | 
						|
  HAL_GPIO_Init(SC_3_5V_GPIO_PORT, &GPIO_InitStruct);
 | 
						|
 | 
						|
  /* Select 5V */
 | 
						|
  SC_VoltageConfig(SC_VOLTAGE_5V);
 | 
						|
 | 
						|
  /* Disable CMDVCC */
 | 
						|
  SC_PowerCmd(DISABLE);
 | 
						|
 | 
						|
  /* Set RSTIN HIGH */
 | 
						|
  SC_Reset(GPIO_PIN_SET);
 | 
						|
 | 
						|
  /* Configure Smartcard OFF pin */
 | 
						|
  GPIO_InitStruct.Pin = SC_OFF_PIN;
 | 
						|
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
 | 
						|
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 | 
						|
  HAL_GPIO_Init(SC_OFF_GPIO_PORT, &GPIO_InitStruct);
 | 
						|
 | 
						|
  /* Configure the NVIC for Smartcard OFF pin */
 | 
						|
  HAL_NVIC_SetPriority(SC_OFF_EXTI_IRQn, 0, 0);
 | 
						|
  HAL_NVIC_EnableIRQ(SC_OFF_EXTI_IRQn);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @brief  Detects whether the Smartcard is present or not.
 | 
						|
  * @param  None.
 | 
						|
  * @retval 0 - Smartcard inserted
 | 
						|
  *         1 - Smartcard not inserted
 | 
						|
  */
 | 
						|
static uint8_t SC_Detect(void)
 | 
						|
{
 | 
						|
  return HAL_GPIO_ReadPin(SC_OFF_GPIO_PORT, SC_OFF_PIN);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  * @}
 | 
						|
  */
 | 
						|
 | 
						|
/**
 | 
						|
  * @}
 | 
						|
  */
 | 
						|
 | 
						|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
 |