Re: [CDC-ACM] Linux USB "Reduced" CDC-ACM driver

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

 



Am Montag 27 April 2009 09:08:28 schrieb Vincent Del Medico:
> 2009/4/26 Oliver Neukum <oliver@xxxxxxxxxx>

> > This patch should make Linux support such devices without the
> > need for quirks. Please test.
> >
> >        Regards
> >                Oliver
> 
> Thanks Oliver, but unfortunately this doesn't work.
> 
> usb 1-1.3.2: new full speed USB device using musb_hdrc and address 5
> usb 1-1.3.2: configuration #1 chosen from 1 choice
> cdc_acm 1-1.3.2:1.0: This device cannot do calls on its own. It is no modem.
> cdc_acm 1-1.3.2:1.0: No union descriptor, giving up

Please try the attached additional patch.

	Regards
		Oliver

commit c1b80bf3ece4485493b862e83b9adb4f5ebd451e
Author: Oliver Neukum <oneukum@linux-d698.(none)>
Date:   Mon Apr 27 14:46:43 2009 +0200

    deal with device that collapse interfaces and have no union descriptor in cdc-acm

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 85956e1..8910274 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -990,8 +990,15 @@ next_desc:
 			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
 			control_interface = intf;
 		} else {
-			dev_dbg(&intf->dev,"No union descriptor, giving up\n");
-			return -ENODEV;
+			if (intf->cur_altsetting->desc.bNumEndpoints != 3) {
+				dev_dbg(&intf->dev,"No union descriptor, giving up\n");
+				return -ENODEV;
+			} else {
+				dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n");
+				combined_interfaces = 1;
+				control_interface = data_interface = intf;
+				goto look_for_collapsed_interface;
+			}
 		}
 	} else {
 		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
@@ -1013,6 +1020,7 @@ next_desc:
 			dev_err(&intf->dev, "This needs exactly 3 endpoints\n");
 			return -EINVAL;
 		}
+look_for_collapsed_interface:
 		for (i = 0; i < 3; i++) {
 			struct usb_endpoint_descriptor *ep;
 			ep = &data_interface->cur_altsetting->endpoint[i].desc;
@@ -1026,7 +1034,10 @@ next_desc:
 			else
 				return -EINVAL;
 		}
-		goto made_compressed_probe;
+		if (!epctrl || !epread || !epwrite)
+			return -ENODEV;
+		else
+			goto made_compressed_probe;
 	}
 
 skip_normal_probe:
@@ -1046,10 +1057,10 @@ skip_normal_probe:
 	}
 
 	/* Accept probe requests only for the control interface */
-	if (intf != control_interface)
+	if (!combined_interfaces && intf != control_interface)
 		return -ENODEV;
 	
-	if (usb_interface_claimed(data_interface)) { /* valid in this context */
+	if (!combined_interfaces && usb_interface_claimed(data_interface)) { /* valid in this context */
 		dev_dbg(&intf->dev,"The data interface isn't available\n");
 		return -EBUSY;
 	}

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

  Powered by Linux