输入的是ATR,通过解析输出TA、TB、TC、TD的信息。

似乎没有容错处理,~~~~(>_<)~~~~

 #include <stdio.h>

 #define TA_BIT          (1<<4)  /**< TAx presence bit (bit 4, 0x10) */
#define TB_BIT (1<<5) /**< TBx presence bit (bit 5, 0x20) */
#define TC_BIT (1<<6) /**< TCx presence bit (bit 6, 0x40) */
#define TD_BIT (1<<7) /**< TDx presence bit (bit 7, 0x80) */ void atr_TS(unsigned char ch)
{
printf("TS: %02X\r\n", ch);
if(ch == 0x3B)
{
printf("\t正向约定\r\n");
}
else if(ch == 0x3F)
{
printf("\t反向约定\r\n");
}
else
{
printf("\tATR 错误\r\n");
}
}
void atr_T0(unsigned char ch)
{
printf("T0: %02X\r\n", ch); if ((ch & TA_BIT) == TA_BIT)
{
printf("\tTA1 存在\r\n");
}
if ((ch & TB_BIT) == TB_BIT)
{
printf("\tTB1 存在\r\n");
}
if ((ch & TC_BIT) == TC_BIT)
{
printf("\tTC1 存在\r\n");
}
if ((ch & TD_BIT) == TD_BIT)
{
printf("\tTD1 存在\r\n");
}
printf("\t历史字符数: %d\r\n", ch & 0x0f);
}
void atr_TA1(unsigned char ch)
{
int Di[] = { , , , , , , , ,
, , , , , , , };
int Fi[] = { , , , , , , , ,
, , , , , , , }; printf("TA1: %02X\r\n", ch);
printf("\t时钟速率转换因子Fi: %d\r\n", (ch >> ) & 0x0f);
printf("\t位速率调节因子Di: %d\r\n", (ch & 0x0f));
printf("\tFi/Di: %f\r\n",
(Fi[(ch>>)&0x0f]!= && Di[ch&0x0f]!=) ? (float)Fi[(ch>>)&0x0f]/(float)Di[ch&0x0f] : );
}
void atr_TB1(unsigned char ch)
{
printf("TB1: %02X\r\n", ch);
printf("\t编程电压 P 值: %d\r\n", ch & 0x1f);
printf("\t最大编程电流 I 值: %d\r\n", (ch >> ) & 0x03);
}
void atr_TC1(unsigned char ch)
{
printf("TC1: %02X\r\n", ch);
printf("\t额外保护时间: %d\r\n", ch);
}
void atr_TD1(unsigned char ch)
{
printf("TD1: %02X\r\n", ch); if ((ch & TA_BIT) == TA_BIT)
{
printf("\tTA2 存在\r\n");
}
if ((ch & TB_BIT) == TB_BIT)
{
printf("\tTB2 存在\r\n");
}
if ((ch & TC_BIT) == TC_BIT)
{
printf("\tTC2 存在\r\n");
}
if ((ch & TD_BIT) == TD_BIT)
{
printf("\tTD2 存在\r\n");
}
printf("\t后续信息交换所使用的协议类型: %d\r\n", ch & 0x0f);
}
void atr_TA2(unsigned char ch)
{
printf("TA2: %02X\r\n", ch);
printf("\t是否有能力改变它的操作模式: %s\r\n",
!!!(ch & 0x80) ? "是(0)" : "否(1)");
printf("\t协商模式 or 特定模式: %s\r\n",
!!!(ch & 0x80) ? "特定模式(0)" : "协商模式(1)");
printf("\t后续信息交换所使用的协议类型: %d\r\n", ch & 0x0f);
}
void atr_TB2(unsigned char ch)
{
printf("TB2: %02X\r\n", ch);
printf("\tIC卡所需的编程电压P的值PI2: %d\r\n", ch);
}
void atr_TC2(unsigned char ch)
{
printf("TC2: %02X\r\n", ch);
printf("\tT=0, 传输工作等待时间整数WI: %d\r\n", ch);
}
void atr_TD2(unsigned char ch)
{
printf("TD2: %02X\r\n", ch); if ((ch & TA_BIT) == TA_BIT)
{
printf("\tTA3 存在\r\n");
}
if ((ch & TB_BIT) == TB_BIT)
{
printf("\tTB3 存在\r\n");
}
if ((ch & TC_BIT) == TC_BIT)
{
printf("\tTC3 存在\r\n");
}
if ((ch & TD_BIT) == TD_BIT)
{
printf("\tTD3 存在\r\n");
}
printf("\t后续信息交换所使用的协议类型: %d\r\n", ch & 0x0f);
}
void atr_TA3(unsigned char ch)
{
printf("TA3: %02X\r\n", ch);
printf("\tT=1, IC卡的信息域大小整数IFSI: %d\r\n", ch);
}
void atr_TB3(unsigned char ch)
{
printf("TB3: %02X\r\n", ch);
printf("\tT=1, CWI: %d\r\n", ch & 0x0f);
printf("\tT=1, BWI: %d\r\n", (ch >> ) & 0x0f);
}
void atr_TC3(unsigned char ch)
{
printf("TC3: %02X\r\n", ch);
printf("\tT=1, 块错误校验码的类型: %d\r\n", ch & 0x01);
}
void atr_history(unsigned char *ch, int len)
{
int i;
printf("TKi:");
for(i = ; i < len; i++)
printf(" %02X", ch[i]);
printf("\r\n");
}
void atr_TCK(unsigned char ch)
{
printf("TCK: %02X\r\n", ch);
} #define STATE_PARSE_TS 1
#define STATE_PARSE_T0 2
#define STATE_PARSE_TA 3
#define STATE_PARSE_TB 4
#define STATE_PARSE_TC 5
#define STATE_PARSE_TD 6
#define STATE_PARSE_HIST_BYTES 7
#define STATE_PARSE_TCK 8
#define STATE_PARSE_END 255 int atr_parse(unsigned char *atr, int len)
{
unsigned char data;
unsigned char TCK = ;
unsigned char K = ;
unsigned char Yi = ;
int k, state, index, length, protocol;
unsigned char *ptr;
unsigned char hist_bytes[]; length = len;
ptr = atr;
state = STATE_PARSE_TS;
index = ;
k = ;
protocol = ; while( ptr < (atr + length) )
{
data = *ptr++;
if ( state != STATE_PARSE_TS )
{
TCK ^= data ;
} switch( state )
{
case STATE_PARSE_TS:
atr_TS(data);
state = STATE_PARSE_T0;
break;
case STATE_PARSE_T0:
atr_T0(data);
K = data & 0x0F;
Yi = data;
if ( data & 0x10 )
{
state = STATE_PARSE_TA;
}
else if ( data & 0x20 )
{
state = STATE_PARSE_TB;
}
else
{
if ( data & 0x40 )
{
state = STATE_PARSE_TC;
}
else if ( data & 0x80 )
{
state = STATE_PARSE_TD;
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
}
break;
case STATE_PARSE_TA :
switch( index )
{
case : /* TA1 */
atr_TA1(data);
break;
case :
atr_TA2(data);
break;
case :
atr_TA3(data);
break;
}
if ( Yi & 0x20 )
{
state = STATE_PARSE_TB;
}
else if ( Yi & 0x40 )
{
state = STATE_PARSE_TC;
}
else if ( Yi & 0x80 )
{
state = STATE_PARSE_TD;
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_TB :
switch( index )
{
case : /* TB1 */
atr_TB1(data);
break ;
case : /* TB2 */
atr_TB2(data);
break ;
case : /* TB3 */
atr_TB3(data);
break;
}
if ( Yi & 0x40 )
{
state = STATE_PARSE_TC;
}
else if ( Yi & 0x80 )
{
state = STATE_PARSE_TD;
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_TC :
switch( index )
{
case : /* TC1 */
atr_TC1(data);
break;
case : /* TC2 */
atr_TC2(data);
break ;
case : /* TC3 */
atr_TC3(data);
break ;
}
if ( Yi & 0x80 )
{
state = STATE_PARSE_TD;
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
break ;
case STATE_PARSE_TD :
Yi = data ;
switch( index++ )
{
case :
protocol = Yi & 0x0F;
atr_TD1(data);
break;
case :
atr_TD2(data);
break;
} if ( Yi & 0xF0 )
{
if ( Yi & 0x10 )
{
/* TAx character present */
state = STATE_PARSE_TA;
}
else if ( Yi & 0x20 )
{
/* TBx character present */
state = STATE_PARSE_TB;
}
else if ( Yi & 0x40 )
{
/* TCx character present */
state = STATE_PARSE_TC;
}
else if ( Yi & 0x80 )
{
/* TDx character present */
state = STATE_PARSE_TD;
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
}
else
{
state = STATE_PARSE_HIST_BYTES;
}
break ;
case STATE_PARSE_HIST_BYTES:
if( K )
{
if( k < K )
{
hist_bytes[k++] = data;
if(k == K)
{
if(protocol > )
state = STATE_PARSE_TCK;
else
ptr = atr + length; atr_history(hist_bytes, k);
}
}
break;
}
case STATE_PARSE_TCK:
atr_TCK(data);
if ( !TCK )
{
}
atr_TCK(TCK);
ptr = atr + length;
break ;
}
if( state == STATE_PARSE_HIST_BYTES && K == && protocol == )
break;
} return ;
} int main(void)
{
//atr_TA2((0 << 7) | (0 << 4) | 0x01);
//atr_TA2((0 << 7) | (1 << 4) | 0x01);
//atr_TA2((1 << 7) | (0 << 4) | 0x01);
//atr_TA2((1 << 7) | (1 << 4) | 0x01);
//atr_TA1(0x11); //unsigned char atr1[] = {0x3B, 0xB5, 0x11, 0x00, 0x81, 0x31, 0x46, 0x15, 0x56, 0x20, 0x31, 0x2E, 0x50, 0x1E};
//unsigned char atr2[] = {0x3B, 0x9C, 0x11, 0x81, 0x21, 0x34, 0x53, 0x43, 0x20, 0x53, 0x56, 0x20, 0x31, 0x2E, 0x31, 0x20, 0x4E, 0x43, 0x0F};
//unsigned char atr3[] = {0x3B, 0x89, 0x40, 0x14, 0x47, 0x47, 0x32, 0x34, 0x4d, 0x35, 0x32, 0x38, 0x30};
unsigned char atr[] = {0x3f, 0x23, 0x00, 0x80, 0x69, 0xae}; atr_parse(atr, sizeof(atr)/sizeof(atr[])); return ;
}

IC卡复位应答ATR解析的更多相关文章

  1. IC卡复位应答ATR的数据元和它们的意义

    ISO/IEC 7816-3标准中对ATR的数据串和数据元做了规定和描述.ATR的数据元和它们的意义: 数据元 说明 TS 起始字符 T0 格式字符 TA1,TB1,TC1,TD1,... 接口字符 ...

  2. 复位应答ATR的基本结构和数据元

    根据定义,复位应答是一系列字节的值,这些字节是由卡作为对复位命令的响应发送给接口设备的 ,在I/O电路上,每个字节在一个异步字符中传输.每个成功的复位操作,都会导致I/O上的一个初始字符TS,TS后面 ...

  3. EMV卡复位应答的时间特性 ---ISO7816协议

    1.冷复位的时间特性 图1 如图1所示: T0为200clk 从T0结束到RST变为高电平为40000-45000个clock 从RST变为高电平后,卡片必须在400-40000个clock之间应答, ...

  4. IC卡热复位时序

    热复位(warm reset):在时钟CLK和电源电压VCC处于激活状态的前提下,IC卡收到复位信号时产生的复位. 冷复位过程之后,如果收到的复位应答信号不满足规定,终端将启动热复位并从IC卡获得复位 ...

  5. IC卡冷复位时序

    冷复位(cold reset):当提供给IC卡的电源电压和其他信号从静止状态中复苏且收到复位信号后,IC卡产生的复位. 在触点激活后,终端将发出一个冷复位信号,并从IC卡获得一个复位应答信号,过程如下 ...

  6. IC卡接口芯片TDA8007的读写器设计

    摘要:阐述T=0传输协议,给出IC卡读写器中使用的IC卡APDU指令流程和原理框图:重点介绍其中的IC卡接口芯片Philips的TDA8007,给出通过TDA8007对CPU IC卡上下电过程.具体程 ...

  7. 智能卡 ATR解析

    如果终端不支持IC卡支持的其它传输协议以及传输参数值,IC卡应该有能力用基本ATR定义的模式和终端进行交互. 终端如果无法满足IC卡回送ATR中定义的传输模式,将发送一个热复位信号,或将IC卡置为静止 ...

  8. IC卡

    本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . IC卡 (Integrated Circuit Card,集成电路卡),也称智能卡(Smart card).智慧卡(Intelligent ...

  9. 智能IC卡与终端(读卡器)之间的传输协议

    1.有两种协议 T=0,异步半双工字符传输协议 T=1,异步半双工块传输协议 终端一般都支持这两种协议,IC卡可以选择支持其中的一种.(因为终端可能需要面对各种类型的卡片,所以必须两种协议都支持,而卡 ...

随机推荐

  1. 文顶顶iOS开发博客链接整理及部分项目源代码下载

    文顶顶iOS开发博客链接整理及部分项目源代码下载   网上的iOS开发的教程很多,但是像cnblogs博主文顶顶的博客这样内容图文并茂,代码齐全,示例经典,原理也有阐述,覆盖面宽广,自成系统的系列教程 ...

  2. iOS 开发之控件快速学习(一)

    最近一个朋友想转iOS所以我开始写一些初级iOS学习博客!也希望第一些初学的朋友有所帮助,!好吧进入今天的正题,我们今天主要完成如下界面的显示! 好的一起打开Xcode一下几步我截图说明:

  3. LeetCode 177 Nth-Highest Salary mysql,取第n条数据,limit子句 难度:1

    https://leetcode.com/problems/nth-highest-salary/ ATTENTION:limit 子句只能接受int常量,不能接受运算式 CREATE FUNCTIO ...

  4. Bootstrap <基础二十五>警告(Alerts)

    警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...

  5. Python Day04

    一.迭代器与生成器: 迭代器(iterator): 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,迭代器的一大优点是不要求事 ...

  6. 关于ZendFramework环境的配置

    在运用PHP进行网站建设的时候,使用框架能够很好的提高编程效率,PHP语言的框架很多,现在普遍使用的是由Zend公司开发的ZendFramework框架,本篇文章是关于ZendFramework的运行 ...

  7. 轮播图适应代码jQ

    (function(){ var i = 0; var time ; $('.page-size').html('1'); var obj = $('.xst-scroll>li'); var ...

  8. less和sass的介绍和差异

    ● 混入(Mixins)——class中的class: ● 参数混入——可以传递参数的class,就像函数一样: ● 嵌套规则——Class中嵌套class,从而减少重复的代码: ● 运算——CSS中 ...

  9. HTML <label> 标签

    定义:<label> 标签为 input 元素定义标注(标记). 用法: label 元素不会向用户呈现任何特殊效果.不过,它为鼠标用户改进了可用性.如果您在 label 元素内点击文本, ...

  10. oracle使用sqlplus创建表空间

    一.打开命令行窗口,输入以下命令:sqlplus /nolog 回车后,将出现提示符 SQL>, 这时输入conn / as sysdba 一般即可登录,如果失败的话,可以试一下用conn sy ...