gnupg/g10 (ChangeLog ccid-driver.c)

cvs user wk cvs at cvs.gnupg.org
Wed Mar 16 19:57:32 CET 2005


    Date: Wednesday, March 16, 2005 @ 20:10:54
  Author: wk
    Path: /cvs/gnupg/gnupg/g10

Modified: ChangeLog ccid-driver.c

(parse_ccid_descriptor): Make SCM workaround
reader type specific.
(scan_or_find_devices): Do not check the interface subclass in the
SPR532 kludge, as this depends on the firmware version.
(ccid_get_atr): Get the Slot status first.  This solves the
problem with readers hanging on recent Linux 2.6.x.
(bulk_in): Add argument TIMEOUT and changed all callers to pass an
appropriate one.  Change the standard timeout from 10 to 5 seconds.
(ccid_slot_status): Add a retry code with an initial short timeout.
(do_close_reader): Do an usb_reset before closing the reader.


---------------+
 ChangeLog     |   13 ++++++++
 ccid-driver.c |   91 ++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 76 insertions(+), 28 deletions(-)


Index: gnupg/g10/ChangeLog
diff -u gnupg/g10/ChangeLog:1.705 gnupg/g10/ChangeLog:1.706
--- gnupg/g10/ChangeLog:1.705	Mon Mar 14 21:41:20 2005
+++ gnupg/g10/ChangeLog	Wed Mar 16 20:10:54 2005
@@ -1,3 +1,16 @@
+2005-03-16  Werner Koch  <wk at g10code.com>
+
+	* ccid-driver.c (parse_ccid_descriptor): Make SCM workaround
+	reader type specific.
+	(scan_or_find_devices): Do not check the interface subclass in the
+	SPR532 kludge, as this depends on the firmware version.
+	(ccid_get_atr): Get the Slot status first.  This solves the
+	problem with readers hanging on recent Linux 2.6.x.
+	(bulk_in): Add argument TIMEOUT and changed all callers to pass an
+	appropriate one.  Change the standard timeout from 10 to 5 seconds.
+	(ccid_slot_status): Add a retry code with an initial short timeout.
+	(do_close_reader): Do an usb_reset before closing the reader.
+
 2005-03-14  Werner Koch  <wk at g10code.com>
 
 	* card-util.c (card_status): Use isotimestamp and not the
Index: gnupg/g10/ccid-driver.c
diff -u gnupg/g10/ccid-driver.c:1.21 gnupg/g10/ccid-driver.c:1.22
--- gnupg/g10/ccid-driver.c:1.21	Thu Jan 27 11:30:27 2005
+++ gnupg/g10/ccid-driver.c	Wed Mar 16 20:10:54 2005
@@ -1,5 +1,5 @@
 /* ccid-driver.c - USB ChipCardInterfaceDevices driver
- *	Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *	Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
  *      Written by Werner Koch.
  *
  * This file is part of GnuPG.
@@ -52,7 +52,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $Id: ccid-driver.c,v 1.21 2005/01/27 10:30:27 wk Exp $
+ * $Date: 2005/03/16 19:10:54 $
  */
 
 
@@ -223,7 +223,7 @@
                                  int use_crc);
 static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen);
 static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
-                    size_t *nread, int expected_type, int seqno);
+                    size_t *nread, int expected_type, int seqno, int timeout);
 
 /* Convert a little endian stored 4 byte value into an unsigned
    integer. */
@@ -403,7 +403,7 @@
   if (buf[49] == 0xff)
     DEBUGOUT_CONT ("echo\n");
   else
-    DEBUGOUT_1 ("  %02X\n", buf[48]);
+    DEBUGOUT_CONT_1 ("  %02X\n", buf[48]);
 
   DEBUGOUT (  "  wlcdLayout           ");
   if (!buf[50] && !buf[51])
@@ -446,12 +446,20 @@
      send a frame of n*wMaxPacketSize back to us.  Given that
      wMaxPacketSize is 64 for these readers we set the IFSD to a value
      lower than that:
-        64 - 10 CCID header -  4 T1frame - 2 reserved = 48 */
+        64 - 10 CCID header -  4 T1frame - 2 reserved = 48
+     Product Ids:
+	 0xe001 - SCR 331 
+	 0x5111 - SCR 331-DI 
+	 0x5115 - SCR 335 
+	 0xe003 - SPR 532 
+  */
   if (handle->id_vendor == VENDOR_SCM
-      /* FIXME: check whether it is the same
-                firmware version for all drivers.  */
-      && handle->bcd_device < 0x0519
-      && handle->max_ifsd > 48)
+      && handle->max_ifsd > 48      
+      && (  (handle->id_product == 0xe001 && handle->bcd_device < 0x0516)
+          ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620)
+          ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519)
+          ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504)
+          ))
     {
       DEBUGOUT ("enabling workaround for buggy SCM readers\n");
       handle->max_ifsd = 48;
@@ -699,9 +707,7 @@
                                   && ifcdesc->bInterfaceProtocol == 0)
                               || (ifcdesc->bInterfaceClass == 255
                                   && dev->descriptor.idVendor == 0x04e6
-                                  && dev->descriptor.idProduct == 0xe003
-                                  && ifcdesc->bInterfaceSubClass == 1
-                                  && ifcdesc->bInterfaceProtocol == 1)))
+                                  && dev->descriptor.idProduct == 0xe003)))
                         {
                           idev = usb_open (dev);
                           if (!idev)
@@ -974,11 +980,13 @@
       
       rc = bulk_out (handle, msg, msglen);
       if (!rc)
-        bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno);
+        bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
+                 seqno, 2000);
       handle->powered_off = 1;
     }
   if (handle->idev)
     {
+      usb_reset (handle->idev);
       usb_release_interface (handle->idev, handle->ifc_no);
       usb_close (handle->idev);
       handle->idev = NULL;
@@ -1102,10 +1110,10 @@
    BUFFER and return the actual read number if bytes in NREAD. SEQNO
    is the sequence number used to send the request and EXPECTED_TYPE
    the type of message we expect. Does checks on the ccid
-   header. Returns 0 on success. */
+   header. TIMEOUT is the timeout value in ms. Returns 0 on success. */
 static int
 bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
-         size_t *nread, int expected_type, int seqno)
+         size_t *nread, int expected_type, int seqno, int timeout)
 {
   int i, rc;
   size_t msglen;
@@ -1117,9 +1125,7 @@
   rc = usb_bulk_read (handle->idev, 
                       handle->ep_bulk_in,
                       buffer, length,
-                      10000 /* ms timeout */ );
-  /* Fixme: instead of using a 10 second timeout we should better
-     handle the timeout here and retry if appropriate.  */
+                      timeout);
   if (rc < 0)
     {
       DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno));
