[Pcsclite-cvs-commit] r5473 - in /trunk/Drivers/ccid/src: ccid_usb.c ccid_usb.h

rousseau at users.alioth.debian.org rousseau at users.alioth.debian.org
Tue Jan 4 09:52:27 UTC 2011


Author: rousseau
Date: Tue Jan  4 09:52:26 2011
New Revision: 5473

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=5473
Log:
Add and use get_ccid_device_descriptor() to get the CCID descriptor
including a fix for bogus readers (Oz776, Reiner SCT and bludrive II)

Thanks to Diego Elio Pettenò and Dario Leone for the patch

Modified:
    trunk/Drivers/ccid/src/ccid_usb.c
    trunk/Drivers/ccid/src/ccid_usb.h

Modified: trunk/Drivers/ccid/src/ccid_usb.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ccid_usb.c?rev=5473&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ccid_usb.c (original)
+++ trunk/Drivers/ccid/src/ccid_usb.c Tue Jan  4 09:52:26 2011
@@ -335,6 +335,7 @@
 				const struct libusb_interface *usb_interface = NULL;
 				int interface;
 				int num = 0;
+				const unsigned char *device_descriptor;
 
 #ifdef USE_COMPOSITE_AS_MULTISLOT
 				static int static_interface = 1;
@@ -463,12 +464,12 @@
 					continue;
 				}
 
-				if (usb_interface->altsetting->extra_length != 54)
+				device_descriptor = get_ccid_device_descriptor(usb_interface);
+				if (NULL == device_descriptor)
 				{
 					(void)libusb_close(dev_handle);
-					DEBUG_CRITICAL4("Extra field for %d/%d has a wrong length: %d",
-						bus_number, device_address,
-						usb_interface->altsetting->extra_length);
+					DEBUG_CRITICAL3("Unable to find the device descriptor for %d/%d",
+						bus_number, device_address);
 					return STATUS_UNSUCCESSFUL;
 				}
 
@@ -535,23 +536,22 @@
 				usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq;
 				usbDevice[reader_index].ccid.readerID =
 					(desc.idVendor << 16) + desc.idProduct;
-				usbDevice[reader_index].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
+				usbDevice[reader_index].ccid.dwFeatures = dw2i(device_descriptor, 40);
 				usbDevice[reader_index].ccid.wLcdLayout =
-					(usb_interface->altsetting->extra[51] << 8) +
-					usb_interface->altsetting->extra[50];
-				usbDevice[reader_index].ccid.bPINSupport = usb_interface->altsetting->extra[52];
-				usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
-				usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(usb_interface->altsetting->extra, 28);
-				usbDevice[reader_index].ccid.dwDefaultClock = dw2i(usb_interface->altsetting->extra, 10);
-				usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);
-				usbDevice[reader_index].ccid.bMaxSlotIndex = usb_interface->altsetting->extra[4];
+					(device_descriptor[51] << 8) + device_descriptor[50];
+				usbDevice[reader_index].ccid.bPINSupport = device_descriptor[52];
+				usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(device_descriptor, 44);
+				usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(device_descriptor, 28);
+				usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10);
+				usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23);
+				usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4];
 				usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
 				usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
 				usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, config_desc, num);
 				usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol;
 				usbDevice[reader_index].ccid.bNumEndpoints = usb_interface->altsetting->bNumEndpoints;
 				usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
