pcsc-wrapper dying problem + patch

Bob Dunlop bob at xyzzy.org.uk
Fri Aug 18 11:08:14 CEST 2006


Hi,

I've been having problems with scdaemon or more correctly the pcsc-wrapper
program dying on me after which no communication with the smartcard has
been possible until the gpg-agent is restarted.

I'm using gnupg 1.9.21 and pcsc-lite 1.3.1-r1 with a SCR335 reader on a
Gentoo linux system.

I've traced the problem to the fact that the USB hub my reader is attached
to (my terminal) is powered down whenever the screen goes into deep sleep.
When power is restored pcsc-wrapper gets confused on the next card access
and terminates.

The following is a patch to pcsc-wrapper.c to fix this problem.  Actually
most of it is minor code cleanups I'd made while investigating the problem,
the actual fix is the very last entry which ignores a PCSC_E_INVALID_HANDLE
error when attempting a pcsc_disconnect().


--- pcsc-wrapper.c-orig	2006-06-20 16:32:59.000000000 +0000
+++ pcsc-wrapper.c	2006-08-18 08:40:48.000000000 +0000
@@ -373,6 +373,16 @@
 }
   
 
+/* Release the card context and tidy a few related vars */
+static void
+release_context_and_tidy ()
+{
+      pcsc_release_context (pcsc_context);
+      free (current_rdrname);
+      current_rdrname = NULL;
+      pcsc_card = 0;
+      pcsc_protocol = 0;
+}
 
 
 /* Handle a open request.  The argument is expected to be a string
@@ -471,9 +481,7 @@
     {
       fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n",
                pcsc_error_string (err), err);
-      pcsc_release_context (pcsc_context);
-      free (current_rdrname);
-      current_rdrname = NULL;
+      release_context_and_tidy ();
       request_failed (err);
       return;
     }      
@@ -524,9 +532,7 @@
       return;
     }
 
-  free (current_rdrname);
-  current_rdrname = NULL;
-  pcsc_release_context (pcsc_context);
+  release_context_and_tidy ();
 
   request_succeeded (NULL, 0);
 }
@@ -567,17 +573,20 @@
     }
 
   status = 0;
-  if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) )
-    status |= 2;
-  if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) )
-    status |= 4;
-  /* We indicate a useful card if it is not in use by another
-     application.  This is because we only use exclusive access
-     mode.  */
-  if ( (status & 6) == 6
-       && !(rdrstates[0].event_state & PCSC_STATE_INUSE) )
-    status |= 1;
-  
+  if ( !(rdrstates[0].event_state & PCSC_STATE_UNKNOWN) )
+    {
+      if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) )
+        status |= 2;
+      if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) )
+        status |= 4;
+      /* We indicate a useful card if it is not in use by another
+         application.  This is because we only use exclusive access
+         mode.  */
+      if ( (status & 6) == 6
+           && !(rdrstates[0].event_state & PCSC_STATE_INUSE) )
+        status |= 1;
+    } 
+
   /* First word is identical to the one used by apdu.c. */
   buf[0] = 0;
   buf[1] = 0;
@@ -618,6 +627,8 @@
   if (pcsc_card)
     {
       err = pcsc_disconnect (pcsc_card, PCSC_LEAVE_CARD);
+      if (err == 0x80100003)    /* Invalid handle.  (already disconnected) */
+        err = 0;
       if (err)
         {
           fprintf (stderr, PGM": pcsc_disconnect failed: %s (0x%lx)\n",
-- 
        Bob Dunlop



More information about the Gnupg-devel mailing list