From 4c49a5f0ef1bc61395329ea7a9fce2893e97eaa6 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:19 +0100 Subject: [PATCH] usb: gadget: udc-core: introduce UDC binding by name This patch adds udc_attach_driver() which allows to bind an UDC which is specified by name to a driver. The name of available UDCs can be obtained from /sys/class/udc. This interface is intended for configfs interface. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 72 +++++++++++++++++++++++++---------- include/linux/usb/gadget.h | 2 + 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 4d90a800063c..e7c591621a3b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -311,26 +311,10 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc); /* ------------------------------------------------------------------------- */ -int usb_gadget_probe_driver(struct usb_gadget_driver *driver) +static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver) { - struct usb_udc *udc = NULL; - int ret; - - if (!driver || !driver->bind || !driver->setup) - return -EINVAL; + int ret; - mutex_lock(&udc_lock); - list_for_each_entry(udc, &udc_list, list) { - /* For now we take the first one */ - if (!udc->driver) - goto found; - } - - pr_debug("couldn't find an available UDC\n"); - mutex_unlock(&udc_lock); - return -ENODEV; - -found: dev_dbg(&udc->dev, "registering UDC driver [%s]\n", driver->function); @@ -352,18 +336,64 @@ found: ret = usb_gadget_start(udc->gadget, driver, driver->bind); if (ret) goto err1; - } kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); - mutex_unlock(&udc_lock); return 0; - err1: dev_err(&udc->dev, "failed to start %s: %d\n", udc->driver->function, ret); udc->driver = NULL; udc->dev.driver = NULL; + return ret; +} + +int udc_attach_driver(const char *name, struct usb_gadget_driver *driver) +{ + struct usb_udc *udc = NULL; + int ret = -ENODEV; + + mutex_lock(&udc_lock); + list_for_each_entry(udc, &udc_list, list) { + ret = strcmp(name, dev_name(&udc->dev)); + if (!ret) + break; + } + if (ret) { + ret = -ENODEV; + goto out; + } + if (udc->driver) { + ret = -EBUSY; + goto out; + } + ret = udc_bind_to_driver(udc, driver); +out: + mutex_unlock(&udc_lock); + return ret; +} +EXPORT_SYMBOL_GPL(udc_attach_driver); + +int usb_gadget_probe_driver(struct usb_gadget_driver *driver) +{ + struct usb_udc *udc = NULL; + int ret; + + if (!driver || !driver->bind || !driver->setup) + return -EINVAL; + + mutex_lock(&udc_lock); + list_for_each_entry(udc, &udc_list, list) { + /* For now we take the first one */ + if (!udc->driver) + goto found; + } + + pr_debug("couldn't find an available UDC\n"); + mutex_unlock(&udc_lock); + return -ENODEV; +found: + ret = udc_bind_to_driver(udc, driver); mutex_unlock(&udc_lock); return ret; } diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 0af6569b8cc6..62156701e4f1 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -880,6 +880,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget); extern void usb_del_gadget_udc(struct usb_gadget *gadget); +extern int udc_attach_driver(const char *name, + struct usb_gadget_driver *driver); /*-------------------------------------------------------------------------*/ -- 2.30.2