输入的是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. 事件(event),正则

    1.事件(event):事件是可以被 JavaScript 侦测到的行为.网页中的每个元素都可以产生某些可以触发 JavaScript 函数的事件.2.事件源: 触发事件的元素 事件: 被 JavaS ...

  2. zookeeper集群安装与配置

    转自: http://my.oschina.net/u/2377453/blog/464739 1.解压zookeeper 2.在$ZOOKEEPER_HOME/conf下创建zoo.cfg文件(参考 ...

  3. 编译内核实现iptables防火墙layer7应用层过滤 (三)

    在前面的两篇文章中我们主要讲解了Linux防火墙iptables的原理及配置规则,想博友们也都知道iptables防火墙是工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙.以 ...

  4. java第一天学习作业及答案

    作业一 一.选择题 1.选出在java中有效的注释声明(AD)(选两项) A.//这是注释 B.*/这是注释*/ C./这是注释 D./*这是注释*/ 2.在控制台运行一个java程序,使用的命名正确 ...

  5. 设置DIV块元素在浏览器页面中垂直居中

    任务目标 实践HTML/CSS布局方式 深入了解position等CSS属性 任务描述 实现如 示例图(点击打开) 的效果 灰色元素水平垂直居中,有两个四分之一圆位于其左上角和右下角. 任务注意事项 ...

  6. 一定要在主线程更新UI

    在一些技术交流群里面,一些初学者(我表示我也是其中一人),总是会发现,为什么我UIView的animate方法,不会动!而是直接闪? 这是为什么呢? 一定要在主线程中更新UI! 一定要在主线程中更新U ...

  7. eclipse为方法添加注释的快捷键是什么

    /** * 登录验证 * @param 传入的vo类 * @return * @throws Exception */这种注释快捷键?   先敲“/”在敲两个**,然后回车

  8. kafka 订单应用需求

    kafka的介绍就不说了,网上会找到一大堆. 为了公司做报表需要对卡券订单的销售情况做总结,所以每次下单的时候都要给卡券活动模块传递一次消息,并把订单的信息发送给活动,活动做相应的数据操作,因为数据量 ...

  9. django使用ldap认证

    pip3 install django-auth-ldap python-ldap urls.py, from app0104 import views urlpatterns = [ url(r'^ ...

  10. grep查询文本:问一个简单shell问题,将grep的输出赋值给一个变量

    问一个简单shell问题,将grep的输出赋值给一个变量 用grep命令得到的输出赋值给一个变量不成功. grep命令如下: 代码: $ grep -c '^abc' file.txt 输出为22,表 ...