mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Add code to better handle unplugging of a reader.
This commit is contained in:
parent
e535e3fccc
commit
e49d808e1f
@ -1,3 +1,17 @@
|
||||
2009-07-16 Werner Koch <wk@g10code.com>
|
||||
|
||||
* command.c (update_reader_status_file): Test for unplugged reader.
|
||||
(TEST_CARD_REMOVAL): Ditto.
|
||||
* app.c (select_application): Ditto.
|
||||
* ccid-driver.c (bulk_out): Return CCID_DRIVER_ERR_NO_READER if a
|
||||
reader was unplugged.
|
||||
(struct ccid_driver_s): Turn nonnull_nad into an unsigned char.
|
||||
Turn apdu_level, auto_ifsd, powered_off, has_pinpad into
|
||||
bitfields. Add enodev_seen.
|
||||
* apdu.c (apdu_prepare_exit): New.
|
||||
(get_status_ccid): Return the status word and nut just -1.
|
||||
* scdaemon.c (scd_exit): Call it.
|
||||
|
||||
2009-07-13 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (struct ccid_driver_s): Add fields last_progress,
|
||||
|
29
scd/apdu.c
29
scd/apdu.c
@ -1853,7 +1853,7 @@ get_status_ccid (int slot, unsigned int *status)
|
||||
|
||||
rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits);
|
||||
if (rc)
|
||||
return -1;
|
||||
return rc;
|
||||
|
||||
if (bits == 0)
|
||||
*status = (APDU_CARD_USABLE|APDU_CARD_PRESENT|APDU_CARD_ACTIVE);
|
||||
@ -2523,6 +2523,33 @@ apdu_close_reader (int slot)
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/* Function suitable for a cleanup function to close all reader. It
|
||||
should not be used if the reader will be opened again. The reason
|
||||
for implementing this to properly close USB devices so that they
|
||||
will startup the next time without error. */
|
||||
void
|
||||
apdu_prepare_exit (void)
|
||||
{
|
||||
static int sentinel;
|
||||
int slot;
|
||||
|
||||
if (!sentinel)
|
||||
{
|
||||
sentinel = 1;
|
||||
for (slot = 0; slot < MAX_READER; slot++)
|
||||
if (reader_table[slot].used)
|
||||
{
|
||||
apdu_disconnect (slot);
|
||||
if (reader_table[slot].close_reader)
|
||||
reader_table[slot].close_reader (slot);
|
||||
reader_table[slot].used = 0;
|
||||
}
|
||||
sentinel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Shutdown a reader; that is basically the same as a close but keeps
|
||||
the handle ready for later use. A apdu_reset_reader or apdu_connect
|
||||
should be used to get it active again. */
|
||||
|
@ -94,6 +94,7 @@ int apdu_open_remote_reader (const char *portstr,
|
||||
void *closefnc_value);
|
||||
int apdu_shutdown_reader (int slot);
|
||||
int apdu_close_reader (int slot);
|
||||
void apdu_prepare_exit (void);
|
||||
int apdu_enum_reader (int slot, int *used);
|
||||
unsigned char *apdu_get_atr (int slot, size_t *atrlen);
|
||||
|
||||
|
@ -367,10 +367,10 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
||||
}
|
||||
|
||||
/* For certain error codes, there is no need to try more. */
|
||||
if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
|
||||
if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
|
||||
|| gpg_err_code (err) == GPG_ERR_ENODEV)
|
||||
goto leave;
|
||||
|
||||
|
||||
/* Figure out the application to use. */
|
||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
@ -244,16 +245,18 @@ struct ccid_driver_s
|
||||
int seqno;
|
||||
unsigned char t1_ns;
|
||||
unsigned char t1_nr;
|
||||
int nonnull_nad;
|
||||
int auto_ifsd;
|
||||
unsigned char nonnull_nad;
|
||||
int max_ifsd;
|
||||
int ifsd;
|
||||
int ifsc;
|
||||
int powered_off;
|
||||
int has_pinpad;
|
||||
int apdu_level; /* Reader supports short APDU level exchange.
|
||||
With a value of 2 short and extended level is
|
||||
supported.*/
|
||||
unsigned char apdu_level:2; /* Reader supports short APDU level
|
||||
exchange. With a value of 2 short
|
||||
and extended level is supported.*/
|
||||
unsigned int auto_ifsd:1;
|
||||
unsigned int powered_off:1;
|
||||
unsigned int has_pinpad:2;
|
||||
unsigned int enodev_seen:1;
|
||||
|
||||
time_t last_progress; /* Last time we sent progress line. */
|
||||
|
||||
/* The progress callback and its first arg as supplied to
|
||||
@ -1423,7 +1426,7 @@ scan_or_find_devices (int readerno, const char *readerid,
|
||||
/* Set the level of debugging to LEVEL and return the old level. -1
|
||||
just returns the old level. A level of 0 disables debugging, 1
|
||||
enables debugging, 2 enables additional tracing of the T=1
|
||||
protocol, 3 additionally enables debuggng for GetSlotStatus, other
|
||||
protocol, 3 additionally enables debugging for GetSlotStatus, other
|
||||
values are not yet defined.
|
||||
|
||||
Note that libusb may provide its own debugging feature which is
|
||||
@ -1763,6 +1766,11 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* No need to continue and clutter the log withy USB error if we
|
||||
ever got an ENODEV. */
|
||||
if (handle->enodev_seen)
|
||||
return CCID_DRIVER_ERR_NO_READER;
|
||||
|
||||
if (debug_level && (!no_debug || debug_level >= 3))
|
||||
{
|
||||
switch (msglen? msg[0]:0)
|
||||
@ -1823,8 +1831,27 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
|
||||
5000 /* ms timeout */);
|
||||
if (rc == msglen)
|
||||
return 0;
|
||||
#ifdef ENODEV
|
||||
if (rc == -(ENODEV))
|
||||
{
|
||||
/* The Linux libusb returns a negative error value. Catch
|
||||
the most important one. */
|
||||
errno = ENODEV;
|
||||
rc = -1;
|
||||
}
|
||||
#endif /*ENODEV*/
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno));
|
||||
#ifdef ENODEV
|
||||
if (errno == ENODEV)
|
||||
{
|
||||
handle->enodev_seen = 1;
|
||||
return CCID_DRIVER_ERR_NO_READER;
|
||||
}
|
||||
#endif /*ENODEV*/
|
||||
}
|
||||
else
|
||||
DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc);
|
||||
}
|
||||
|
@ -54,12 +54,14 @@
|
||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||
|
||||
|
||||
/* Macro to flag a removed card. */
|
||||
/* Macro to flag a removed card. ENODEV is also tested to catch teh
|
||||
case of a removed reader. */
|
||||
#define TEST_CARD_REMOVAL(c,r) \
|
||||
do { \
|
||||
int _r = (r); \
|
||||
if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
|
||||
|| gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
|
||||
|| gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \
|
||||
|| gpg_err_code (_r) == GPG_ERR_ENODEV ) \
|
||||
update_card_removed ((c)->reader_slot, 1); \
|
||||
} while (0)
|
||||
|
||||
@ -2159,7 +2161,13 @@ update_reader_status_file (int set_card_removed_flag)
|
||||
continue; /* Not valid or reader not yet open. */
|
||||
|
||||
sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
|
||||
if (sw_apdu)
|
||||
if (sw_apdu == SW_HOST_NO_READER)
|
||||
{
|
||||
/* Most likely the _reader_ has been unplugged. */
|
||||
status = 0;
|
||||
changed = ss->changed;
|
||||
}
|
||||
else if (sw_apdu)
|
||||
{
|
||||
/* Get status failed. Ignore that. */
|
||||
continue;
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "i18n.h"
|
||||
#include "sysutils.h"
|
||||
#include "app-common.h"
|
||||
#include "apdu.h"
|
||||
#include "ccid-driver.h"
|
||||
#include "mkdtemp.h"
|
||||
#include "gc-opt-flags.h"
|
||||
@ -858,6 +859,7 @@ main (int argc, char **argv )
|
||||
void
|
||||
scd_exit (int rc)
|
||||
{
|
||||
apdu_prepare_exit ();
|
||||
#if 0
|
||||
#warning no update_random_seed_file
|
||||
update_random_seed_file();
|
||||
|
Loading…
x
Reference in New Issue
Block a user