diff options
author | NIIBE Yutaka <[email protected]> | 2019-07-09 01:56:09 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2019-07-09 01:56:09 +0000 |
commit | c51a5685554a06e00ae1e99070b44613b2f8d417 (patch) | |
tree | 691e0bb4b3a37fd632a3c70b98aaa91883c9f85a | |
parent | scd: Fix keygrip search. (diff) | |
download | gnupg-c51a5685554a06e00ae1e99070b44613b2f8d417.tar.gz gnupg-c51a5685554a06e00ae1e99070b44613b2f8d417.zip |
scd: ccid-driver: Initial getting ATR more robustly.
* scd/ccid-driver.c (send_power_off): New.
(do_close_reader): Use send_power_off.
(ccid_get_atr): Add error recovery.
GnuPG-bug-id: 4616
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r-- | scd/ccid-driver.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index e092a2b9a..f791c3ad5 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1717,31 +1717,37 @@ ccid_require_get_status (ccid_driver_t handle) return 1; } - -static void -do_close_reader (ccid_driver_t handle) +static int +send_power_off (ccid_driver_t handle) { int rc; unsigned char msg[100]; size_t msglen; unsigned char seqno; - if (!handle->powered_off) - { - msg[0] = PC_to_RDR_IccPowerOff; - msg[5] = 0; /* slot */ - msg[6] = seqno = handle->seqno++; - msg[7] = 0; /* RFU */ - msg[8] = 0; /* RFU */ - msg[9] = 0; /* RFU */ - set_msg_len (msg, 0); - msglen = 10; + msg[0] = PC_to_RDR_IccPowerOff; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + msglen = 10; - rc = bulk_out (handle, msg, msglen, 0); - if (!rc) - bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, - seqno, 2000, 0); - } + rc = bulk_out (handle, msg, msglen, 0); + if (!rc) + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, + seqno, 2000, 0); + return rc; +} + +static void +do_close_reader (ccid_driver_t handle) +{ + int rc; + + if (!handle->powered_off) + send_power_off (handle); if (handle->transfer) { @@ -2597,6 +2603,21 @@ ccid_get_atr (ccid_driver_t handle, NULL, 0, NULL)) goto again; } + else if (statusbits == 0 && CCID_COMMAND_FAILED (msg)) + { + /* Card was active already, and something went wrong with + PC_to_RDR_IccPowerOn command. It may be baud-rate mismatch + between the card and the reader. To recover from this state, + send PC_to_RDR_IccPowerOff command to reset the card and try + again. + */ + rc = send_power_off (handle); + if (rc) + return rc; + + statusbits = 1; + goto again; + } else if (CCID_COMMAND_FAILED (msg)) return CCID_DRIVER_ERR_CARD_IO_ERROR; |