From 2a025039c1817c7f75c35a898884849a8e5dc926 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 30 Jan 2017 09:30:32 +0900 Subject: [PATCH] scd: Fix GetSlotStatus. * scd/apdu.c (get_status_reader): Add ON_WIRE arg, here. (ct_get_status, pcsc_get_status_direct, pcsc_get_status_wrapped) (pcsc_get_status, get_status_ccid, my_rapdu_get_status): Likewise. (reset_pcsc_reader_wrapped, open_pcsc_reader_wrapped): Follow the change. (apdu_get_status_internal): It's lower-level driver which judge it's not needed. Otherwise, it can't detect the removal. * scd/ccid-driver.c (ccid_slot_status): After the POWERED_OFF check, we can skip sending GetSlotStatus packet on wire, when no need. Signed-off-by: NIIBE Yutaka Fixes-commit: c8eee4d396a751d41fd1ee1e1b87b851fca172a --- scd/apdu.c | 44 ++++++++++++++++++-------------------------- scd/ccid-driver.c | 14 ++++++++++++-- scd/ccid-driver.h | 2 +- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/scd/apdu.c b/scd/apdu.c index f7522841f..6fc62aa00 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -109,7 +109,7 @@ struct reader_table_s { int (*disconnect_card)(int); int (*close_reader)(int); int (*reset_reader)(int); - int (*get_status_reader)(int, unsigned int *); + int (*get_status_reader)(int, unsigned int *, int); int (*send_apdu_reader)(int,unsigned char *,size_t, unsigned char *, size_t *, pininfo_t *); int (*check_pinpad)(int, int, pininfo_t *); @@ -365,7 +365,7 @@ long (* DLSTDCALL pcsc_control) (long card, /* Prototypes. */ static int pcsc_vendor_specific_init (int slot); -static int pcsc_get_status (int slot, unsigned int *status); +static int pcsc_get_status (int slot, unsigned int *status, int on_wire); static int reset_pcsc_reader (int slot); static int apdu_get_status_internal (int slot, int hang, unsigned int *status, int on_wire); @@ -665,9 +665,10 @@ reset_ct_reader (int slot) static int -ct_get_status (int slot, unsigned int *status) +ct_get_status (int slot, unsigned int *status, int on_wire) { (void)slot; + (void)on_wire; /* The status we returned is wrong but we don't care because ctAPI is not anymore required. */ *status = APDU_CARD_USABLE|APDU_CARD_PRESENT|APDU_CARD_ACTIVE; @@ -929,11 +930,12 @@ dump_pcsc_reader_status (int slot) #ifndef NEED_PCSC_WRAPPER static int -pcsc_get_status_direct (int slot, unsigned int *status) +pcsc_get_status_direct (int slot, unsigned int *status, int on_wire) { long err; struct pcsc_readerstate_s rdrstates[1]; + (void)on_wire; memset (rdrstates, 0, sizeof *rdrstates); rdrstates[0].reader = reader_table[slot].rdrname; rdrstates[0].current_state = PCSC_STATE_UNAWARE; @@ -992,7 +994,7 @@ pcsc_get_status_direct (int slot, unsigned int *status) #ifdef NEED_PCSC_WRAPPER static int -pcsc_get_status_wrapped (int slot, unsigned int *status) +pcsc_get_status_wrapped (int slot, unsigned int *status, int on_wire) { long err; reader_table_t slotp; @@ -1002,6 +1004,7 @@ pcsc_get_status_wrapped (int slot, unsigned int *status) unsigned char buffer[16]; int sw = SW_HOST_CARD_IO_ERROR; + (void)on_wire; slotp = reader_table + slot; if (slotp->pcsc.req_fd == -1 @@ -1101,12 +1104,12 @@ pcsc_get_status_wrapped (int slot, unsigned int *status) static int -pcsc_get_status (int slot, unsigned int *status) +pcsc_get_status (int slot, unsigned int *status, int on_wire) { #ifdef NEED_PCSC_WRAPPER - return pcsc_get_status_wrapped (slot, status); + return pcsc_get_status_wrapped (slot, status, on_wire); #else - return pcsc_get_status_direct (slot, status); + return pcsc_get_status_direct (slot, status, on_wire); #endif } @@ -1705,7 +1708,7 @@ reset_pcsc_reader_wrapped (int slot) slotp->atrlen = len; /* Read the status so that IS_T0 will be set. */ - pcsc_get_status (slot, &dummy_status); + pcsc_get_status (slot, &dummy_status, 1); return 0; @@ -2184,7 +2187,7 @@ open_pcsc_reader_wrapped (const char *portstr) pcsc_vendor_specific_init (slot); /* Read the status so that IS_T0 will be set. */ - pcsc_get_status (slot, &dummy_status); + pcsc_get_status (slot, &dummy_status, 1); dump_reader_status (slot); unlock_slot (slot); @@ -2471,12 +2474,12 @@ set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg) static int -get_status_ccid (int slot, unsigned int *status) +get_status_ccid (int slot, unsigned int *status, int on_wire) { int rc; int bits; - rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits); + rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits, on_wire); if (rc) return rc; @@ -2718,13 +2721,14 @@ reset_rapdu_reader (int slot) static int -my_rapdu_get_status (int slot, unsigned int *status) +my_rapdu_get_status (int slot, unsigned int *status, int on_wire) { int err; reader_table_t slotp; rapdu_msg_t msg = NULL; int oldslot; + (void)on_wire; slotp = reader_table + slot; oldslot = rapdu_set_reader (slotp->rapdu.handle, slot); @@ -3565,20 +3569,8 @@ apdu_get_status_internal (int slot, int hang, unsigned int *status, int on_wire) if ((sw = hang? lock_slot (slot) : trylock_slot (slot))) return sw; - /* If the card (with its lower-level driver) doesn't require - GET_STATUS on wire (because it supports INTERRUPT transfer for - status change, or it's a token which has a card always inserted), - no need to send on wire. */ - if (!on_wire && !reader_table[slot].require_get_status) - { - unlock_slot (slot); - if (status) - *status = (APDU_CARD_USABLE|APDU_CARD_ACTIVE); - return 0; - } - if (reader_table[slot].get_status_reader) - sw = reader_table[slot].get_status_reader (slot, &s); + sw = reader_table[slot].get_status_reader (slot, &s, on_wire); unlock_slot (slot); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 305c9d2f4..7124c6e7a 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -2708,7 +2708,7 @@ ccid_poll (ccid_driver_t handle) /* Note that this function won't return the error codes NO_CARD or CARD_INACTIVE */ int -ccid_slot_status (ccid_driver_t handle, int *statusbits) +ccid_slot_status (ccid_driver_t handle, int *statusbits, int on_wire) { int rc; unsigned char msg[100]; @@ -2719,6 +2719,16 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) if (handle->powered_off) return CCID_DRIVER_ERR_NO_READER; + /* If the card (with its lower-level driver) doesn't require + GET_STATUS on wire (because it supports INTERRUPT transfer for + status change, or it's a token which has a card always inserted), + no need to send on wire. */ + if (!on_wire && !ccid_require_get_status (handle)) + { + *statusbits = 0; + return 0; + } + retry: msg[0] = PC_to_RDR_GetSlotStatus; msg[5] = 0; /* slot */ @@ -2935,7 +2945,7 @@ ccid_get_atr (ccid_driver_t handle, }; /* First check whether a card is available. */ - rc = ccid_slot_status (handle, &statusbits); + rc = ccid_slot_status (handle, &statusbits, 1); if (rc) return rc; if (statusbits == 2) diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index cff3f198f..b6da30c07 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -128,7 +128,7 @@ int ccid_shutdown_reader (ccid_driver_t handle); int ccid_close_reader (ccid_driver_t handle); int ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen); -int ccid_slot_status (ccid_driver_t handle, int *statusbits); +int ccid_slot_status (ccid_driver_t handle, int *statusbits, int on_wire); int ccid_transceive (ccid_driver_t handle, const unsigned char *apdu, size_t apdulen, unsigned char *resp, size_t maxresplen, size_t *nresp);