Package: libccid Version: 1.4.4-1 Severity: normal Tags: upstream patch -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Upstream commit r4987 ("Use libusb-1.0 instead of libusb-0.1") breaks communication with my reader (REINER SCT cyberJack RFID basis, USB 0c4b:9102). When sending an APDU to the reader, e.g. via scriptor, libccid hangs while waiting for data from the reader. The pcscd log shows: 00000009 APDU: 60 00000010 ifdhandler.c:1283:IFDHTransmitToICC() usb:0c4b/9102:libudev:0:/dev/bus/usb/002/047 (lun: 0) 00000018 commands.c:1456:CmdXfrBlockAPDU_extended() T=0 (extended): 1 bytes 00000020 -> 000000 6F 01 00 00 00 00 0C 00 00 00 60 00006239 <- 000000 80 00 00 00 00 00 0C 80 02 00 80 08 00 00 00 00 0C 00 00 00 AF 04 01 01 01 00 16 05 00000025 commands.c:1391:CCID_Receive() Time extension requested: 0x02 (now hangs there) So what's happening is that libusb_bulk_transfer in ReadUSB returns two messages at once, CCID_Receive calls ReadUSB again but the data already has been read. For some reason this used to be different with libusb 0.x - I have no idea whether this is a timing issue or what not: 00000022 APDU: 60 00000017 ifdhandler.c:1264:IFDHTransmitToICC() usb:0c4b/9102:libudev:0:/dev/bus/usb/002/045 (lun: 0) 00000024 commands.c:1412:CmdXfrBlockAPDU_extended() T=0 (extended): 1 bytes 00000029 -> 000000 6F 01 00 00 00 00 0F 00 00 00 60 00001543 <- 000000 80 00 00 00 00 00 0F 80 02 00 00000034 commands.c:1347:CCID_Receive() Time extension requested: 0x02 00001971 <- 000000 80 08 00 00 00 00 0F 00 00 00 AF 04 01 01 01 00 16 05 00000038 SW: AF 04 01 01 01 00 16 05 I have attached a patch (against svn trunk, yet it applies to the source .tgz with -p3) which fixes that for me, though I'm unsure whether handling this for different cases as CCID_TIME_EXTENSION might be necessary. Sebastian -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iD8DBQFOPvpMvBVic1oTsEgRAtfuAJ41KuYLg95oayPbpOUbDhlogGax5gCdFfpV ffnq0SrZC9P1YOZUybTI/PI= =K521 -----END PGP SIGNATURE-----
diff --git a/Drivers/ccid/src/commands.c b/Drivers/ccid/src/commands.c index fec90cc..e2e13ab 100644 --- a/Drivers/ccid/src/commands.c +++ b/Drivers/ccid/src/commands.c @@ -1222,8 +1222,9 @@ RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length, RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length, unsigned char rx_buffer[], unsigned char *chain_parameter) { - unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */ - unsigned int length; + unsigned char cmdbuf[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */ + unsigned char *cmd = cmdbuf; + unsigned int length, datalen; RESPONSECODE return_value = IFD_SUCCESS; status_t ret; @@ -1341,9 +1342,12 @@ time_request_ICCD_B: } #endif -time_request: - length = sizeof(cmd); - ret = ReadPort(reader_index, &length, cmd); +time_request_read: + length = sizeof(cmdbuf); + cmd = cmdbuf; + ret = ReadPort(reader_index, &length, cmdbuf); + +time_request_parse: if (ret != STATUS_SUCCESS) { if (STATUS_NO_SUCH_DEVICE == ret) @@ -1386,21 +1390,28 @@ time_request: } } + datalen = dw2i(cmd, 1); if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION) { DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]); - goto time_request; + if (length-10 > datalen) { + DEBUG_COMM("Still data available, not reading again"); + length -= (datalen+10); + cmd += (datalen+10); + goto time_request_parse; + } else + goto time_request_read; } /* we have read less (or more) data than the CCID frame says to contain */ - if (length-10 != dw2i(cmd, 1)) + if (length-10 != datalen) { DEBUG_CRITICAL3("Can't read all data (%d out of %d expected)", - length-10, dw2i(cmd, 1)); + length-10, datalen); return_value = IFD_COMMUNICATION_ERROR; } - length = dw2i(cmd, 1); + length = datalen; if (length <= *rx_length) *rx_length = length; else