1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-17 14:07:03 +01:00

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 <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2021-05-13 16:22:59 +09:00
parent ccfb5e0a7d
commit 36b98b595d

View File

@ -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);