发新帖我要提问
12
返回列表
打印
[STM32F1]

三问读取SIM卡的问题

[复制链接]
楼主: JY-DX-JY
手机看帖
扫描二维码
随时随地手机跟帖
21
sinshine| | 2015-6-12 11:16 | 只看该作者 回帖奖励 |倒序浏览
JY-DX-JY 发表于 2015-6-12 10:52
我现在试了CLA从00-07,80都不支持。A0,提示域长度错误。

LZ应该好好看看7816-3的协议
老SIM卡都是ICC的,CLA都是A0。LZ只发了C0 apdu,肯定得不到正确的回复。这个是当卡回9Fxx或者6Cxx后,才能发的。
按照前文的ATR,解析是这样的
TS   - 3B
T0   - 1A (只有TA1,10个history byte)
TA1 - 11  DI/FI
剩下的都是history byte。TD1不存在,则T0。

LZ的ATR解析有问题的,对照7816好好看一下,没有判断TD是否存在就得出了T1。
还有SC_A2R.T = card[i + 2]; 有问题的

使用特权

评论回复
22
sinshine| | 2015-6-12 11:23 | 只看该作者
sinshine 发表于 2015-6-12 11:16
LZ应该好好看看7816-3的协议
老SIM卡都是ICC的,CLA都是A0。LZ只发了C0 apdu,肯定得不到正确的回复。这 ...

差不多这个样子,当然ATR解析还是有点复杂的
if (flag == 1)
protocol = SC_A2R.T[SC_A2R.Tlength - 1] & (uint8_t)0x0F;  
else
protocol = 0x00;

使用特权

评论回复
23
JY-DX-JY|  楼主 | 2015-6-12 11:57 | 只看该作者
sinshine 发表于 2015-6-12 11:16
LZ应该好好看看7816-3的协议
老SIM卡都是ICC的,CLA都是A0。LZ只发了C0 apdu,肯定得不到正确的回复。这 ...

谢谢!
我参考的stsw-stm32011官网固件库。
/**
  * @brief  Manages the Smartcard transport layer: send APDU commands and receives
  *   the APDU responce.
  * @param  SC_ADPU: pointer to a SC_ADPU_Commands structure which will be initialized.
  * @param  SC_Response: pointer to a SC_ADPU_Responce structure which will be initialized.
  * @retval None
  */
static void SC_SendData(SC_ADPU_Commands *SC_ADPU, SC_ADPU_Responce *SC_ResponceStatus)
{
  uint32_t i = 0;
  uint8_t locData = 0;
  /* Reset responce buffer ---------------------------------------------------*/
  for(i = 0; i < LC_MAX; i++)
  {
    SC_ResponceStatus->Data = 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(SC_USART, USART_DMAReq_Rx, ENABLE);
  /* Send header -------------------------------------------------------------*/
  SCData = SC_ADPU->Header.CLA;
  USART_SendData(SC_USART, SCData);
  while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
  {
  }
  SCData = SC_ADPU->Header.INS;
  USART_SendData(SC_USART, SCData);
  while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
  {
  }
  SCData = SC_ADPU->Header.P1;
  USART_SendData(SC_USART, SCData);
  while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
  {
  }
  SCData = SC_ADPU->Header.P2;
  USART_SendData(SC_USART, SCData);
  while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
  {
  }
  /* Send body length to/from SC ---------------------------------------------*/
  if(SC_ADPU->Body.LC)
  {
    SCData = SC_ADPU->Body.LC;
    USART_SendData(SC_USART, SCData);
    while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
    {
    }
  }
  else if(SC_ADPU->Body.LE)
  {
    SCData = SC_ADPU->Body.LE;
    USART_SendData(SC_USART, SCData);
    while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
    {
    }
  }
  /* Flush the SC_USART DR */
  (void)USART_ReceiveData(SC_USART);
  /* --------------------------------------------------------
    Wait Procedure byte from card:
    1 - ACK
    2 - NULL
    3 - SW1; SW2
   -------------------------------------------------------- */
  if((USART_ByteReceive(&locData, SC_RECEIVE_TIMEOUT)) == SUCCESS)
  {
    if(((locData & (uint8_t)0xF0) == 0x60) || ((locData & (uint8_t)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 & (uint8_t)0xFE) == (((uint8_t)~(SC_ADPU->Header.INS)) & \
             (uint8_t)0xFE))||((locData & (uint8_t)0xFE) == (SC_ADPU->Header.INS & (uint8_t)0xFE)))
    {
      SC_ResponceStatus->Data[0] = locData;/* ACK received */
    }
  }
  /* If no status bytes received ---------------------------------------------*/
  if(SC_ResponceStatus->SW1 == 0x00)
  {
    /* Send body data to SC--------------------------------------------------*/
    if (SC_ADPU->Body.LC)
    {
      for(i = 0; i < SC_ADPU->Body.LC; i++)
      {
        SCData = SC_ADPU->Body.Data;
        USART_SendData(SC_USART, SCData);
        while(USART_GetFlagStatus(SC_USART, USART_FLAG_TC) == RESET)
        {
        }
      }
      /* Flush the SC_USART DR */
      (void)USART_ReceiveData(SC_USART);
      /* Disable the DMA Receive (Reset DMAR bit only) */
      USART_DMACmd(SC_USART, USART_DMAReq_Rx, DISABLE);
    }
    /* Or receive body data from SC ------------------------------------------*/
    else if (SC_ADPU->Body.LE)
    {
      for(i = 0; i < SC_ADPU->Body.LE; i++)
      {
        if(USART_ByteReceive(&locData, SC_RECEIVE_TIMEOUT) == SUCCESS)
        {
          SC_ResponceStatus->Data = locData;
        }
      }
    }
    /* Wait SW1 --------------------------------------------------------------*/
    i = 0;
    while(i < 10)
    {
      if(USART_ByteReceive(&locData, SC_RECEIVE_TIMEOUT) == SUCCESS)
      {
        SC_ResponceStatus->SW1 = locData;
        i = 11;
      }
      else
      {
        i++;
      }
    }
    /* Wait SW2 ------------------------------------------------------------*/
    i = 0;
    while(i < 10)
    {
      if(USART_ByteReceive(&locData, SC_RECEIVE_TIMEOUT) == SUCCESS)
      {
        SC_ResponceStatus->SW2 = locData;
        i = 11;
      }
      else
      {
        i++;
      }
    }
  }
}
是先发了APDU又判断接收9F和6C的,难道库是错的吗?

使用特权

评论回复
24
JY-DX-JY|  楼主 | 2015-6-12 11:59 | 只看该作者
本帖最后由 JY-DX-JY 于 2015-6-12 12:04 编辑
sinshine 发表于 2015-6-12 11:23
差不多这个样子,当然ATR解析还是有点复杂的
if (flag == 1)
protocol = SC_A2R.T[SC_A2R.Tlength - 1] & ...

谢谢!
库里的解码是这样的:
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 = card[i + 2];                                               //这个地方有什么问题?
  }

  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 = card[i + 2 + SC_A2R.Tlength];
  }

  return (uint8_t)protocol;
}

