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

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

 



On Sun, 28 Dec 2008 15:38:25 +0100, Oliver Neukum wrote:
> You cannot do this this way. Sharing an interface is against the spec.

I see. Thanks for that information. So a device advertising an
interface with:

      bInterfaceNumber        2
      bNumEndpoints           3
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      CDC Union:
        bMasterInterface        2
        bSlaveInterface         2 

would not be conforming to the USB standard?

> If you do a generic work around you need to verify the endpoints are
> correct.

You mean something like this?

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index d50a99f..7ce549a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -896,8 +896,8 @@ static int acm_probe (struct usb_interface *intf,
 	struct usb_interface *control_interface;
 	struct usb_interface *data_interface;
 	struct usb_endpoint_descriptor *epctrl;
-	struct usb_endpoint_descriptor *epread;
-	struct usb_endpoint_descriptor *epwrite;
+	struct usb_endpoint_descriptor *epread = NULL;
+	struct usb_endpoint_descriptor *epwrite = NULL;
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	struct acm *acm;
 	int minor;
@@ -1028,29 +1028,38 @@ skip_normal_probe:
 	if (intf != control_interface)
 		return -ENODEV;
 	
-	if (usb_interface_claimed(data_interface)) { /* valid in this context */
+	if (intf != data_interface && 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;
-
 	epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
-	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)) {
-		/* descriptors are swapped */
-		struct usb_endpoint_descriptor *t;
-		dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
-		
-		t = epread;
-		epread = epwrite;
-		epwrite = t;
+
+	/* find data endpoints */
+	i = 0;
+	if (data_interface == control_interface) {
+		dev_dbg(&intf->dev,
+			"Shared interface. That's against the spec.\n");
+		i++;		/* skip control EP */
+	}
+	while (i < data_interface->cur_altsetting->desc.bNumEndpoints) {
+		struct usb_endpoint_descriptor *ep
+			= &data_interface->cur_altsetting->endpoint[i++].desc;
+		if (usb_endpoint_xfer_bulk(ep)) {
+			if (epread == NULL && usb_endpoint_dir_in(ep))
+				epread = ep;
+			else if (epwrite == NULL && usb_endpoint_dir_out(ep))
+				epwrite = ep;
+		}
+	}
+	if (epread == NULL) {
+		err("missing input pipe\n");
+		return -EINVAL;
+	}
+	if (epwrite == NULL) {
+		err("missing output pipe\n");
+		return -EINVAL;
 	}
 	dbg("interfaces are valid");
 	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);


Thanks,
Tilman
--
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