@@ -1175,7 +1181,7 @@
 }
 
 
-/* Note that this fucntion won't return the error codes NO_CARD or
+/* Note that this function won't return the error codes NO_CARD or
    CARD_INACTIVE */
 static int 
 send_escape_cmd (ccid_driver_t handle,
@@ -1206,7 +1212,8 @@
   rc = bulk_out (handle, msg, msglen);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
+                seqno, 5000);
 
   return rc;
 }
@@ -1276,7 +1283,9 @@
   unsigned char msg[100];
   size_t msglen;
   unsigned char seqno;
+  int retries = 0;
 
+ retry:
   msg[0] = PC_to_RDR_GetSlotStatus;
   msg[5] = 0; /* slot */
   msg[6] = seqno = handle->seqno++;
@@ -1288,7 +1297,21 @@
   rc = bulk_out (handle, msg, 10);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
+                seqno, retries? 1000 : 200);
+  if (rc == CCID_DRIVER_ERR_CARD_IO_ERROR && retries < 3)
+    {
+      if (!retries)
+        {
+          fprintf (stderr, "CALLING USB_CLEAR_HALT\n");
+          usb_clear_halt (handle->idev, handle->ep_bulk_in);
+          usb_clear_halt (handle->idev, handle->ep_bulk_out);
+        }
+      else
+          fprintf (stderr, "RETRYING AGIAN\n");
+      retries++;
+      goto retry;
+    }
   if (rc && rc != CCID_DRIVER_ERR_NO_CARD
       && rc != CCID_DRIVER_ERR_CARD_INACTIVE)
     return rc;
@@ -1303,6 +1326,7 @@
               unsigned char *atr, size_t maxatrlen, size_t *atrlen)
 {
   int rc;
+  int statusbits;
   unsigned char msg[100];
   unsigned char *tpdu;
   size_t msglen, tpdulen;
@@ -1311,6 +1335,15 @@
   unsigned int edc;
   int i;
 
+  /* First check whether a card is available.  */
+  rc = ccid_slot_status (handle, &statusbits);
+  if (rc)
+    return rc;
+  if (statusbits == 2)
+    return CCID_DRIVER_ERR_NO_CARD;
+
+  /* For an inactive and also for an active card, issue the PowerOn
+     command to get the ATR.  */
   msg[0] = PC_to_RDR_IccPowerOn;
   msg[5] = 0; /* slot */
   msg[6] = seqno = handle->seqno++;
@@ -1323,7 +1356,8 @@
   rc = bulk_out (handle, msg, msglen);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
+                seqno, 5000);
   if (rc)
     return rc;
 
@@ -1367,7 +1401,8 @@
   if (rc)
     return rc;
   /* Note that we ignore the error code on purpose. */
-  bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno);
+  bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
+           seqno, 5000);
 
   handle->t1_ns = 0;
   handle->t1_nr = 0;
@@ -1414,7 +1449,7 @@
 
 
       rc = bulk_in (handle, msg, sizeof msg, &msglen,
-                    RDR_to_PC_DataBlock, seqno);
+                    RDR_to_PC_DataBlock, seqno, 5000);
       if (rc)
         return rc;
       
@@ -1510,7 +1545,7 @@
 
   msg = recv_buffer;
   rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                RDR_to_PC_DataBlock, seqno);
+                RDR_to_PC_DataBlock, seqno, 5000);
   if (rc)
     return rc;
       
@@ -1683,7 +1718,7 @@
 
       msg = recv_buffer;
       rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                    RDR_to_PC_DataBlock, seqno);
+                    RDR_to_PC_DataBlock, seqno, 5000);
       if (rc)
         return rc;
       
@@ -1692,7 +1727,7 @@
       
       if (tpdulen < 4) 
         {
-          usb_clear_halt (handle->idev, 0x82);
+          usb_clear_halt (handle->idev, handle->ep_bulk_in);
           return CCID_DRIVER_ERR_ABORTED; 
         }
 #ifdef DEBUG_T1
@@ -1960,7 +1995,7 @@
   
   msg = recv_buffer;
   rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                RDR_to_PC_DataBlock, seqno);
+                RDR_to_PC_DataBlock, seqno, 5000);
   if (rc)
     return rc;
   




More information about the Gnupg-commits mailing list