我主要是觉得库不太可能错,想借鉴。自己从头写比较费劲。请多指教吧,再次感谢!

使用特权

评论回复
25
sinshine| | 2015-6-12 12:05 | 只看该作者
JY-DX-JY 发表于 2015-6-12 11:59
库里的解码是这样的:
static uint8_t SC_decode_Answer2reset(uint8_t *card)
{

库里的ATR解码有很大的问题,参考7816好好改一下

使用特权

评论回复
26
JY-DX-JY|  楼主 | 2015-6-12 12:31 | 只看该作者
好,我试试。

使用特权

评论回复
27
JY-DX-JY|  楼主 | 2015-6-12 13:22 | 只看该作者
现在可以译码是T0协议了。
但是往下走
SC_PTSConfig();
   /* Inserts delay(400ms) for Smartcard clock resynchronisation */
    Delay(400);

    /* Select MF -------------------------------------------------------------*/
    SC_ADPU.Header.CLA = SC_CLA_GSM11;
    SC_ADPU.Header.INS = SC_SELECT_FILE;
    SC_ADPU.Header.P1 = 0x00;
    SC_ADPU.Header.P2 = 0x00;
    SC_ADPU.Body.LC = 0x02;

    for(i = 0; i < SC_ADPU.Body.LC; i++)           // 数据长度   
    {
      SC_ADPU.Body.Data = MasterRoot;        // 主机设置
    }
    while(i < LC_MAX)                              // 20字节的0  
    {   
      SC_ADPU.Body.Data[i++] = 0;
    }
    SC_ADPU.Body.LE = 0;                           // 返回为0个字节长度  

    SC_Handler(&SCState, &SC_ADPU, &SC_Responce);
执行到这里又看了下,SC_Responce结构体中的数据缓冲区第一个数据为0XA4其他全为0,sw1,sw2分别为0X00和0X00。

老卡就这样吗?CLA是A0呀!

使用特权

评论回复
28
sinshine| | 2015-6-12 16:55 | 只看该作者
老卡这个时候SW1SW2应该是90XX,或者9FXX。
我不了解STM32 uart。 SC_Response里收到0XA4 是ACK。如果STM32 UART硬件上收到卡发过来的ACK后,自动发送body.data. 那么SW1SW2应该能收到90XX或者9FXX。如果STM32 UART不是硬件自动发送的,检查一下软件有没有在收到ACK后,把body.data发送出去。感觉STM32的库不靠谱。LZ好好看看UART控制器是怎么操作的。

使用特权

评论回复
29
JY-DX-JY|  楼主 | 2015-6-12 17:14 | 只看该作者
本帖最后由 JY-DX-JY 于 2015-6-12 19:32 编辑

谢谢!好像好啦。
因为IO口用到了电平转换芯片,有一个IO口方向引脚,控制发送或者接收。
我前面修改了,后边忘了改。

使用特权

评论回复
30
huangcunxiake| | 2015-9-15 12:40 | 只看该作者
哈哈,我看了好多贴,都是你发的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则