Commit 998835d5 authored by Colin Leroy's avatar Colin Leroy Committed by Greg Kroah-Hartman

[PATCH] USB: fix cdc-acm as it is still (differently) broken

parent c3998736
...@@ -583,44 +583,50 @@ static int acm_probe (struct usb_interface *intf, ...@@ -583,44 +583,50 @@ static int acm_probe (struct usb_interface *intf,
cfacm = dev->actconfig; cfacm = dev->actconfig;
for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) { /* We know we're probe()d with the control interface. */
ifcom = intf->cur_altsetting;
if (usb_interface_claimed(cfacm->interface[j]) ||
usb_interface_claimed(cfacm->interface[j + 1]))
continue;
/* We know we're probe()d with the control interface. /* ACM doesn't guarantee the data interface is
* FIXME ACM doesn't guarantee the data interface is
* adjacent to the control interface, or that if one * adjacent to the control interface, or that if one
* is there it's not for call management ... so use * is there it's not for call management ... so find
* the cdc union descriptor whenever there is one. * it
*/ */
ifcom = intf->cur_altsetting; for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
if (intf == cfacm->interface[j]) {
ifdata = cfacm->interface[j + 1]->cur_altsetting;
data = cfacm->interface[j + 1];
} else if (intf == cfacm->interface[j + 1]) {
ifdata = cfacm->interface[j]->cur_altsetting; ifdata = cfacm->interface[j]->cur_altsetting;
data = cfacm->interface[j]; data = cfacm->interface[j];
} else
continue;
if (ifdata->desc.bInterfaceClass != 10 || ifdata->desc.bNumEndpoints < 2)
continue;
if (ifdata->desc.bInterfaceClass == 10 &&
ifdata->desc.bNumEndpoints == 2) {
epctrl = &ifcom->endpoint[0].desc; epctrl = &ifcom->endpoint[0].desc;
epread = &ifdata->endpoint[0].desc; epread = &ifdata->endpoint[0].desc;
epwrite = &ifdata->endpoint[1].desc; epwrite = &ifdata->endpoint[1].desc;
if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 || if ((epctrl->bEndpointAddress & 0x80) != 0x80 ||
(epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || (epctrl->bmAttributes & 3) != 3 ||
(epread->bmAttributes & 3) != 2 ||
(epwrite->bmAttributes & 3) != 2 ||
((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
continue; goto next_interface;
if ((epread->bEndpointAddress & 0x80) != 0x80) { if ((epread->bEndpointAddress & 0x80) != 0x80) {
epread = &ifdata->endpoint[1].desc; epread = &ifdata->endpoint[1].desc;
epwrite = &ifdata->endpoint[0].desc; epwrite = &ifdata->endpoint[0].desc;
} }
dbg("found data interface at %d\n", j);
break;
} else {
next_interface:
ifdata = NULL;
data = NULL;
}
}
/* there's been a problem */
if (!ifdata) {
dbg("interface not found (%p)\n", ifdata);
return -ENODEV;
}
for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
if (acm_table[minor]) { if (acm_table[minor]) {
...@@ -696,16 +702,21 @@ static int acm_probe (struct usb_interface *intf, ...@@ -696,16 +702,21 @@ static int acm_probe (struct usb_interface *intf,
acm->line.databits = 8; acm->line.databits = 8;
acm_set_line(acm, &acm->line); acm_set_line(acm, &acm->line);
usb_driver_claim_interface(&acm_driver, data, acm); if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) {
err("claim failed");
usb_free_urb(acm->ctrlurb);
usb_free_urb(acm->readurb);
usb_free_urb(acm->writeurb);
kfree(acm);
kfree(buf);
return j;
}
tty_register_device(acm_tty_driver, minor, &intf->dev); tty_register_device(acm_tty_driver, minor, &intf->dev);
acm_table[minor] = acm; acm_table[minor] = acm;
usb_set_intfdata (intf, acm); usb_set_intfdata (intf, acm);
return 0; return 0;
}
return -EIO;
} }
static void acm_disconnect(struct usb_interface *intf) static void acm_disconnect(struct usb_interface *intf)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment