[svn] GnuPG - r5080 - trunk/scd
svn author wk
cvs at cvs.gnupg.org
Thu Jul 16 17:55:00 CEST 2009
Author: wk
Date: 2009-07-16 17:54:59 +0200 (Thu, 16 Jul 2009)
New Revision: 5080
Modified:
trunk/scd/ChangeLog
trunk/scd/apdu.c
trunk/scd/apdu.h
trunk/scd/app.c
trunk/scd/ccid-driver.c
trunk/scd/command.c
trunk/scd/scdaemon.c
Log:
Add code to better handle unplugging of a reader.
Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/ChangeLog 2009-07-16 15:54:59 UTC (rev 5080)
@@ -1,3 +1,17 @@
+2009-07-16 Werner Koch <wk at 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 at g10code.com>
* ccid-driver.c (struct ccid_driver_s): Add fields last_progress,
Modified: trunk/scd/apdu.c
===================================================================
--- trunk/scd/apdu.c 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/apdu.c 2009-07-16 15:54:59 UTC (rev 5080)
@@ -1853,7 +1853,7 @@
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 @@
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. */
Modified: trunk/scd/apdu.h
===================================================================
--- trunk/scd/apdu.h 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/apdu.h 2009-07-16 15:54:59 UTC (rev 5080)
@@ -94,6 +94,7 @@
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);
Modified: trunk/scd/app.c
===================================================================
--- trunk/scd/app.c 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/app.c 2009-07-16 15:54:59 UTC (rev 5080)
@@ -367,10 +367,10 @@
}
/* 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);
Modified: trunk/scd/ccid-driver.c
===================================================================
--- trunk/scd/ccid-driver.c 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/ccid-driver.c 2009-07-16 15:54:59 UTC (rev 5080)
@@ -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 @@
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 @@
/* 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 @@
{
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 @@
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));
+ {
+ 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);
}
Modified: trunk/scd/command.c
===================================================================
--- trunk/scd/command.c 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/command.c 2009-07-16 15:54:59 UTC (rev 5080)
@@ -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,8 +2161,14 @@
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;
}
Modified: trunk/scd/scdaemon.c
===================================================================
--- trunk/scd/scdaemon.c 2009-07-16 07:40:16 UTC (rev 5079)
+++ trunk/scd/scdaemon.c 2009-07-16 15:54:59 UTC (rev 5080)
@@ -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 @@
void
scd_exit (int rc)
{
+ apdu_prepare_exit ();
#if 0
#warning no update_random_seed_file
update_random_seed_file();
More information about the Gnupg-commits
mailing list