1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-12 22:11:29 +02:00

scd,pcsc: Use a single context.

* scd/apdu.c (pcsc): New variable.
(struct reader_table_s): Remove pcsc.context from member.
(pcsc_get_status, connect_pcsc_card): Use pcsc.context.
(close_pcsc_reader): Release pcsc.context here with reference count.
(pcsc_init): New.
(open_pcsc_reader): Don't call pcsc_establish_context here.  Call
close_pcsc_reader instead of pcsc_release_context.
(apdu_open_reader): Call pcsc_init if needed.
(apdu_init): Initialize pcsc.count and pcsc.context.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2019-09-10 15:51:05 +09:00
parent f44aa290c1
commit 1080e91efd

View File

@ -76,6 +76,12 @@ typedef unsigned int pcsc_dword_t;
typedef unsigned long pcsc_dword_t; typedef unsigned long pcsc_dword_t;
#endif #endif
/* PC/SC context to access readers. Shared among all readers. */
static struct pcsc {
int count;
long context;
} pcsc;
/* A structure to collect information pertaining to one reader /* A structure to collect information pertaining to one reader
slot. */ slot. */
struct reader_table_s { struct reader_table_s {
@ -101,7 +107,6 @@ struct reader_table_s {
ccid_driver_t handle; ccid_driver_t handle;
} ccid; } ccid;
struct { struct {
long context;
long card; long card;
pcsc_dword_t protocol; pcsc_dword_t protocol;
pcsc_dword_t verify_ioctl; pcsc_dword_t verify_ioctl;
@ -652,9 +657,7 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire)
memset (rdrstates, 0, sizeof *rdrstates); memset (rdrstates, 0, sizeof *rdrstates);
rdrstates[0].reader = reader_table[slot].rdrname; rdrstates[0].reader = reader_table[slot].rdrname;
rdrstates[0].current_state = reader_table[slot].pcsc.current_state; rdrstates[0].current_state = reader_table[slot].pcsc.current_state;
err = pcsc_get_status_change (reader_table[slot].pcsc.context, err = pcsc_get_status_change (pcsc.context, 0, rdrstates, 1);
0,
rdrstates, 1);
if (err == PCSC_E_TIMEOUT) if (err == PCSC_E_TIMEOUT)
err = 0; /* Timeout is no error here. */ err = 0; /* Timeout is no error here. */
if (err) if (err)
@ -788,7 +791,12 @@ control_pcsc (int slot, pcsc_dword_t ioctl_code,
static int static int
close_pcsc_reader (int slot) close_pcsc_reader (int slot)
{ {
pcsc_release_context (reader_table[slot].pcsc.context); (void)slot;
if (--pcsc.count == 0)
{
pcsc_release_context (pcsc.context);
pcsc.context = -1;
}
return 0; return 0;
} }
@ -807,7 +815,7 @@ connect_pcsc_card (int slot)
reader_table[slot].atrlen = 0; reader_table[slot].atrlen = 0;
reader_table[slot].is_t0 = 0; reader_table[slot].is_t0 = 0;
err = pcsc_connect (reader_table[slot].pcsc.context, err = pcsc_connect (pcsc.context,
reader_table[slot].rdrname, reader_table[slot].rdrname,
PCSC_SHARE_EXCLUSIVE, PCSC_SHARE_EXCLUSIVE,
PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
@ -826,10 +834,11 @@ connect_pcsc_card (int slot)
pcsc_dword_t readerlen, atrlen; pcsc_dword_t readerlen, atrlen;
pcsc_dword_t card_state, card_protocol; pcsc_dword_t card_state, card_protocol;
pcsc.count++;
pcsc_vendor_specific_init (slot); pcsc_vendor_specific_init (slot);
atrlen = DIM (reader_table[0].atr); atrlen = DIM (reader_table[0].atr);
readerlen = sizeof reader -1 ; readerlen = sizeof reader - 1;
err = pcsc_status (reader_table[slot].pcsc.card, err = pcsc_status (reader_table[slot].pcsc.card,
reader, &readerlen, reader, &readerlen,
&card_state, &card_protocol, &card_state, &card_protocol,
@ -1042,6 +1051,21 @@ pcsc_vendor_specific_init (int slot)
return 0; return 0;
} }
static int
pcsc_init (void)
{
long err;
err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, &pcsc.context);
if (err)
{
log_error ("pcsc_establish_context failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
return -1;
}
return 0;
}
/* Open the PC/SC reader without using the wrapper. Returns -1 on /* Open the PC/SC reader without using the wrapper. Returns -1 on
error or a slot number for the reader. */ error or a slot number for the reader. */
@ -1059,40 +1083,28 @@ open_pcsc_reader (const char *portstr)
if (slot == -1) if (slot == -1)
return -1; return -1;
/* Fixme: Allocating a context for each slot is not required. One reader_table[slot].used = 0;
global context should be sufficient. */ unlock_slot (slot);
err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL,
&reader_table[slot].pcsc.context);
if (err)
{
log_error ("pcsc_establish_context failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
reader_table[slot].used = 0;
unlock_slot (slot);
return -1;
}
err = pcsc_list_readers (reader_table[slot].pcsc.context, err = pcsc_list_readers (pcsc.context, NULL, NULL, &nreader);
NULL, NULL, &nreader);
if (!err) if (!err)
{ {
list = xtrymalloc (nreader+1); /* Better add 1 for safety reasons. */ list = xtrymalloc (nreader+1); /* Better add 1 for safety reasons. */
if (!list) if (!list)
{ {
log_error ("error allocating memory for reader list\n"); log_error ("error allocating memory for reader list\n");
pcsc_release_context (reader_table[slot].pcsc.context); close_pcsc_reader (0);
reader_table[slot].used = 0; reader_table[slot].used = 0;
unlock_slot (slot); unlock_slot (slot);
return -1 /*SW_HOST_OUT_OF_CORE*/; return -1 /*SW_HOST_OUT_OF_CORE*/;
} }
err = pcsc_list_readers (reader_table[slot].pcsc.context, err = pcsc_list_readers (pcsc.context, NULL, list, &nreader);
NULL, list, &nreader);
} }
if (err) if (err)
{ {
log_error ("pcsc_list_readers failed: %s (0x%lx)\n", log_error ("pcsc_list_readers failed: %s (0x%lx)\n",
pcsc_error_string (err), err); pcsc_error_string (err), err);
pcsc_release_context (reader_table[slot].pcsc.context); close_pcsc_reader (0);
reader_table[slot].used = 0; reader_table[slot].used = 0;
xfree (list); xfree (list);
unlock_slot (slot); unlock_slot (slot);
@ -1123,7 +1135,7 @@ open_pcsc_reader (const char *portstr)
if (!reader_table[slot].rdrname) if (!reader_table[slot].rdrname)
{ {
log_error ("error allocating memory for reader name\n"); log_error ("error allocating memory for reader name\n");
pcsc_release_context (reader_table[slot].pcsc.context); close_pcsc_reader (0);
reader_table[slot].used = 0; reader_table[slot].used = 0;
unlock_slot (slot); unlock_slot (slot);
return -1; return -1;
@ -2113,6 +2125,11 @@ apdu_open_reader (struct dev_list *dl, int app_empty)
else else
#endif #endif
{ /* PC/SC readers. */ { /* PC/SC readers. */
if (pcsc.context < 0)
if (pcsc_init () < 0)
return -1;
if (app_empty && dl->idx == 0) if (app_empty && dl->idx == 0)
{ {
dl->idx++; dl->idx++;
@ -3299,6 +3316,9 @@ apdu_init (void)
gpg_error_t err; gpg_error_t err;
int i; int i;
pcsc.count = 0;
pcsc.context = -1;
if (npth_mutex_init (&reader_table_lock, NULL)) if (npth_mutex_init (&reader_table_lock, NULL))
goto leave; goto leave;