aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/udc-core.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 21:10:19 +0100
committerFelipe Balbi <balbi@ti.com>2013-01-21 20:52:46 +0200
commit4c49a5f0ef1bc61395329ea7a9fce2893e97eaa6 (patch)
tree064349fb779ad5d628ea9f9b7b137205c7a14647 /drivers/usb/gadget/udc-core.c
parent0062f6e56f70bd2230ba1ebd1667d1b32a1af3b2 (diff)
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 <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/udc-core.c')
-rw-r--r--drivers/usb/gadget/udc-core.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 4d90a800063..e7c591621a3 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;
}