usb: gadget: factor out two helper functions from composite_bind()
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Sun, 23 Dec 2012 20:10:20 +0000 (21:10 +0100)
committerFelipe Balbi <balbi@ti.com>
Mon, 21 Jan 2013 18:52:47 +0000 (20:52 +0200)
This patch factors out two helper functions from composite_bind()
that is composite_dev_prepare() and its counterpart
composite_dev_cleanup().

This will be used by the configfs which requries a slightly different
bind/setup code because part of its configurations (i.e. config
descripts, cdev, …) are setup in advance and VID/PID and so one should
not be overwritten. Also the setup of ep0 endpoint can be delayed until
the UDC is assigned.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/composite.c
include/linux/usb/composite.h

index 366facccf4f6b7c019a6dd4530730520cc03a395..9083ec93f38e28278dcb0ccaaff180f547c0b376 100644 (file)
@@ -1394,11 +1394,8 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
        if (cdev->driver->unbind && unbind_driver)
                cdev->driver->unbind(cdev);
 
-       if (cdev->req) {
-               kfree(cdev->req->buf);
-               usb_ep_free_request(gadget->ep0, cdev->req);
-       }
-       device_remove_file(&gadget->dev, &dev_attr_suspended);
+       composite_dev_cleanup(cdev);
+
        kfree(cdev->def_manufacturer);
        kfree(cdev);
        set_gadget_data(gadget, NULL);
@@ -1447,34 +1444,25 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
                new->iProduct = iProduct;
 }
 
-static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv)
+int composite_dev_prepare(struct usb_composite_driver *composite,
+               struct usb_composite_dev *cdev)
 {
-       return container_of(gdrv, struct usb_composite_driver, gadget_driver);
-}
-
-static int composite_bind(struct usb_gadget *gadget,
-               struct usb_gadget_driver *gdriver)
-{
-       struct usb_composite_dev        *cdev;
-       struct usb_composite_driver     *composite = to_cdriver(gdriver);
-       int                             status = -ENOMEM;
-
-       cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
-       if (!cdev)
-               return status;
-
-       spin_lock_init(&cdev->lock);
-       cdev->gadget = gadget;
-       set_gadget_data(gadget, cdev);
-       INIT_LIST_HEAD(&cdev->configs);
+       struct usb_gadget *gadget = cdev->gadget;
+       int ret = -ENOMEM;
 
        /* preallocate control response and buffer */
        cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
        if (!cdev->req)
-               goto fail;
+               return -ENOMEM;
+
        cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
        if (!cdev->req->buf)
                goto fail;
+
+       ret = device_create_file(&gadget->dev, &dev_attr_suspended);
+       if (ret)
+               goto fail_dev;
+
        cdev->req->complete = composite_setup_complete;
        gadget->ep0->driver_data = cdev;
 
@@ -1492,7 +1480,44 @@ static int composite_bind(struct usb_gadget *gadget,
         * we force endpoints to start unassigned; few controller
         * drivers will zero ep->driver_data.
         */
-       usb_ep_autoconfig_reset(cdev->gadget);
+       usb_ep_autoconfig_reset(gadget);
+       return 0;
+fail_dev:
+       kfree(cdev->req->buf);
+fail:
+       usb_ep_free_request(gadget->ep0, cdev->req);
+       cdev->req = NULL;
+       return ret;
+}
+
+void composite_dev_cleanup(struct usb_composite_dev *cdev)
+{
+       if (cdev->req) {
+               kfree(cdev->req->buf);
+               usb_ep_free_request(cdev->gadget->ep0, cdev->req);
+       }
+       device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
+}
+
+static int composite_bind(struct usb_gadget *gadget,
+               struct usb_gadget_driver *gdriver)
+{
+       struct usb_composite_dev        *cdev;
+       struct usb_composite_driver     *composite = to_cdriver(gdriver);
+       int                             status = -ENOMEM;
+
+       cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
+       if (!cdev)
+               return status;
+
+       spin_lock_init(&cdev->lock);
+       cdev->gadget = gadget;
+       set_gadget_data(gadget, cdev);
+       INIT_LIST_HEAD(&cdev->configs);
+
+       status = composite_dev_prepare(composite, cdev);
+       if (status)
+               goto fail;
 
        /* composite gadget needs to assign strings for whole device (like
         * serial number), register function drivers, potentially update
@@ -1508,11 +1533,6 @@ static int composite_bind(struct usb_gadget *gadget,
        if (composite->needs_serial && !cdev->desc.iSerialNumber)
                WARNING(cdev, "userspace failed to provide iSerialNumber\n");
 
-       /* finish up */
-       status = device_create_file(&gadget->dev, &dev_attr_suspended);
-       if (status)
-               goto fail;
-
        INFO(cdev, "%s ready\n", composite->name);
        return 0;
 
index 771de7acf8ddeaf7dda382adc28853b7e57b5eb2..bd6d857c12f47ca49b007d4ca8640621543f1954 100644 (file)
@@ -323,7 +323,15 @@ struct usb_composite_driver {
 extern int usb_composite_probe(struct usb_composite_driver *driver);
 extern void usb_composite_unregister(struct usb_composite_driver *driver);
 extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
+extern int composite_dev_prepare(struct usb_composite_driver *composite,
+               struct usb_composite_dev *cdev);
+void composite_dev_cleanup(struct usb_composite_dev *cdev);
 
+static inline struct usb_composite_driver *to_cdriver(
+               struct usb_gadget_driver *gdrv)
+{
+       return container_of(gdrv, struct usb_composite_driver, gadget_driver);
+}
 
 /**
  * struct usb_composite_device - represents one composite usb gadget