summaryrefslogtreecommitdiffstats
path: root/scd/apdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/apdu.c')
-rw-r--r--scd/apdu.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index f88d97035..0037c476c 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -141,11 +141,12 @@ struct reader_table_s {
} rapdu;
#endif /*USE_G10CODE_RAPDU*/
char *rdrname; /* Name of the connected reader or NULL if unknown. */
- int is_t0; /* True if we know that we are running T=0. */
- int is_spr532; /* True if we know that the reader is a SPR532. */
- int pinpad_varlen_supported; /* True if we know that the reader
- supports variable length pinpad
- input. */
+ unsigned int is_t0:1; /* True if we know that we are running T=0. */
+ unsigned int is_spr532:1; /* True if we know that the reader is a SPR532. */
+ unsigned int pinpad_varlen_supported:1; /* True if we know that the reader
+ supports variable length pinpad
+ input. */
+ unsigned int require_get_status:1;
unsigned char atr[33];
size_t atrlen; /* A zero length indicates that the ATR has
not yet been read; i.e. the card is not
@@ -470,6 +471,7 @@ new_reader_slot (void)
reader_table[reader].is_t0 = 1;
reader_table[reader].is_spr532 = 0;
reader_table[reader].pinpad_varlen_supported = 0;
+ reader_table[reader].require_get_status = 1;
#ifdef NEED_PCSC_WRAPPER
reader_table[reader].pcsc.req_fd = -1;
reader_table[reader].pcsc.rsp_fd = -1;
@@ -2572,6 +2574,7 @@ open_ccid_reader (struct dev_list *dl)
{
int err;
int slot;
+ int require_get_status;
reader_table_t slotp;
slot = new_reader_slot ();
@@ -2596,6 +2599,8 @@ open_ccid_reader (struct dev_list *dl)
err = 0;
}
+ require_get_status = ccid_require_get_status (slotp->ccid.handle);
+
reader_table[slot].close_reader = close_ccid_reader;
reader_table[slot].reset_reader = reset_ccid_reader;
reader_table[slot].get_status_reader = get_status_ccid;
@@ -2608,6 +2613,7 @@ open_ccid_reader (struct dev_list *dl)
/* Our CCID reader code does not support T=0 at all, thus reset the
flag. */
reader_table[slot].is_t0 = 0;
+ reader_table[slot].require_get_status = require_get_status;
dump_reader_status (slot);
unlock_slot (slot);
@@ -2970,22 +2976,15 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
return 0;
}
-int
+void
apdu_dev_list_finish (struct dev_list *dl)
{
- int all_have_intr_endp;
-
#ifdef HAVE_LIBUSB
if (dl->ccid_table)
- all_have_intr_endp = ccid_dev_scan_finish (dl->ccid_table, dl->idx_max);
- else
- all_have_intr_endp = 0;
-#else
- all_have_intr_endp = 0;
+ ccid_dev_scan_finish (dl->ccid_table, dl->idx_max);
#endif
xfree (dl);
npth_mutex_unlock (&reader_table_lock);
- return all_have_intr_endp;
}
@@ -3347,8 +3346,11 @@ apdu_enum_reader (int slot, int *used)
/* Connect a card. This is used to power up the card and make sure
that an ATR is available. Depending on the reader backend it may
- return an error for an inactive card or if no card is
- available. */
+ return an error for an inactive card or if no card is available.
+ Return -1 on error. Return 1 if reader requires get_status to
+ watch card removal. Return 0 if it's a token (always with a card),
+ or it supports INTERRUPT endpoint to watch card removal.
+ */
int
apdu_connect (int slot)
{
@@ -3362,7 +3364,7 @@ apdu_connect (int slot)
{
if (DBG_READER)
log_debug ("leave: apdu_connect => SW_HOST_NO_DRIVER\n");
- return SW_HOST_NO_DRIVER;
+ return -1;
}
/* Only if the access method provides a connect function we use it.
@@ -3393,10 +3395,19 @@ apdu_connect (int slot)
else if ((status & APDU_CARD_PRESENT) && !(status & APDU_CARD_ACTIVE))
sw = SW_HOST_CARD_INACTIVE;
+ if (sw == SW_HOST_CARD_INACTIVE)
+ {
+ /* Try power it up again. */
+ sw = apdu_reset (slot);
+ }
+
if (DBG_READER)
log_debug ("leave: apdu_connect => sw=0x%x\n", sw);
- return sw;
+ if (sw)
+ return -1;
+
+ return reader_table[slot].require_get_status;
}