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,
cfacm = dev->actconfig;
for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) {
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. */
ifcom = intf->cur_altsetting;
/* We know we're probe()d with the control interface.
* FIXME ACM doesn't guarantee the data interface is
/* 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 use
* the cdc union descriptor whenever there is one.
* is there it's not for call management ... so find
* it
*/
ifcom = intf->cur_altsetting;
if (intf == cfacm->interface[j]) {
ifdata = cfacm->interface[j + 1]->cur_altsetting;
data = cfacm->interface[j + 1];
} else if (intf == cfacm->interface[j + 1]) {
for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
ifdata = cfacm->interface[j]->cur_altsetting;
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;
epread = &ifdata->endpoint[0].desc;
epwrite = &ifdata->endpoint[1].desc;
if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
(epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
if ((epctrl->bEndpointAddress & 0x80) != 0x80 ||
(epctrl->bmAttributes & 3) != 3 ||
(epread->bmAttributes & 3) != 2 ||
(epwrite->bmAttributes & 3) != 2 ||
((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
continue;
goto next_interface;
if ((epread->bEndpointAddress & 0x80) != 0x80) {
epread = &ifdata->endpoint[1].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++);
if (acm_table[minor]) {
......@@ -696,16 +702,21 @@ static int acm_probe (struct usb_interface *intf,
acm->line.databits = 8;
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);
acm_table[minor] = acm;
usb_set_intfdata (intf, acm);
return 0;
}
return -EIO;
}
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