From a59233407aed54b8a9121cea75d9c6a2a470d8d3 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:20 +0100 Subject: [PATCH] usb: gadget: factor out two helper functions from composite_bind() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 92 +++++++++++++++++++++------------- include/linux/usb/composite.h | 8 +++ 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 366facccf4f6..9083ec93f38e 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -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,9 +1444,59 @@ 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); + 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) + 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; + + cdev->driver = composite; + + /* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + */ + if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) + usb_gadget_set_selfpowered(gadget); + + /* interface and string IDs start at zero via kzalloc. + * we force endpoints to start unassigned; few controller + * drivers will zero ep->driver_data. + */ + 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, @@ -1468,31 +1515,9 @@ static int composite_bind(struct usb_gadget *gadget, set_gadget_data(gadget, cdev); INIT_LIST_HEAD(&cdev->configs); - /* preallocate control response and buffer */ - cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); - if (!cdev->req) + status = composite_dev_prepare(composite, cdev); + if (status) goto fail; - cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); - if (!cdev->req->buf) - goto fail; - cdev->req->complete = composite_setup_complete; - gadget->ep0->driver_data = cdev; - - cdev->driver = composite; - - /* - * As per USB compliance update, a device that is actively drawing - * more than 100mA from USB must report itself as bus-powered in - * the GetStatus(DEVICE) call. - */ - if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) - usb_gadget_set_selfpowered(gadget); - - /* interface and string IDs start at zero via kzalloc. - * we force endpoints to start unassigned; few controller - * drivers will zero ep->driver_data. - */ - usb_ep_autoconfig_reset(cdev->gadget); /* 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; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 771de7acf8dd..bd6d857c12f4 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -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