项目场景:调试一款芯片作为读卡器使用
将一款芯片的代码一直到另一款新芯片上,实现的功能是7816读卡器功能
<技术小白,错误之处,烦请斧正>
问题描述
1、在初始化枚举时候对于主机下发的命令不能正确返回响应
2、正确返回ATR后,主机不下发 61 指令,所以无法进行ETU自校验
Bus Hound 6.01 capture on Windows Vista Service Pack 1 (x64). Complements of www.perisoft.net
Device - Device ID (followed by the endpoint for USB devices)
(25) Microsoft Usbccid Smartcard Reader (WUDF)
(26) 智能卡筛选器驱动程序
(27) 智能卡
Length - Total transfer length
Phase - Phase Type
CTL USB control transfer
IN Data in transfer
OUT Data out transfer
Data - Hex dump of the data transferred
Descr - Description of the phase
Delta - Elapsed time from the previous phase to the current phase
Cmd... - Position in the captured data
Time - Time the phase occurred in hour:minute:second.millisec form
Device Length Phase Data Description Delta Cmd.Phase.Ofs(rep) Time
------ -------- ----- ------------------------------------------------------------------------------------------------------ -------------------------------- ----- ------------------ ------------
25.2 10 OUT 63 00 00 00 00 00 01 00 00 00 c......... 37ms 12.1.0 15:48:47.336
25.1 10 IN 81 00 00 00 00 00 01 00 00 00 .......... 992us 13.1.0 15:48:47.337
25.2 10 OUT 62 00 00 00 00 00 02 01 00 00 b......... 9.6ms 14.1.0 15:48:47.347
25.1 22 IN 80 0c 00 00 00 00 02 00 00 00 3b 68 00 00 43 31 42 4f 4f 54 33 32 ..........;h..C1BOOT32 20ms 15.1.0 15:48:47.368
25.2 10 OUT 6c 00 00 00 00 00 03 00 00 00 l......... 10ms 16.1.0 15:48:47.378
25.1 10 IN 81 00 00 00 00 00 03 40 00 00 .......@.. 1.0ms 17.1.0 15:48:47.379
25.2 26 OUT 6f 10 00 00 00 00 04 00 00 00 00 a4 04 00 0b a0 00 00 03 97 43 49 44 5f 01 00 o...................CID_.. 1.9ms 18.1.0 15:48:47.381
25.1 12 IN 80 02 00 00 00 00 04 00 00 00 6d 00 ..........m. 10ms 19.1.0 15:48:47.391
3、用命令设置新的ETU值后无法返回新的ATR
4、正确返回新的ATR后,61指令中的第10字节时钟是低速状态
Device Length Phase Data Description Delta Cmd.Phase.Ofs(rep) Time
------ -------- ----- ------------------------------------------------------------------------------------------------------ -------------------------------- ----- ------------------ ------------
25.2 10 OUT 63 00 00 00 00 00 29 00 00 00 c.....)... 2.5sc 1.1.0 15:54:59.440
25.1 10 IN 81 00 00 00 00 00 29 00 00 00 ......)... 995us 2.1.0 15:54:59.441
25.2 10 OUT 63 00 00 00 00 00 2a 00 00 00 c.....*... 2.0ms 3.1.0 15:54:59.443
25.1 10 IN 81 00 00 00 00 00 2a 00 00 00 ......*... 1.0ms 4.1.0 15:54:59.444
25.2 10 OUT 62 00 00 00 00 00 2b 01 00 00 b.....+... 10ms 5.1.0 15:54:59.454
25.1 22 IN 80 0c 00 00 00 00 2b 00 00 00 3b 68 00 00 43 31 42 4f 4f 54 33 32 ......+...;h..C1BOOT32 20ms 6.1.0 15:54:59.475
25.2 15 OUT 61 05 00 00 00 00 2c 00 00 00 11 00 00 0a 00 a.....,........ 10ms 7.1.0 15:54:59.485
25.1 15 IN 82 05 00 00 00 00 2c 00 00 00 11 00 00 0a 00 ......,........ 992us 8.1.0 15:54:59.486
25.2 18 OUT 73 08 00 00 00 00 2d 00 00 00 fc 0d 00 00 80 25 00 00 s.....-........%.. 994us 9.1.0 15:54:59.487
25.1 18 IN 84 08 00 00 00 00 2d 00 00 00 fc 0d 00 00 80 25 00 00 ......-........%.. 1.0ms 10.1.0 15:54:59.488
25.2 15 OUT 6f 05 00 00 00 00 2e 00 00 00 c0 88 96 01 00 o.............. 3.8sc 11.1.0 15:55:03.386
25.1 12 IN 80 02 00 00 00 00 2e 00 00 00 90 00 ............ 10ms 12.1.0 15:55:03.397
25.2 10 OUT 63 00 00 00 00 00 2f 00 00 00 c...../... 3.3sc 13.1.0 15:55:06.783
25.1 10 IN 81 00 00 00 00 00 2f 00 00 00 ....../... 1.0ms 14.1.0 15:55:06.784
25.2 10 OUT 63 00 00 00 00 00 30 00 00 00 c.....0... 2.4ms 15.1.0 15:55:06.787
25.1 10 IN 81 00 00 00 00 00 30 00 00 00 ......0... 1.0ms 16.1.0 15:55:06.788
25.2 10 OUT 62 00 00 00 00 00 31 01 00 00 b.....1... 10ms 17.1.0 15:55:06.798
25.1 23 IN 80 0d 00 00 00 00 31 00 00 00 3b 78 96 00 00 43 31 42 4f 4f 54 33 32 ......1...;x...C1BOOT32 26ms 18.1.0 15:55:06.825
25.2 14 OUT 6f 04 00 00 00 00 32 00 00 00 ff 10 11 fe o.....2....... 11ms 19.1.0 15:55:06.836
25.1 14 IN 80 04 00 00 00 00 32 00 00 00 ff 10 11 fe ......2....... 12ms 20.1.0 15:55:06.848
25.2 15 OUT 61 05 00 00 00 00 33 00 00 00 11 00 00 0a 00 a.....3........ 925us 21.1.0 15:55:06.849
25.1 15 IN 82 05 00 00 00 00 33 00 00 00 11 00 00 0a 00 ......3........ 1.0ms 22.1.0 15:55:06.850
25.2 18 OUT 73 08 00 00 00 00 34 00 00 00 fc 0d 00 00 80 25 00 00 s.....4........%.. 1.0ms 23.1.0 15:55:06.851
25.1 18 IN 84 08 00 00 00 00 34 00 00 00 fc 0d 00 00 80 25 00 00 ......4........%.. 980us 24.1.0 15:55:06.852
原因分析:
1、原因可能是设备中没有处理主机下发的数据或者设备处理错了相应的命令。(代码写错了、、、、、、)
7816的协议一般是主机发送5字节收一个INS,判断是否继续发送。有的指令是仅收SW。所以改写处理 6F 指令的函数
2、61命令涉及到读卡器自动修改通信速率,主机不下发命令应该是设备描述符中相应的位置没有设置正确
3、设置新的速度模式后需复位卡片,可能是在62命令处理不当,导致没有返回正确响应
4、新的速率的ATR成功返回后,主机下发的命令没有更新,应该与设备描述符设置有关
解决方案:
1、修改接收到命令后的处理过程,如果不了解怎么处理可能请教大神。。。。。(下面是我自己的代码,)
//此函数用于处理 6F 命令
void user_custom_commands(void)
{
U16 data_len = (U16)((message_data[2]<<8) | message_data[1]);
unsigned char sw[2];
// send command header to card 将命令发送到卡
memcpy(data_buff,(U8*)(SPECIAL_RAM_BASE + EP1_ADDR + 10),data_len);
if(message_data[10] == 0xff)
{
send_data(data_buff, 4);
receive_data(recv_buff, 4);
memcpy(message_data + 10, recv_buff, 4);
message_data[0] = 0x80;
ep1_send(EP1_ADDR,14);
return ;
}
if(data_len < 5)
{
send_data(data_buff, 4);
}
else
{
send_data(data_buff, 5);
}
if(0 == receive_byte(sw))
{
goto timeout_exit;
}
//Null
while(sw[0] == 0x60)
{
SCITCR = 0x601B3F00;
while(!(SCISR & SCISR_RDRF) & !(SCITCR & SCISR_CNTOR));
SCITCR = 0;
if(0 == receive_byte(sw))
{
goto timeout_exit;
}
}
//0x6X or 0x9X
if(((sw[0] & 0xf0) == 0x60) || ((sw[0] & 0xf0) == 0x90))
{
if(0 == receive_byte(sw+1))
{
goto timeout_exit;
}
data_len = 2;
memcpy(message_data + 10, sw, data_len);
message_data[0] = 0x80; //RDR_to_PC_SlotStatus
message_data[1] = (unsigned char)(data_len & 0xff);
message_data[2] = (unsigned char)(data_len >> 8);
message_data[3] = 0x00;
message_data[4] = 0x00;
message_data[7] = 0x00;
message_data[8] = 0x00;
message_data[9] = 0x00;
data_len += 10;
ep1_send(EP1_ADDR,data_len);
return ;
}
//CMD
if(sw[0] != data_buff[1])
{
goto timeout_exit;
}
// 判断长度
if(data_len == 5)
{
receive_data(recv_buff, data_buff[4] + 2);
//get_procedure_byte(sw, 0);
memcpy(message_data + 10, recv_buff, data_buff[4] + 2);
data_len = data_buff[4];
data_len += 2;
message_data[0] = 0x80; //RDR_to_PC_SlotStatus
message_data[1] = (unsigned char)(data_len & 0xff);
message_data[2] = (unsigned char)(data_len >> 8);
message_data[3] = 0x00;
message_data[4] = 0x00;
message_data[7] = 0x00;
message_data[8] = 0x00;
message_data[9] = 0x00;
data_len += 10;
ep1_send(EP1_ADDR,data_len);
return;
}
else if(data_len > 5)
{
send_data(data_buff + 5, data_len - 5);
if(true != get_procedure_byte(sw, data_buff[1]))
{
goto timeout_exit;
}
if(((sw[0] & 0x60) == 0x60) || ((sw[0] & 0x90) == 0x90))
{
data_len = 2;
memcpy(message_data + 10, sw, data_len);
message_data[0] = 0x80; //RDR_to_PC_SlotStatus
message_data[1] = (unsigned char)(data_len & 0xff);
message_data[2] = (unsigned char)(data_len >> 8);
message_data[3] = 0x00;
message_data[4] = 0x00;
message_data[7] = 0x00;
message_data[8] = 0x00;
message_data[9] = 0x00;
data_len += 10;
ep1_send(EP1_ADDR,data_len);
return ;
}
}
timeout_exit:
SCISR |= SCISR_WTF;
SCICR2 &= ~SCICR2_WTEN;
message_data[7] = SLOT_STATUS_ERROR;
message_data[8] = ICC_MUTE;
ep1_send(EP1_ADDR,10);
//usb_send_ep3(CARD_REMOVE_NOTICE);
last_state = 0;
slot_state = 0;
return;
}
2、主机不下发61命令修改设备描述符的
dwFeatures
信息,此信息是决定是否自动修改速率的配置
3、修改62命令的处理过程
case 0x62: // PC_to_RDR_IccPowerOn
{
/*没有一下两行代码是不行的*/
SCICR1 |= SCICR1_SRST; //复位SCI模块,我是“两句代码的第一行”
SCI_Master_Init(); //重新初始化,我是“两句代码的第二行”
Activate_Card(); //连接卡片
get_ATR((unsigned char*)&message_data[10], &T, &ATR_Len); //获取ATR
message_data[0] = 0x80;
message_data[1] = ATR_Len;
message_data[7] = 0;
message_data[8] = 0;
ep1_send(EP1_ADDR,ATR_Len + 10); //将数据返回到上位机
}
break;
4、此与
dwMaxDataRate
参数有关,表明设备支持最大的速率
其他
1、61命令的处理方式
unsigned short etu_clk[256]={
0, 372, 186, 93, 0, 0, 0, 0, 31, 0, 0,0,0,0,0,0,
0, 372, 186, 93, 0, 0, 0, 0, 31, 0, 0,0,0,0,0,0,
0, 558, 279, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,
0, 744, 372, 186, 93, 0, 0, 0, 62, 0, 0,0,0,0,0,0,
0, 1116, 558, 279, 0, 0, 0, 0, 93, 0, 0,0,0,0,0,0,
0, 1488, 744, 372, 186, 93, 0, 0, 124, 0, 0,0,0,0,0,0,
0, 1860, 930, 465, 0, 0, 0, 0, 155, 93, 0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,
0, 512, 256, 128, 64, 32, 16, 8, 0, 0, 0,0,0,0,0,0,
0, 768, 384, 192, 96, 48, 24, 12, 64, 0, 0,0,0,0,0,0,
0, 1024, 512, 256, 128, 64, 32, 16, 0, 0, 0,0,0,0,0,0,
0, 1536, 768, 384, 192, 96, 48, 24, 128, 0, 0,0,0,0,0,0,
0, 2048, 1024, 512, 256, 128, 64, 32, 0, 0, 0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0
};
case 0x61: //PC_to_RDR_SetParameters
{
etu_parameter = etu_clk[message_data[10]];
if(etu_parameter==0)
{
message_data[0] = 0x82; //RDR_to_PC_Parameters
message_data[1] = 0x00;
message_data[2] = 0x00;
message_data[3] = 0x00;
message_data[4] = 0x00;
message_data[9] = message_data[7];
message_data[7] = 0x40;
message_data[8] = FI_DI_PAIR_INVALID_OR_NOT_SUPPORTED;
ep1_send(EP1_ADDR,10);
}
else
{
//set etu clock
SCIECR = etu_parameter;
//set convetion
if(message_data[11]) SCICR1 |= SCICR1_CONV;
else SCICR1 &= ~SCICR1_CONV;
//set extra gard time
if(message_data[12]==255) SCIGTR = 12;
else SCIGTR = (U16)(12+message_data[12]);
//set wait time
WT = 960 * /*(U32)message_data[13]*/ 10 * (372/etu_parameter) * 4; // 4M????3.4?
SCICWTR = WT;
//set stop clock level
if(message_data[14]==2) SCICR2 |= SCICR2_CSHL;
else SCICR2 &= ~SCICR2_CSHL;
message_data[0] = 0x82; //RDR_to_PC_Parameters
message_data[9] = message_data[7];
message_data[7] = 0x00;
message_data[8] = 0x00;
ep1_send(EP1_ADDR,10+message_data[1]);
}
}
break;
2、设备描述符
static unsigned char ConfigurationDescriptor[0x56+7] =
{
//*Configuration Descriptor
0x09, //bLength
0x02, //bDescriptorType : Configuration
//0x56, 0x00, //wTotalLength
0x5d, 0x00, //wTotalLength
0x01, //bNumInterfaces
0x01, //bConfigurationValue
0x00, //iConfiguration
0x80, //bmAttributes
0x64, //MaxPower
//Interface Descriptor
0x09, //bLength
0x04, //bDescriptorType : Interface
0x00, //bInterfaceNumber
0x00, //bAlternateSetting
0x02, //bNumEndpoints: In and Ou
//0x03, //bNumEndpoints: In and Ou
0x0b, //bInterfaceClass : Smart card
0x00, //bInterfaceSubClass
0x00, //bInterfaceProtocol: Bulk
0x00, //iInterface
//Class Descriptor
0x36, //bLength
0x21, //bDescriptorType : CCID
0x10, 0x01, //bcdCCID : v1.1
0x00, //bMaxSlotIndex
0x01, //bVoltageSupport
0x01, 0x00, 0x00, 0x00, //dwProtocols : T=0
0xfc, 0x0d, 0x00, 0x00, //dwDefaultClock : 3.58MHz
0xfc, 0x0d, 0x00, 0x00, //dwMaximumClock : 3.58MHz
0x00, //bNumClockSupported: should be non-zero according to ccid driver
//0x01, //bNumClockSupported: should be non-zero according to ccid driver
0x80, 0x25, 0x00, 0x00, //dwDataRate
//0x80, 0x25, 0x00, 0x00, //dwMaxDataRate
0x06, 0x6a, 0x03, 0x00, //dwMaxDataRate
0x00, //bNumDataRatesSupported: should be non-zero according to ccid driver
0x00, 0x00, 0x00, 0x00, //dwMaxIFSD
0x00, 0x00, 0x00, 0x00, //dwSynchProtocols
0x00, 0x00, 0x00, 0x00, //dwMechanical
//0x40, 0x08, 0x02, 0x00, //dwFeatures
0x00, 0x00, 0x01, 0x00, //dwFeatures
0x0f, 0x01, 0x00, 0x00, //dwMaxCCIDMessageLength: 271
0xff, //bClassGetResponse
0xff, //bClassEnvelope
0x00, 0x00, //wLcdLayout
0x00, //bPINSupport
0x01, //bMaxCCIDBusySlots
//Endpoint Descriptors
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x83, 0x03, 0x08, 0x00, 0x18,
};
3、
dwMaxDataRate
的一些值
static unsigned char Response_To_GET_DATA_RATES[76] = {
0x80, 0x25, 0x00, 0x00, //9600: 372 clocks/etu
0x1f, 0x32, 0x00, 0x00, //12831(12800): 279 clocks/etu
0xa0, 0x36, 0x00, 0x00, //13984(13950): 256 clocks/etu
0xd5, 0x48, 0x00, 0x00, //18645(18600): 192 clocks/etu
0x2f, 0x4b, 0x00, 0x00, //19247(19200): 186 clocks/etu
0x38, 0x5a, 0x00, 0x00, //23096(23040): 155 clocks/etu
0x40, 0x6d, 0x00, 0x00, //27968(27900): 128 clocks/etu
0xc6, 0x70, 0x00, 0x00, //28870(28800): 124 clocks/etu
0xab, 0x91, 0x00, 0x00, //37291(37200): 96 clocks/etu
0x5e, 0x96, 0x00, 0x00, //38494(38400): 93 clocks/etu
0x81, 0xda, 0x00, 0x00, //55937(55800): 64 clocks/etu
0x8d, 0xe1, 0x00, 0x00, //57741(57600): 62 clocks/etu
0x57, 0x23, 0x01, 0x00, //74583(74400): 48 clocks/etu
0x03, 0xb5, 0x01, 0x00, //111875(111600): 32 clocks/etu
0x1b, 0xc3, 0x01, 0x00, //115483(115200): 31 clocks/etu
0xae, 0x46, 0x02, 0x00, //149166(148800): 24 clocks/etu
0x06, 0x6a, 0x03, 0x00, //223750(223200): 16 clocks/etu
0x5d, 0x8d, 0x04, 0x00, //298333(297600): 12 clocks/etu
0x0c, 0xd4, 0x06, 0x00 //447500(446400): 8 clocks/etu
};