mirror of
git://git.gnupg.org/gnupg.git
synced 2025-05-19 09:02:22 +02: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:
parent
ccfb5e0a7d
commit
36b98b595d
56
scd/apdu.c
56
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 *
|
static void *
|
||||||
pcsc_thread (void *arg)
|
pcsc_thread (void *arg)
|
||||||
{
|
{
|
||||||
long err;
|
long err;
|
||||||
struct pcsc_readerstate_s rdrstates[MAX_READER];
|
struct pcsc_readerstate_s rdrstates[MAX_READER];
|
||||||
|
HANDLE context;
|
||||||
|
|
||||||
(void)arg;
|
(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);
|
npth_mutex_lock (&reader_table_lock);
|
||||||
while (pcsc.count)
|
while (pcsc.count)
|
||||||
{
|
{
|
||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
int any_change = 0;
|
||||||
|
|
||||||
pcsc.count++;
|
memset (rdrstates, 0, sizeof (struct pcsc_readerstate_s) * MAX_READER);
|
||||||
memset (rdrstates, 0, sizeof *rdrstates);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_READER; i++)
|
for (i = 0; i < MAX_READER; i++)
|
||||||
if (reader_table[i].used)
|
if (reader_table[i].used)
|
||||||
{
|
{
|
||||||
rdrstates[j].reader = reader_table[i].rdrname;
|
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;
|
rdrstates[j].current_state = reader_table[i].pcsc.current_state;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
@ -1112,17 +1122,48 @@ pcsc_thread (void *arg)
|
|||||||
#ifdef USE_NPTH
|
#ifdef USE_NPTH
|
||||||
npth_unprotect ();
|
npth_unprotect ();
|
||||||
#endif
|
#endif
|
||||||
err = pcsc_get_status_change (pcsc.context, STATUS_CHANGE_TIMEOUT,
|
err = pcsc_get_status_change (context, STATUS_CHANGE_TIMEOUT,
|
||||||
rdrstates, j);
|
rdrstates, j);
|
||||||
#ifdef USE_NPTH
|
#ifdef USE_NPTH
|
||||||
npth_protect ();
|
npth_protect ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
npth_mutex_lock (&reader_table_lock);
|
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);
|
for (j--; j >= 0; j--)
|
||||||
if (!--pcsc.count)
|
{
|
||||||
release_pcsc_context ();
|
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);
|
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].get_status_reader = pcsc_get_status;
|
||||||
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
||||||
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
||||||
|
reader_table[slot].require_get_status = 0;
|
||||||
|
|
||||||
dump_reader_status (slot);
|
dump_reader_status (slot);
|
||||||
unlock_slot (slot);
|
unlock_slot (slot);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user