Commit 7e0cb221 authored by Colin Leroy's avatar Colin Leroy Committed by Greg Kroah-Hartman

[PATCH] USB: cosmetic fixes for cdc-acm

parent c8ae88da
...@@ -567,6 +567,8 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_ ...@@ -567,6 +567,8 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
* USB probe and disconnect routines. * USB probe and disconnect routines.
*/ */
#define CHECK_XFERTYPE(descr, xfer_type) (((descr)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == xfer_type)
static int acm_probe (struct usb_interface *intf, static int acm_probe (struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -583,143 +585,150 @@ static int acm_probe (struct usb_interface *intf, ...@@ -583,143 +585,150 @@ static int acm_probe (struct usb_interface *intf,
dev = interface_to_usbdev (intf); dev = interface_to_usbdev (intf);
cfacm = dev->actconfig; cfacm = dev->actconfig;
/* We know we're probe()d with the control interface. */ /* We know we're probe()d with the control interface. */
ifcom = intf->cur_altsetting; ifcom = intf->cur_altsetting;
/* 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 * adjacent to the control interface, or that if one
* is there it's not for call management ... so find * is there it's not for call management ... so find
* it * it
*/ */
for (j = 0; j < cfacm->desc.bNumInterfaces; j++) { for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
ifdata = cfacm->interface[j]->cur_altsetting; ifdata = cfacm->interface[j]->cur_altsetting;
data = cfacm->interface[j]; data = cfacm->interface[j];
if (ifdata->desc.bInterfaceClass == 10 && if (ifdata->desc.bInterfaceClass == USB_CLASS_CDC_DATA
ifdata->desc.bNumEndpoints == 2) { && ifdata->desc.bNumEndpoints == 2) {
epctrl = &ifcom->endpoint[0].desc;
epread = &ifdata->endpoint[0].desc; epctrl = &ifcom->endpoint[0].desc;
epwrite = &ifdata->endpoint[1].desc; epread = &ifdata->endpoint[0].desc;
epwrite = &ifdata->endpoint[1].desc;
if ((epctrl->bEndpointAddress & 0x80) != 0x80 ||
(epctrl->bmAttributes & 3) != 3 || if ((epctrl->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN
(epread->bmAttributes & 3) != 2 || || !CHECK_XFERTYPE(epctrl, USB_ENDPOINT_XFER_INT)
(epwrite->bmAttributes & 3) != 2 || || !CHECK_XFERTYPE(epread, USB_ENDPOINT_XFER_BULK)
((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) || !CHECK_XFERTYPE(epwrite, USB_ENDPOINT_XFER_BULK)
goto next_interface; || ((epread->bEndpointAddress & USB_DIR_IN)
^ (epwrite->bEndpointAddress & USB_DIR_IN)) != USB_DIR_IN) {
if ((epread->bEndpointAddress & 0x80) != 0x80) { /* not suitable */
epread = &ifdata->endpoint[1].desc; goto next_interface;
epwrite = &ifdata->endpoint[0].desc; }
}
dbg("found data interface at %d\n", j); if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
break; /* descriptors are swapped */
} else { epread = &ifdata->endpoint[1].desc;
next_interface: epwrite = &ifdata->endpoint[0].desc;
ifdata = NULL;
data = NULL;
}
} }
dev_dbg(&intf->dev, "found data interface at %d\n", j);
break;
} else {
next_interface:
ifdata = NULL;
data = NULL;
}
}
/* there's been a problem */ /* there's been a problem */
if (!ifdata) { if (!ifdata) {
dbg("interface not found (%p)\n", ifdata); dev_dbg(&intf->dev, "data interface not found\n");
return -ENODEV; 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]) {
err("no more free acm devices"); err("no more free acm devices");
return -ENODEV; return -ENODEV;
} }
if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
err("out of memory"); dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
return -ENOMEM; return -ENOMEM;
} }
memset(acm, 0, sizeof(struct acm));
memset(acm, 0, sizeof(struct acm));
ctrlsize = epctrl->wMaxPacketSize;
readsize = epread->wMaxPacketSize; ctrlsize = epctrl->wMaxPacketSize;
acm->writesize = epwrite->wMaxPacketSize; readsize = epread->wMaxPacketSize;
acm->control = intf; acm->writesize = epwrite->wMaxPacketSize;
acm->data = data; acm->control = intf;
acm->minor = minor; acm->data = data;
acm->dev = dev; acm->minor = minor;
acm->dev = dev;
acm->bh.func = acm_rx_tasklet;
acm->bh.data = (unsigned long) acm; acm->bh.func = acm_rx_tasklet;
INIT_WORK(&acm->work, acm_softint, acm); acm->bh.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint, acm);
if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
err("out of memory"); if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
kfree(acm); dev_dbg(&intf->dev, "out of memory (buf kmalloc)\n");
return -ENOMEM; kfree(acm);
} return -ENOMEM;
}
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) { if (!acm->ctrlurb) {
err("out of memory"); dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
kfree(acm); kfree(acm);
kfree(buf); kfree(buf);
return -ENOMEM; return -ENOMEM;
} }
acm->readurb = usb_alloc_urb(0, GFP_KERNEL); acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->readurb) { if (!acm->readurb) {
err("out of memory"); dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
usb_free_urb(acm->ctrlurb); usb_free_urb(acm->ctrlurb);
kfree(acm); kfree(acm);
kfree(buf); kfree(buf);
return -ENOMEM; return -ENOMEM;
} }
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL); acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) { if (!acm->writeurb) {
err("out of memory"); dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
usb_free_urb(acm->readurb); usb_free_urb(acm->readurb);
usb_free_urb(acm->ctrlurb); usb_free_urb(acm->ctrlurb);
kfree(acm); kfree(acm);
kfree(buf); kfree(buf);
return -ENOMEM; return -ENOMEM;
} }
usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); 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, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
buf += ctrlsize, readsize, acm_read_bulk, acm); buf += ctrlsize, readsize, acm_read_bulk, acm);
acm->readurb->transfer_flags |= URB_NO_FSBR; 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, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
buf += readsize, acm->writesize, acm_write_bulk, acm); buf += readsize, acm->writesize, acm_write_bulk, acm);
acm->writeurb->transfer_flags |= URB_NO_FSBR; acm->writeurb->transfer_flags |= URB_NO_FSBR;
dev_info(&intf->dev, "ttyACM%d: USB ACM device", minor); 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;
}
acm_set_control(acm, acm->ctrlout); tty_register_device(acm_tty_driver, minor, &intf->dev);
acm->line.speed = cpu_to_le32(9600); dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
acm->line.databits = 8;
acm_set_line(acm, &acm->line);
if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) { acm_set_control(acm, acm->ctrlout);
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->line.speed = cpu_to_le32(9600);
acm->line.databits = 8;
acm_set_line(acm, &acm->line);
acm_table[minor] = acm; acm_table[minor] = acm;
usb_set_intfdata (intf, acm); usb_set_intfdata (intf, acm);
return 0; return 0;
} }
#undef CHECK_XFERTYPE
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