w32: Also change the directory on daemon startup.
[gnupg.git] / scd / ccid-driver.c
index c10787b..9c22f51 100644 (file)
@@ -1228,7 +1228,12 @@ ccid_get_reader_list (void)
 
   if (!initialized_usb)
     {
-      libusb_init (NULL);
+      int rc;
+      if ((rc = libusb_init (NULL)))
+        {
+          DEBUGOUT_1 ("usb_init failed: %s.\n", libusb_error_name (rc));
+          return NULL;
+        }
       initialized_usb = 1;
     }
 
@@ -1292,9 +1297,17 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
   int idx = 0;
   int err = 0;
 
+  *idx_max_p = 0;
+  *t_p = NULL;
+
   if (!initialized_usb)
     {
-      libusb_init (NULL);
+      int rc;
+      if ((rc = libusb_init (NULL)))
+        {
+          DEBUGOUT_1 ("usb_init failed: %s.\n", libusb_error_name (rc));
+          return gpg_error (GPG_ERR_ENODEV);
+        }
       initialized_usb = 1;
     }
 
@@ -1373,8 +1386,6 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
 
   if (err)
     {
-      *idx_max_p = 0;
-      *t_p = NULL;
       for (i = 0; i < idx; i++)
         {
           free (ccid_dev_table[idx].ifcdesc_extra);
@@ -1476,6 +1487,7 @@ intr_cb (struct libusb_transfer *transfer)
         {
           DEBUGOUT ("CCID: card removed\n");
           handle->powered_off = 1;
+          scd_kick_the_loop ();
         }
       else
         {
@@ -1490,9 +1502,8 @@ intr_cb (struct libusb_transfer *transfer)
     device_removed:
       DEBUGOUT ("CCID: device removed\n");
       handle->powered_off = 1;
+      scd_kick_the_loop ();
     }
-
-  scd_kick_the_loop ();
 }
 
 static void
@@ -1980,7 +1991,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
       goto retry;
     }
 
-  if (buffer[0] != expected_type)
+  if (buffer[0] != expected_type && buffer[0] != RDR_to_PC_SlotStatus)
     {
       DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
       abort_cmd (handle, seqno);
@@ -2020,11 +2031,26 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
   switch ((buffer[7] & 0x03))
     {
     case 0: /* no error */ break;
-    case 1: return CCID_DRIVER_ERR_CARD_INACTIVE;
-    case 2: return CCID_DRIVER_ERR_NO_CARD;
+    case 1: rc = CCID_DRIVER_ERR_CARD_INACTIVE; break;
+    case 2: rc = CCID_DRIVER_ERR_NO_CARD; break;
     case 3: /* RFU */ break;
     }
-  return 0;
+
+  if (rc)
+    {
+      /*
+       * Communication failure by device side.
+       * Possibly, it was forcibly suspended and resumed.
+       */
+      DEBUGOUT ("CCID: card inactive/removed\n");
+      if (handle->transfer == NULL)
+        {
+          handle->powered_off = 1;
+          scd_kick_the_loop ();
+        }
+    }
+
+  return rc;
 }