[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