[PATCH RFC] cdc_acm: handle shared control/data interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I am still fighting with a Siemens Gigaset M34 USB DECT adapter
(ID 0681:0026) advertizing, among others, four CDC ACM shared
control/data interfaces. The current probe code in cdc-acm.c refuses
to touch these because of the test for
usb_interface_claimed(data_interface) in line 1031. Also, the endpoint
assignments following that test don't look right for the case where
data_interface == control_interface.

Does the following patch look sensible, or am I completely on
the wrong track?

Thanks,
Tilman

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index d50a99f..8d38813 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1027,22 +1027,35 @@ skip_normal_probe:
 	/* Accept probe requests only for the control interface */
 	if (intf != control_interface)
 		return -ENODEV;
-	
-	if (usb_interface_claimed(data_interface)) { /* valid in this context */
-		dev_dbg(&intf->dev,"The data interface isn't available\n");
-		return -EBUSY;
-	}
-
-
-	if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
-		return -EINVAL;
 
+	/* find endpoints */
 	epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
-	epread = &data_interface->cur_altsetting->endpoint[0].desc;
-	epwrite = &data_interface->cur_altsetting->endpoint[1].desc;
-
+	if (data_interface == control_interface) {
+		/* shared interface */
+		if (data_interface->cur_altsetting->desc.bNumEndpoints < 3)
+			return -EINVAL;
+		dev_dbg(&intf->dev, "Shared interface, shifting data EPs.\n");
+		epread = &data_interface->cur_altsetting->endpoint[1].desc;
+		epwrite = &data_interface->cur_altsetting->endpoint[2].desc;
+	} else {
+		/* separate interfaces */
+		if (usb_interface_claimed(data_interface)) {
+			/* valid in this context */
+			dev_dbg(&intf->dev,
+				"The data interface isn't available\n");
+			return -EBUSY;
+		}
+		if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
+			return -EINVAL;
+		epread = &data_interface->cur_altsetting->endpoint[0].desc;
+		epwrite = &data_interface->cur_altsetting->endpoint[1].desc;
+	}
 
 	/* workaround for switched endpoints */
+	if (usb_endpoint_dir_in(epread) == usb_endpoint_dir_in(epwrite)) {
+		err("Bad data endpoint directions.\n");
+		return -EINVAL;
+	}
 	if (!usb_endpoint_dir_in(epread)) {
 		/* descriptors are swapped */
 		struct usb_endpoint_descriptor *t;
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux