aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2021-05-13 07:22:59 +0000
committerNIIBE Yutaka <[email protected]>2021-05-13 07:25:43 +0000
commit36b98b595df410e8dee35133d507740669966754 (patch)
tree715bb3676406b2841a0436ade0c38de5fe6b8291
parentscd: Use SCardStatus for pcsc_get_status. (diff)
downloadgnupg-36b98b595df410e8dee35133d507740669966754.tar.gz
gnupg-36b98b595df410e8dee35133d507740669966754.zip
scd: Use the thread to monitor PC/SC card status change.
* scd/apdu.c (pcsc_thread): Use an independent context. Fix initialization of RDRSTATES. Call scd_kick_the_loop when detecting any change. (open_pcsc_reader): No requirement for periodical check. -- GnuPG-bug-id: 5437 Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--scd/apdu.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index 5e37e2289..053a2b12a 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -1082,28 +1082,38 @@ pcsc_vendor_specific_init (int slot)
}
-#define STATUS_CHANGE_TIMEOUT 2500
+#define STATUS_CHANGE_TIMEOUT 7500
static void *
pcsc_thread (void *arg)
{
long err;
struct pcsc_readerstate_s rdrstates[MAX_READER];
+ HANDLE context;
(void)arg;
+ err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL,
+ &context);
+ if (err)
+ {
+ log_error ("pcsc_establish_context failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ return NULL;
+ }
npth_mutex_lock (&reader_table_lock);
while (pcsc.count)
{
int i, j = 0;
+ int any_change = 0;
- pcsc.count++;
- memset (rdrstates, 0, sizeof *rdrstates);
+ memset (rdrstates, 0, sizeof (struct pcsc_readerstate_s) * MAX_READER);
for (i = 0; i < MAX_READER; i++)
if (reader_table[i].used)
{
rdrstates[j].reader = reader_table[i].rdrname;
+ rdrstates[j].user_data = (void *)(uintptr_t)i;
rdrstates[j].current_state = reader_table[i].pcsc.current_state;
j++;
}
@@ -1112,17 +1122,48 @@ pcsc_thread (void *arg)
#ifdef USE_NPTH
npth_unprotect ();
#endif
- err = pcsc_get_status_change (pcsc.context, STATUS_CHANGE_TIMEOUT,
+ err = pcsc_get_status_change (context, STATUS_CHANGE_TIMEOUT,
rdrstates, j);
#ifdef USE_NPTH
npth_protect ();
#endif
npth_mutex_lock (&reader_table_lock);
+ if (err)
+ {
+ if (err != PCSC_E_TIMEOUT)
+ log_error ("pcsc_get_status_change failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ continue;
+ }
- log_assert (pcsc.count > 0);
- if (!--pcsc.count)
- release_pcsc_context ();
+ for (j--; j >= 0; j--)
+ {
+ if ((rdrstates[j].event_state & PCSC_STATE_CHANGED))
+ {
+ int slot = (int)(uintptr_t)rdrstates[j].user_data;
+ reader_table[slot].pcsc.current_state =
+ (rdrstates[j].event_state & ~PCSC_STATE_CHANGED);
+ any_change = 1;
+ }
+
+ if (DBG_READER)
+ log_debug
+ ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n",
+ (rdrstates[j].event_state & PCSC_STATE_IGNORE)? " ignore":"",
+ (rdrstates[j].event_state & PCSC_STATE_CHANGED)? " changed":"",
+ (rdrstates[j].event_state & PCSC_STATE_UNKNOWN)? " unknown":"",
+ (rdrstates[j].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"",
+ (rdrstates[j].event_state & PCSC_STATE_EMPTY)? " empty":"",
+ (rdrstates[j].event_state & PCSC_STATE_PRESENT)? " present":"",
+ (rdrstates[j].event_state & PCSC_STATE_ATRMATCH)? " atr":"",
+ (rdrstates[j].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"",
+ (rdrstates[j].event_state & PCSC_STATE_INUSE)? " inuse":"",
+ (rdrstates[j].event_state & PCSC_STATE_MUTE)? " mute":"" );
+ }
+
+ if (any_change)
+ scd_kick_the_loop ();
}
npth_mutex_unlock (&reader_table_lock);
@@ -1288,6 +1329,7 @@ open_pcsc_reader (const char *rdrname)
reader_table[slot].get_status_reader = pcsc_get_status;
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
+ reader_table[slot].require_get_status = 0;
dump_reader_status (slot);
unlock_slot (slot);