From f8b8b6aac2ca1cb34d7a346aee1d874e7650557b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 8 Mar 2018 16:51:51 +0900 Subject: [PATCH] scd: Fix status check when using PC/SC. * scd/apdu.c (struct reader_table_s): Add field of current_state. (new_reader_slot): Initialize current_state. (pcsc_get_status): Keep the status in READER_TABLE array. Return SW_HOST_NO_READER when PCSC_STATE_CHANGED. * scd/scdaemon.c (handle_connections): Silence a warning. -- To detect some change of card status, including suspend/resume possibly, SCardGetStatusChange should be used keeping the dwCurrentState field. This change could improve situation for suspend/resume with Yubikey on Windows. Even not, this is doing the Right Thing. Signed-off-by: NIIBE Yutaka --- scd/apdu.c | 15 ++++++++++++--- scd/scdaemon.c | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/scd/apdu.c b/scd/apdu.c index c50afbde2..6758e69e8 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -119,6 +119,7 @@ struct reader_table_s { pcsc_dword_t modify_ioctl; int pinmin; int pinmax; + pcsc_dword_t current_state; } pcsc; #ifdef USE_G10CODE_RAPDU struct { @@ -453,6 +454,7 @@ new_reader_slot (void) reader_table[reader].pcsc.modify_ioctl = 0; reader_table[reader].pcsc.pinmin = -1; reader_table[reader].pcsc.pinmax = -1; + reader_table[reader].pcsc.current_state = PCSC_STATE_UNAWARE; return reader; } @@ -652,12 +654,12 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) (void)on_wire; memset (rdrstates, 0, sizeof *rdrstates); rdrstates[0].reader = reader_table[slot].rdrname; - rdrstates[0].current_state = PCSC_STATE_UNAWARE; + rdrstates[0].current_state = reader_table[slot].pcsc.current_state; err = pcsc_get_status_change (reader_table[slot].pcsc.context, 0, rdrstates, 1); if (err == PCSC_E_TIMEOUT) - err = 0; /* Timeout is no error error here. */ + err = 0; /* Timeout is no error here. */ if (err) { log_error ("pcsc_get_status_change failed: %s (0x%lx)\n", @@ -665,6 +667,9 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) return pcsc_error_to_sw (err); } + reader_table[slot].pcsc.current_state = + (rdrstates[0].event_state & ~PCSC_STATE_CHANGED); + /* log_debug */ /* ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", */ /* (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", */ @@ -701,7 +706,11 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire) *status |= APDU_CARD_USABLE; #endif - return 0; + if (!on_wire && (rdrstates[0].event_state & PCSC_STATE_CHANGED)) + /* Event like sleep/resume occurs, which requires RESET. */ + return SW_HOST_NO_READER; + else + return 0; } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index cebeea9d3..91b559925 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -1348,6 +1348,8 @@ handle_connections (int listen_fd) FD_SET (pipe_fd[0], &read_fdset); if (max_fd < pipe_fd[0]) max_fd = pipe_fd[0]; +#else + (void)max_fd; #endif #ifndef HAVE_W32_SYSTEM