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>
This commit is contained in:
Sebastian Andrzej Siewior 2012-12-23 21:10:19 +01:00 committed by Felipe Balbi
parent 0062f6e56f
commit 4c49a5f0ef
2 changed files with 53 additions and 21 deletions

View file

@ -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;
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:
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;
}

View file

@ -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);
/*-------------------------------------------------------------------------*/