-				usbDevice[reader_index].ccid.bVoltageSupport = usb_interface->altsetting->extra[5];
+				usbDevice[reader_index].ccid.bVoltageSupport = device_descriptor[5];
 				usbDevice[reader_index].ccid.sIFD_serial_number = NULL;
 				if (desc.iSerialNumber)
 				{
@@ -750,6 +750,47 @@
 
 /*****************************************************************************
  *
+ *					get_ccid_device_descriptor
+ *
+ ****************************************************************************/
+const unsigned char *get_ccid_device_descriptor(const struct libusb_interface *usb_interface)
+{
+#ifdef O2MICRO_OZ776_PATCH
+	uint8_t last_endpoint;
+#endif
+
+	if (54 == usb_interface->altsetting->extra_length)
+		return usb_interface->altsetting->extra;
+
+	if (0 != usb_interface->altsetting->extra_length)
+	{
+		/* If extra_length is zero, the descriptor might be at
+		 * the end, but if it's not zero, we have a
+		 * problem. */
+		DEBUG_CRITICAL2("Extra field has a wrong length: %d",
+			usb_interface->altsetting->extra_length);
+		return NULL;
+	}
+
+#ifdef O2MICRO_OZ776_PATCH
+	/* Some devices, such as the Oz776, Reiner SCT and bludrive II
+	 * report the device descriptor at the end of the endpoint
+	 * descriptors; to support those, look for it at the end as well.
+	 */
+	last_endpoint = usb_interface->altsetting->bNumEndpoints-1;
+	if (usb_interface->altsetting->endpoint[last_endpoint].extra_length == 54)
+		return usb_interface->altsetting->endpoint[last_endpoint].extra;
+#else
+	DEBUG_CRITICAL2("Extra field has a wrong length: %d",
+		usb_interface->altsetting->extra_length);
+#endif
+
+	return NULL;
+} /* get_ccid_device_descriptor */
+
+
+/*****************************************************************************
+ *
  *					get_end_points
  *
  ****************************************************************************/
@@ -806,9 +847,6 @@
 {
 	const struct libusb_interface *usb_interface = NULL;
 	int i;
-#ifdef O2MICRO_OZ776_PATCH
-	int readerID;
-#endif
 
 	/* if multiple interfaces use the first one with CCID class type */
 	for (i = *num; i < desc->bNumInterfaces; i++)
@@ -826,32 +864,6 @@
 			break;
 		}
 	}
-
-#ifdef O2MICRO_OZ776_PATCH
-	readerID = (dev->descriptor.idVendor << 16) + dev->descriptor.idProduct;
-	if (usb_interface != NULL
-		&& ((OZ776 == readerID) || (OZ776_7772 == readerID)
-		|| (REINER_SCT == readerID) || (BLUDRIVEII_CCID == readerID))
-		&& (0 == usb_interface->altsetting->extra_length)) /* this is the bug */
-	{
-		int j;
-		for (j=0; j<usb_interface->altsetting->bNumEndpoints; j++)
-		{
-			/* find the extra[] array */
-			if (54 == usb_interface->altsetting->endpoint[j].extra_length)
-			{
-				/* get the extra[] from the endpoint */
-				usb_interface->altsetting->extra_length = 54;
-				usb_interface->altsetting->extra =
-					usb_interface->altsetting->endpoint[j].extra;
-				/* avoid double free on close */
-				usb_interface->altsetting->endpoint[j].extra = NULL;
-				usb_interface->altsetting->endpoint[j].extra_length = 0;
-				break;
-			}
-		}
-	}
-#endif
 
 	return usb_interface;
 } /* get_ccid_usb_interface */
@@ -934,7 +946,7 @@
 	n /= sizeof(int);
 
 	/* we do not get the expected number of data rates */
-	len = get_ccid_usb_interface(desc, &num)->altsetting->extra[27]; /* bNumDataRatesSupported */
+	len = get_ccid_device_descriptor(get_ccid_usb_interface(desc, &num))[27]; /* bNumDataRatesSupported */
 	if ((n != len) && len)
 	{
 		DEBUG_INFO3("Got %d data rates but was expecting %d", n, len);

Modified: trunk/Drivers/ccid/src/ccid_usb.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ccid_usb.h?rev=5473&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ccid_usb.h (original)
+++ trunk/Drivers/ccid/src/ccid_usb.h Tue Jan  4 09:52:26 2011
@@ -39,6 +39,8 @@
 /*@null@*/ const struct libusb_interface *get_ccid_usb_interface(
 	struct libusb_config_descriptor *desc, int *num);
 
+const unsigned char *get_ccid_device_descriptor(const struct libusb_interface *usb_interface);
+
 int ControlUSB(int reader_index, int requesttype, int request, int value,
 	unsigned char *bytes, unsigned int size);
 




More information about the Pcsclite-cvs-commit mailing list