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 <bige...@linutronix.de>
---
 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 4d90a80..e7c5916 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 @@ int usb_gadget_probe_driver(struct usb_gadget_driver 
*driver)
                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 0af6569..6215670 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);
 
 /*-------------------------------------------------------------------------*/
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to