[Pcsclite-cvs-commit] r3350 - /trunk/Drivers/ccid/src/ccid_usb.c

rousseau at users.alioth.debian.org rousseau at users.alioth.debian.org
Thu Mar 19 13:48:10 UTC 2009


Author: rousseau
Date: Thu Mar 19 13:48:10 2009
New Revision: 3350

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=3350
Log:
OpenUSBByName(): support more than one CCID interface per USB device
with the libhal scheme

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

Modified: trunk/Drivers/ccid/src/ccid_usb.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/Drivers/ccid/src/ccid_usb.c?rev=3350&op=diff
==============================================================================
--- trunk/Drivers/ccid/src/ccid_usb.c (original)
+++ trunk/Drivers/ccid/src/ccid_usb.c Thu Mar 19 13:48:10 2009
@@ -155,6 +155,8 @@
 	unsigned int device_vendor, device_product;
 #endif
 	char *dirname = NULL, *filename = NULL;
+	char *serial = NULL;
+	int interface_number = -1;
 	static int previous_reader_index = -1;
 
 	DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, device);
@@ -202,6 +204,55 @@
 
 				DEBUG_CRITICAL2("can't parse using libusb scheme: %s", device);
 			}
+		}
+
+		/* format usb:%04x/%04x:libhal:%s
+		 * with %s set to
+		 * /org/freedesktop/Hal/devices/usb_device_VID_PID_SERIAL_ifX
+		 * VID is VendorID
+		 * PID is ProductID
+		 * SERIAL is device serial number
+		 * X is the interface number
+		 */
+		if ((dirname = strstr(device, "libhal:")) != NULL)
+		{
+			char *p;
+
+#define HAL_HEADER "usb_device_"
+
+			/* parse the hal string */
+			if (
+				/* search the last '/' char */
+				(p = strrchr(dirname, '/'))
+
+				/* if the string starts with "usb_device_" we continue */
+				&& (0 == strncmp(++p, HAL_HEADER, sizeof(HAL_HEADER)-1))
+				/* skip the HAL header */
+				&& (p += sizeof(HAL_HEADER)-1)
+
+				/* search the '_' before PID */
+				&& (p = strchr(++p, '_'))
+
+				/* search the '_' before SERIAL */
+				&& (p = strchr(++p, '_'))
+				&& (serial = p+1)
+
+				/* search the '_' before ifX */
+				&& (p = strchr(++p, '_'))
+				&& (0 == strncmp(++p, "if", 2))
+			   )
+			{
+				/* terminate the serial number C-string */
+				*(p-1) = '\0';
+
+				/* convert the interface number */
+				interface_number = atoi(p+2);
+			}
+			else
+				DEBUG_CRITICAL2("can't parse using libhal scheme: %s", device);
+
+			/* dirname was just a temporary variable */
+			dirname = NULL;
 		}
 	}
 #endif
@@ -352,12 +403,16 @@
 						}
 						else
 						{
-							DEBUG_INFO3("USB device %s/%s already in use."
-								" Checking next one.",
-								bus->dirname, dev->filename);
+							/* if an interface number is given by HAL we
+							 * continue with this device. */
+							if (-1 == interface_number)
+							{
+								DEBUG_INFO3("USB device %s/%s already in use."
+									" Checking next one.",
+									bus->dirname, dev->filename);
+								continue;
+							}
 						}
-
-						continue;
 					}
 
 					DEBUG_COMM3("Trying to open USB bus/device: %s/%s",
@@ -381,12 +436,14 @@
 						return STATUS_UNSUCCESSFUL;
 					}
 
+again:
 					usb_interface = get_ccid_usb_interface(dev, &num);
 					if (usb_interface == NULL)
 					{
 						(void)usb_close(dev_handle);
-						DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
-							bus->dirname, dev->filename);
+						if (0 == num)
+							DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
+								bus->dirname, dev->filename);
 						return STATUS_UNSUCCESSFUL;
 					}
 
@@ -398,6 +455,19 @@
 					}
 
 					interface = usb_interface->altsetting->bInterfaceNumber;
+					if (interface_number >= 0 && interface != interface_number)
+					{
+						/* an interface was specified and it is not the
+						 * current one */
+						DEBUG_INFO3("Wrong interface for USB device %s/%s."
+							" Checking next one.", bus->dirname, dev->filename);
+
+						/* check for another CCID interface on the same device */
+						num++;
+
+						goto again;
+					}
+
 					if (usb_claim_interface(dev_handle, interface) < 0)
 					{
 						(void)usb_close(dev_handle);




More information about the Pcsclite-cvs-commit mailing list