summaryrefslogtreecommitdiff
path: root/drivers/usb/class/cdc-wdm.c
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-03-06 17:29:20 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-08 13:06:48 -0800
commit0dffb4862a5f109dc9b72e3a4e0ecc85a87ce397 (patch)
treee45b3920a374874225d1c0efe4c44d0167a977d0 /drivers/usb/class/cdc-wdm.c
parentc1cee1d84001815a1b4321c49b995254c0df3100 (diff)
usb: cdc-wdm: split out reusable parts of probe
Preparing for the addition of subdriver registering as an alternative to probe for interface-less usage. This should not change anything apart from minor code reordering. Signed-off-by: Bjørn Mork <bjorn@mork.no> Acked-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class/cdc-wdm.c')
-rw-r--r--drivers/usb/class/cdc-wdm.c105
1 files changed, 54 insertions, 51 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 6037b503153f..451793036d37 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -631,47 +631,11 @@ static void wdm_rxwork(struct work_struct *work)
/* --- hotplug --- */
-static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, u16 bufsize)
{
- int rv = -EINVAL;
+ int rv = -ENOMEM;
struct wdm_device *desc;
- struct usb_host_interface *iface;
- struct usb_endpoint_descriptor *ep;
- struct usb_cdc_dmm_desc *dmhd;
- u8 *buffer = intf->altsetting->extra;
- int buflen = intf->altsetting->extralen;
- u16 maxcom = WDM_DEFAULT_BUFSIZE;
-
- if (!buffer)
- goto out;
-
- while (buflen > 2) {
- if (buffer [1] != USB_DT_CS_INTERFACE) {
- dev_err(&intf->dev, "skipping garbage\n");
- goto next_desc;
- }
-
- switch (buffer [2]) {
- case USB_CDC_HEADER_TYPE:
- break;
- case USB_CDC_DMM_TYPE:
- dmhd = (struct usb_cdc_dmm_desc *)buffer;
- maxcom = le16_to_cpu(dmhd->wMaxCommand);
- dev_dbg(&intf->dev,
- "Finding maximum buffer length: %d", maxcom);
- break;
- default:
- dev_err(&intf->dev,
- "Ignoring extra header, type %d, length %d\n",
- buffer[2], buffer[0]);
- break;
- }
-next_desc:
- buflen -= buffer[0];
- buffer += buffer[0];
- }
- rv = -ENOMEM;
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
@@ -679,18 +643,14 @@ next_desc:
mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
- desc->wMaxCommand = maxcom;
+ desc->wMaxCommand = bufsize;
/* this will be expanded and needed in hardware endianness */
desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
desc->intf = intf;
INIT_WORK(&desc->rxwork, wdm_rxwork);
rv = -EINVAL;
- iface = intf->cur_altsetting;
- if (iface->desc.bNumEndpoints != 1)
- goto err;
- ep = &iface->endpoint[0].desc;
- if (!ep || !usb_endpoint_is_int_in(ep))
+ if (!usb_endpoint_is_int_in(ep))
goto err;
desc->wMaxPacketSize = usb_endpoint_maxp(ep);
@@ -766,13 +726,56 @@ out:
err2:
usb_set_intfdata(intf, NULL);
err:
- free_urbs(desc);
- kfree(desc->inbuf);
- kfree(desc->sbuf);
- kfree(desc->ubuf);
- kfree(desc->orq);
- kfree(desc->irq);
- kfree(desc);
+ cleanup(desc);
+ return rv;
+}
+
+static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ int rv = -EINVAL;
+ struct usb_host_interface *iface;
+ struct usb_endpoint_descriptor *ep;
+ struct usb_cdc_dmm_desc *dmhd;
+ u8 *buffer = intf->altsetting->extra;
+ int buflen = intf->altsetting->extralen;
+ u16 maxcom = WDM_DEFAULT_BUFSIZE;
+
+ if (!buffer)
+ goto err;
+ while (buflen > 2) {
+ if (buffer[1] != USB_DT_CS_INTERFACE) {
+ dev_err(&intf->dev, "skipping garbage\n");
+ goto next_desc;
+ }
+
+ switch (buffer[2]) {
+ case USB_CDC_HEADER_TYPE:
+ break;
+ case USB_CDC_DMM_TYPE:
+ dmhd = (struct usb_cdc_dmm_desc *)buffer;
+ maxcom = le16_to_cpu(dmhd->wMaxCommand);
+ dev_dbg(&intf->dev,
+ "Finding maximum buffer length: %d", maxcom);
+ break;
+ default:
+ dev_err(&intf->dev,
+ "Ignoring extra header, type %d, length %d\n",
+ buffer[2], buffer[0]);
+ break;
+ }
+next_desc:
+ buflen -= buffer[0];
+ buffer += buffer[0];
+ }
+
+ iface = intf->cur_altsetting;
+ if (iface->desc.bNumEndpoints != 1)
+ goto err;
+ ep = &iface->endpoint[0].desc;
+
+ rv = wdm_create(intf, ep, maxcom);
+
+err:
return rv;
}