Hi,
I am looking for testers with a CDC ACM device willing to test this patch
which makes device detection follow the standard.
TIA
Oliver
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c Fri May 28 10:48:56 2004
+++ b/drivers/usb/class/cdc-acm.c Fri May 28 10:48:56 2004
@@ -60,6 +60,8 @@
#include <linux/usb.h>
#include <asm/byteorder.h>
+#include "cdc.h"
+
/*
* Version Information
*/
@@ -572,70 +574,84 @@
static int acm_probe (struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct usb_device *dev;
+ struct union_desc *union_header = NULL;
+ u8 *buffer = intf->altsetting->extra;
+ int buflen = intf->altsetting->extralen;
+ struct usb_interface *control_interface;
+ struct usb_interface *data_interface;
+ struct usb_host_interface *ifcom = intf->cur_altsetting;
+ struct usb_host_interface *ifdata = NULL;
+ struct usb_device *usb_dev;
+
struct acm *acm;
- struct usb_host_config *cfacm;
- struct usb_interface *data = NULL;
- struct usb_host_interface *ifcom, *ifdata = NULL;
+
struct usb_endpoint_descriptor *epctrl = NULL;
struct usb_endpoint_descriptor *epread = NULL;
struct usb_endpoint_descriptor *epwrite = NULL;
- int readsize, ctrlsize, minor, j;
+
+ int minor;
+ int ctrlsize,readsize,j;
unsigned char *buf;
- dev = interface_to_usbdev (intf);
+ usb_dev = interface_to_usbdev(intf);
- cfacm = dev->actconfig;
+ if (!buffer) {
+ err("Wierd descriptor references");
+ return -EINVAL;
+ }
- /* We know we're probe()d with the control interface. */
- ifcom = intf->cur_altsetting;
+ while (buflen > 0) {
+ if (buffer [1] != USB_DT_CS_INTERFACE) {
+ err("skipping garbage");
+ goto next_desc;
+ }
+ switch (buffer [2]) {
+ case CDC_UNION_TYPE: /* we've found it */
+ if (union_header) {
+ err("More than one union descriptor, skipping
...");
+ goto next_desc;
+ }
+ union_header = (struct union_desc *)buffer;
+ break;
+ default:
+ err("Ignoring extra header");
+ break;
+ }
+next_desc:
+ buflen -= buffer[0];
+ buffer += buffer[0];
+ }
+
+ if (!union_header) {
+ err("No union descriptor, giving up");
+ return -ENODEV;
+ }
- /* ACM doesn't guarantee the data interface is
- * adjacent to the control interface, or that if one
- * is there it's not for call management ... so find
- * it
- */
- for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
- ifdata = cfacm->interface[j]->cur_altsetting;
- data = cfacm->interface[j];
+ control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+ data_interface = usb_ifnum_to_if(usb_dev, union_header->bSlaveInterface0);
+ if (!control_interface || !data_interface) {
+ err("No interfaces");
+ return -ENODEV;
+ }
- if (ifdata->desc.bInterfaceClass == USB_CLASS_CDC_DATA
- && ifdata->desc.bNumEndpoints == 2) {
+ /* workaround for buggy devices */
+ if (data_interface->cur_altsetting->desc.bInterfaceClass !=
CDC_DATA_INTERFACE_TYPE) {
+ if (control_interface->cur_altsetting->desc.bInterfaceClass ==
CDC_DATA_INTERFACE_TYPE) {
+ struct usb_interface *t;
- epctrl = &ifcom->endpoint[0].desc;
- epread = &ifdata->endpoint[0].desc;
- epwrite = &ifdata->endpoint[1].desc;
-
- if ((epctrl->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN
- || !CHECK_XFERTYPE(epctrl, USB_ENDPOINT_XFER_INT)
- || !CHECK_XFERTYPE(epread, USB_ENDPOINT_XFER_BULK)
- || !CHECK_XFERTYPE(epwrite, USB_ENDPOINT_XFER_BULK)
- || ((epread->bEndpointAddress & USB_DIR_IN)
- ^ (epwrite->bEndpointAddress & USB_DIR_IN)) !=
USB_DIR_IN) {
- /* not suitable */
- goto next_interface;
- }
-
- if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
- /* descriptors are swapped */
- epread = &ifdata->endpoint[1].desc;
- epwrite = &ifdata->endpoint[0].desc;
- }
- dev_dbg(&intf->dev, "found data interface at %d\n", j);
- break;
- } else {
-next_interface:
- ifdata = NULL;
- data = NULL;
+ dev_dbg(&intf->dev, "Unswitching descriptors.");
+ t = control_interface;
+ control_interface = data_interface;
+ data_interface = t;
}
}
+
+ ifdata = data_interface->cur_altsetting;
- /* there's been a problem */
- if (!ifdata) {
- dev_dbg(&intf->dev, "data interface not found\n");
- return -ENODEV;
+ epctrl = &ifcom->endpoint[0].desc;
+ epread = &ifcom->endpoint[0].desc;
+ epwrite = &ifdata->endpoint[1].desc;
- }
for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
if (acm_table[minor]) {
@@ -653,10 +669,10 @@
ctrlsize = epctrl->wMaxPacketSize;
readsize = epread->wMaxPacketSize;
acm->writesize = epwrite->wMaxPacketSize;
- acm->control = intf;
- acm->data = data;
+ acm->control = control_interface;
+ acm->data = data_interface;
acm->minor = minor;
- acm->dev = dev;
+ acm->dev = usb_dev;
acm->bh.func = acm_rx_tasklet;
acm->bh.data = (unsigned long) acm;
@@ -693,18 +709,18 @@
return -ENOMEM;
}
- usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev,
epctrl->bEndpointAddress),
+ usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev,
epctrl->bEndpointAddress),
buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
- usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev,
epread->bEndpointAddress),
+ usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev,
epread->bEndpointAddress),
buf += ctrlsize, readsize, acm_read_bulk, acm);
acm->readurb->transfer_flags |= URB_NO_FSBR;
- usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev,
epwrite->bEndpointAddress),
+ usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev,
epwrite->bEndpointAddress),
buf += readsize, acm->writesize, acm_write_bulk, acm);
acm->writeurb->transfer_flags |= URB_NO_FSBR;
- if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) {
+ if ( (j = usb_driver_claim_interface(&acm_driver, data_interface, acm)) != 0) {
err("claim failed");
usb_free_urb(acm->ctrlurb);
usb_free_urb(acm->readurb);
diff -Nru a/drivers/usb/class/cdc.h b/drivers/usb/class/cdc.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/cdc.h Fri May 28 10:48:56 2004
@@ -0,0 +1,13 @@
+/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
+struct union_desc {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bDescriptorSubType;
+
+ u8 bMasterInterface0;
+ u8 bSlaveInterface0;
+ /* ... and there could be other slave interfaces */
+} __attribute__ ((packed));
+
+#define CDC_UNION_TYPE 0x06
+#define CDC_DATA_INTERFACE_TYPE 0x0a
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g.
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel