Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Thu, Apr 30, 2015 at 11:08:27AM +0200, Robert Baldyga wrote: > On 04/29/2015 05:30 PM, Felipe Balbi wrote: > > On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: > >> Hi Felipe, > >> > >> On 04/28/2015 06:40 PM, Felipe Balbi wrote: > >>> On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: > These functions allows to deactivate gadget to make it not visible to > host and make it active again when gadget driver is finally ready. > > They are needed to fix usb_function_activate() and > usb_function_deactivate() > functions which currently are not working as usb_gadget_connect() is > called immediately after function bind regardless to previous calls of > usb_gadget_disconnect() function. > >>> > >>> and that's what needs to be fixed, a long time ago I wrote the patch > >>> below which I never got to finishing: > >>> > >>> commit a23800e2463ae1f4eafa7c0a15bb44afee75994f > >>> Author: Felipe Balbi > >>> Date: Thu Jul 26 14:23:44 2012 +0300 > >>> > >>> usb: gadget: let gadgets control pullup on their own > >>> > >>> This is useful on gadgets that depend on userland > >>> daemons to function properly. We can delay connection > >>> to the host until userland is ready. > >>> > >>> Signed-off-by: Felipe Balbi > >>> > >>> diff --git a/drivers/usb/gadget/composite.c > >>> b/drivers/usb/gadget/composite.c > >>> index 7c821de8ce3d..790ccf29f2ee 100644 > >>> --- a/drivers/usb/gadget/composite.c > >>> +++ b/drivers/usb/gadget/composite.c > >>> @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver > >>> *driver) > >>> driver->name = "composite"; > >>> > >>> driver->gadget_driver = composite_driver_template; > >>> - gadget_driver = >gadget_driver; > >>> > >>> + gadget_driver = >gadget_driver; > >>> + gadget_driver->controls_pullups = driver->controls_pullups; > >>> gadget_driver->function = (char *) driver->name; > >>> gadget_driver->driver.name = driver->name; > >>> gadget_driver->max_speed = driver->max_speed; > >>> diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c > >>> index 8a1eeb24ae6a..c0f4fca9384b 100644 > >>> --- a/drivers/usb/gadget/udc-core.c > >>> +++ b/drivers/usb/gadget/udc-core.c > >>> @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc > >>> *udc) > >>> > >>> kobject_uevent(>dev.kobj, KOBJ_CHANGE); > >>> > >>> - usb_gadget_disconnect(udc->gadget); > >>> + /* > >>> + * NOTICE: if gadget driver wants to control > >>> + * pullup, it needs to make sure that when > >>> + * user tries to rmmod the gadget driver, it > >>> + * will disconnect the pullups before returning > >>> + * from its ->unbind() method. > >>> + * > >>> + * We are truly trusting the gadget driver here. > >>> + */ > >>> + if (!udc->driver->controls_pullups) > >>> + usb_gadget_disconnect(udc->gadget); > >>> + > >>> udc->driver->disconnect(udc->gadget); > >>> udc->driver->unbind(udc->gadget); > >>> usb_gadget_udc_stop(udc->gadget, udc->driver); > >>> @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, > >>> struct usb_gadget_driver *dri > >>> driver->unbind(udc->gadget); > >>> goto err1; > >>> } > >>> - usb_gadget_connect(udc->gadget); > >>> + > >>> + /* > >>> + * NOTICE: if gadget driver wants to control > >>> + * pullups, it needs to make sure its calls > >>> + * to usb_function_activate() and > >>> + * usb_function_deactivate() are balanced, > >>> + * otherwise gadget_driver will never enumerate. > >>> + * > >>> + * We are truly trusting the gadget driver here. > >>> + */ > >>> + if (!driver->controls_pullups) > >>> + usb_gadget_connect(udc->gadget); > >>> > >>> kobject_uevent(>dev.kobj, KOBJ_CHANGE); > >>> return 0; > >>> diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h > >>> index 3c671c1b37f6..7ae797c85cb9 100644 > >>> --- a/include/linux/usb/composite.h > >>> +++ b/include/linux/usb/composite.h > >>> @@ -157,6 +157,7 @@ struct usb_function { > >>> int (*get_status)(struct usb_function *); > >>> int (*func_suspend)(struct usb_function *, > >>> u8 suspend_opt); > >>> + > >>> /* private: */ > >>> /* internals */ > >>> struct list_headlist; > >>> @@ -279,6 +280,8 @@ enum { > >>> * @max_speed: Highest speed the driver supports. > >>> * @needs_serial: set to 1 if the gadget needs userspace to provide > >>> * a serial number. If one is not provided, warning will be > >>> printed. > >>> + * @controls_pullups: this driver will control pullup and udc-core > >>> shouldn't > >>> + * enable it by default > >>> * @bind: (REQUIRED) Used to allocate resources that are shared across > >>> the > >>> * whole device, such as string IDs, and add its configurations > >>> using > >>> * @usb_add_config(). This
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On 04/29/2015 05:30 PM, Felipe Balbi wrote: > On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: >> Hi Felipe, >> >> On 04/28/2015 06:40 PM, Felipe Balbi wrote: >>> On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. >>> >>> and that's what needs to be fixed, a long time ago I wrote the patch >>> below which I never got to finishing: >>> >>> commit a23800e2463ae1f4eafa7c0a15bb44afee75994f >>> Author: Felipe Balbi >>> Date: Thu Jul 26 14:23:44 2012 +0300 >>> >>> usb: gadget: let gadgets control pullup on their own >>> >>> This is useful on gadgets that depend on userland >>> daemons to function properly. We can delay connection >>> to the host until userland is ready. >>> >>> Signed-off-by: Felipe Balbi >>> >>> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c >>> index 7c821de8ce3d..790ccf29f2ee 100644 >>> --- a/drivers/usb/gadget/composite.c >>> +++ b/drivers/usb/gadget/composite.c >>> @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver >>> *driver) >>> driver->name = "composite"; >>> >>> driver->gadget_driver = composite_driver_template; >>> - gadget_driver = >gadget_driver; >>> >>> + gadget_driver = >gadget_driver; >>> + gadget_driver->controls_pullups = driver->controls_pullups; >>> gadget_driver->function = (char *) driver->name; >>> gadget_driver->driver.name = driver->name; >>> gadget_driver->max_speed = driver->max_speed; >>> diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c >>> index 8a1eeb24ae6a..c0f4fca9384b 100644 >>> --- a/drivers/usb/gadget/udc-core.c >>> +++ b/drivers/usb/gadget/udc-core.c >>> @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc >>> *udc) >>> >>> kobject_uevent(>dev.kobj, KOBJ_CHANGE); >>> >>> - usb_gadget_disconnect(udc->gadget); >>> + /* >>> +* NOTICE: if gadget driver wants to control >>> +* pullup, it needs to make sure that when >>> +* user tries to rmmod the gadget driver, it >>> +* will disconnect the pullups before returning >>> +* from its ->unbind() method. >>> +* >>> +* We are truly trusting the gadget driver here. >>> +*/ >>> + if (!udc->driver->controls_pullups) >>> + usb_gadget_disconnect(udc->gadget); >>> + >>> udc->driver->disconnect(udc->gadget); >>> udc->driver->unbind(udc->gadget); >>> usb_gadget_udc_stop(udc->gadget, udc->driver); >>> @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, >>> struct usb_gadget_driver *dri >>> driver->unbind(udc->gadget); >>> goto err1; >>> } >>> - usb_gadget_connect(udc->gadget); >>> + >>> + /* >>> +* NOTICE: if gadget driver wants to control >>> +* pullups, it needs to make sure its calls >>> +* to usb_function_activate() and >>> +* usb_function_deactivate() are balanced, >>> +* otherwise gadget_driver will never enumerate. >>> +* >>> +* We are truly trusting the gadget driver here. >>> +*/ >>> + if (!driver->controls_pullups) >>> + usb_gadget_connect(udc->gadget); >>> >>> kobject_uevent(>dev.kobj, KOBJ_CHANGE); >>> return 0; >>> diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h >>> index 3c671c1b37f6..7ae797c85cb9 100644 >>> --- a/include/linux/usb/composite.h >>> +++ b/include/linux/usb/composite.h >>> @@ -157,6 +157,7 @@ struct usb_function { >>> int (*get_status)(struct usb_function *); >>> int (*func_suspend)(struct usb_function *, >>> u8 suspend_opt); >>> + >>> /* private: */ >>> /* internals */ >>> struct list_headlist; >>> @@ -279,6 +280,8 @@ enum { >>> * @max_speed: Highest speed the driver supports. >>> * @needs_serial: set to 1 if the gadget needs userspace to provide >>> * a serial number. If one is not provided, warning will be >>> printed. >>> + * @controls_pullups: this driver will control pullup and udc-core >>> shouldn't >>> + * enable it by default >>> * @bind: (REQUIRED) Used to allocate resources that are shared across the >>> * whole device, such as string IDs, and add its configurations using >>> * @usb_add_config(). This may fail by returning a negative errno >>> @@ -308,6 +311,7 @@ struct usb_composite_driver { >>> struct usb_gadget_strings **strings; >>> enum usb_device_speed max_speed; >>> unsigned
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On 04/29/2015 05:30 PM, Felipe Balbi wrote: On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: Hi Felipe, On 04/28/2015 06:40 PM, Felipe Balbi wrote: On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi ba...@ti.com Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi ba...@ti.com diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver-name = composite; driver-gadget_driver = composite_driver_template; - gadget_driver = driver-gadget_driver; + gadget_driver = driver-gadget_driver; + gadget_driver-controls_pullups = driver-controls_pullups; gadget_driver-function = (char *) driver-name; gadget_driver-driver.name = driver-name; gadget_driver-max_speed = driver-max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc-gadget); + /* +* NOTICE: if gadget driver wants to control +* pullup, it needs to make sure that when +* user tries to rmmod the gadget driver, it +* will disconnect the pullups before returning +* from its -unbind() method. +* +* We are truly trusting the gadget driver here. +*/ + if (!udc-driver-controls_pullups) + usb_gadget_disconnect(udc-gadget); + udc-driver-disconnect(udc-gadget); udc-driver-unbind(udc-gadget); usb_gadget_udc_stop(udc-gadget, udc-driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver-unbind(udc-gadget); goto err1; } - usb_gadget_connect(udc-gadget); + + /* +* NOTICE: if gadget driver wants to control +* pullups, it needs to make sure its calls +* to usb_function_activate() and +* usb_function_deactivate() are balanced, +* otherwise gadget_driver will never enumerate. +* +* We are truly trusting the gadget driver here. +*/ + if (!driver-controls_pullups) + usb_gadget_connect(udc-gadget); kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 32b734d88d6b..87971fa38f08 100644 ---
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Thu, Apr 30, 2015 at 11:08:27AM +0200, Robert Baldyga wrote: On 04/29/2015 05:30 PM, Felipe Balbi wrote: On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: Hi Felipe, On 04/28/2015 06:40 PM, Felipe Balbi wrote: On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi ba...@ti.com Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi ba...@ti.com diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver-name = composite; driver-gadget_driver = composite_driver_template; - gadget_driver = driver-gadget_driver; + gadget_driver = driver-gadget_driver; + gadget_driver-controls_pullups = driver-controls_pullups; gadget_driver-function = (char *) driver-name; gadget_driver-driver.name = driver-name; gadget_driver-max_speed = driver-max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc-gadget); + /* + * NOTICE: if gadget driver wants to control + * pullup, it needs to make sure that when + * user tries to rmmod the gadget driver, it + * will disconnect the pullups before returning + * from its -unbind() method. + * + * We are truly trusting the gadget driver here. + */ + if (!udc-driver-controls_pullups) + usb_gadget_disconnect(udc-gadget); + udc-driver-disconnect(udc-gadget); udc-driver-unbind(udc-gadget); usb_gadget_udc_stop(udc-gadget, udc-driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver-unbind(udc-gadget); goto err1; } - usb_gadget_connect(udc-gadget); + + /* + * NOTICE: if gadget driver wants to control + * pullups, it needs to make sure its calls + * to usb_function_activate() and + * usb_function_deactivate() are balanced, + * otherwise gadget_driver will never enumerate. + * + * We are truly trusting the gadget driver here. + */ + if (!driver-controls_pullups) + usb_gadget_connect(udc-gadget); kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: > Hi Felipe, > > On 04/28/2015 06:40 PM, Felipe Balbi wrote: > > On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: > >> These functions allows to deactivate gadget to make it not visible to > >> host and make it active again when gadget driver is finally ready. > >> > >> They are needed to fix usb_function_activate() and > >> usb_function_deactivate() > >> functions which currently are not working as usb_gadget_connect() is > >> called immediately after function bind regardless to previous calls of > >> usb_gadget_disconnect() function. > > > > and that's what needs to be fixed, a long time ago I wrote the patch > > below which I never got to finishing: > > > > commit a23800e2463ae1f4eafa7c0a15bb44afee75994f > > Author: Felipe Balbi > > Date: Thu Jul 26 14:23:44 2012 +0300 > > > > usb: gadget: let gadgets control pullup on their own > > > > This is useful on gadgets that depend on userland > > daemons to function properly. We can delay connection > > to the host until userland is ready. > > > > Signed-off-by: Felipe Balbi > > > > diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c > > index 7c821de8ce3d..790ccf29f2ee 100644 > > --- a/drivers/usb/gadget/composite.c > > +++ b/drivers/usb/gadget/composite.c > > @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver > > *driver) > > driver->name = "composite"; > > > > driver->gadget_driver = composite_driver_template; > > - gadget_driver = >gadget_driver; > > > > + gadget_driver = >gadget_driver; > > + gadget_driver->controls_pullups = driver->controls_pullups; > > gadget_driver->function = (char *) driver->name; > > gadget_driver->driver.name = driver->name; > > gadget_driver->max_speed = driver->max_speed; > > diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c > > index 8a1eeb24ae6a..c0f4fca9384b 100644 > > --- a/drivers/usb/gadget/udc-core.c > > +++ b/drivers/usb/gadget/udc-core.c > > @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc > > *udc) > > > > kobject_uevent(>dev.kobj, KOBJ_CHANGE); > > > > - usb_gadget_disconnect(udc->gadget); > > + /* > > +* NOTICE: if gadget driver wants to control > > +* pullup, it needs to make sure that when > > +* user tries to rmmod the gadget driver, it > > +* will disconnect the pullups before returning > > +* from its ->unbind() method. > > +* > > +* We are truly trusting the gadget driver here. > > +*/ > > + if (!udc->driver->controls_pullups) > > + usb_gadget_disconnect(udc->gadget); > > + > > udc->driver->disconnect(udc->gadget); > > udc->driver->unbind(udc->gadget); > > usb_gadget_udc_stop(udc->gadget, udc->driver); > > @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, > > struct usb_gadget_driver *dri > > driver->unbind(udc->gadget); > > goto err1; > > } > > - usb_gadget_connect(udc->gadget); > > + > > + /* > > +* NOTICE: if gadget driver wants to control > > +* pullups, it needs to make sure its calls > > +* to usb_function_activate() and > > +* usb_function_deactivate() are balanced, > > +* otherwise gadget_driver will never enumerate. > > +* > > +* We are truly trusting the gadget driver here. > > +*/ > > + if (!driver->controls_pullups) > > + usb_gadget_connect(udc->gadget); > > > > kobject_uevent(>dev.kobj, KOBJ_CHANGE); > > return 0; > > diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h > > index 3c671c1b37f6..7ae797c85cb9 100644 > > --- a/include/linux/usb/composite.h > > +++ b/include/linux/usb/composite.h > > @@ -157,6 +157,7 @@ struct usb_function { > > int (*get_status)(struct usb_function *); > > int (*func_suspend)(struct usb_function *, > > u8 suspend_opt); > > + > > /* private: */ > > /* internals */ > > struct list_headlist; > > @@ -279,6 +280,8 @@ enum { > > * @max_speed: Highest speed the driver supports. > > * @needs_serial: set to 1 if the gadget needs userspace to provide > > * a serial number. If one is not provided, warning will be > > printed. > > + * @controls_pullups: this driver will control pullup and udc-core > > shouldn't > > + * enable it by default > > * @bind: (REQUIRED) Used to allocate resources that are shared across the > > * whole device, such as string IDs, and add its configurations using > > * @usb_add_config(). This may fail by returning a negative errno > > @@ -308,6 +311,7 @@ struct usb_composite_driver { > > struct usb_gadget_strings **strings; > > enum usb_device_speed max_speed; > > unsignedneeds_serial:1; > > + unsigned
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
Hi Felipe, On 04/28/2015 06:40 PM, Felipe Balbi wrote: > On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: >> These functions allows to deactivate gadget to make it not visible to >> host and make it active again when gadget driver is finally ready. >> >> They are needed to fix usb_function_activate() and usb_function_deactivate() >> functions which currently are not working as usb_gadget_connect() is >> called immediately after function bind regardless to previous calls of >> usb_gadget_disconnect() function. > > and that's what needs to be fixed, a long time ago I wrote the patch > below which I never got to finishing: > > commit a23800e2463ae1f4eafa7c0a15bb44afee75994f > Author: Felipe Balbi > Date: Thu Jul 26 14:23:44 2012 +0300 > > usb: gadget: let gadgets control pullup on their own > > This is useful on gadgets that depend on userland > daemons to function properly. We can delay connection > to the host until userland is ready. > > Signed-off-by: Felipe Balbi > > diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c > index 7c821de8ce3d..790ccf29f2ee 100644 > --- a/drivers/usb/gadget/composite.c > +++ b/drivers/usb/gadget/composite.c > @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver > *driver) > driver->name = "composite"; > > driver->gadget_driver = composite_driver_template; > - gadget_driver = >gadget_driver; > > + gadget_driver = >gadget_driver; > + gadget_driver->controls_pullups = driver->controls_pullups; > gadget_driver->function = (char *) driver->name; > gadget_driver->driver.name = driver->name; > gadget_driver->max_speed = driver->max_speed; > diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c > index 8a1eeb24ae6a..c0f4fca9384b 100644 > --- a/drivers/usb/gadget/udc-core.c > +++ b/drivers/usb/gadget/udc-core.c > @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) > > kobject_uevent(>dev.kobj, KOBJ_CHANGE); > > - usb_gadget_disconnect(udc->gadget); > + /* > + * NOTICE: if gadget driver wants to control > + * pullup, it needs to make sure that when > + * user tries to rmmod the gadget driver, it > + * will disconnect the pullups before returning > + * from its ->unbind() method. > + * > + * We are truly trusting the gadget driver here. > + */ > + if (!udc->driver->controls_pullups) > + usb_gadget_disconnect(udc->gadget); > + > udc->driver->disconnect(udc->gadget); > udc->driver->unbind(udc->gadget); > usb_gadget_udc_stop(udc->gadget, udc->driver); > @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, > struct usb_gadget_driver *dri > driver->unbind(udc->gadget); > goto err1; > } > - usb_gadget_connect(udc->gadget); > + > + /* > + * NOTICE: if gadget driver wants to control > + * pullups, it needs to make sure its calls > + * to usb_function_activate() and > + * usb_function_deactivate() are balanced, > + * otherwise gadget_driver will never enumerate. > + * > + * We are truly trusting the gadget driver here. > + */ > + if (!driver->controls_pullups) > + usb_gadget_connect(udc->gadget); > > kobject_uevent(>dev.kobj, KOBJ_CHANGE); > return 0; > diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h > index 3c671c1b37f6..7ae797c85cb9 100644 > --- a/include/linux/usb/composite.h > +++ b/include/linux/usb/composite.h > @@ -157,6 +157,7 @@ struct usb_function { > int (*get_status)(struct usb_function *); > int (*func_suspend)(struct usb_function *, > u8 suspend_opt); > + > /* private: */ > /* internals */ > struct list_headlist; > @@ -279,6 +280,8 @@ enum { > * @max_speed: Highest speed the driver supports. > * @needs_serial: set to 1 if the gadget needs userspace to provide > * a serial number. If one is not provided, warning will be printed. > + * @controls_pullups: this driver will control pullup and udc-core shouldn't > + * enable it by default > * @bind: (REQUIRED) Used to allocate resources that are shared across the > * whole device, such as string IDs, and add its configurations using > * @usb_add_config(). This may fail by returning a negative errno > @@ -308,6 +311,7 @@ struct usb_composite_driver { > struct usb_gadget_strings **strings; > enum usb_device_speed max_speed; > unsignedneeds_serial:1; > + unsignedcontrols_pullups:1; > > int (*bind)(struct usb_composite_dev *cdev); > int (*unbind)(struct usb_composite_dev *); > diff --git
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
Hi Felipe, On 04/28/2015 06:40 PM, Felipe Balbi wrote: On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi ba...@ti.com Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi ba...@ti.com diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver-name = composite; driver-gadget_driver = composite_driver_template; - gadget_driver = driver-gadget_driver; + gadget_driver = driver-gadget_driver; + gadget_driver-controls_pullups = driver-controls_pullups; gadget_driver-function = (char *) driver-name; gadget_driver-driver.name = driver-name; gadget_driver-max_speed = driver-max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc-gadget); + /* + * NOTICE: if gadget driver wants to control + * pullup, it needs to make sure that when + * user tries to rmmod the gadget driver, it + * will disconnect the pullups before returning + * from its -unbind() method. + * + * We are truly trusting the gadget driver here. + */ + if (!udc-driver-controls_pullups) + usb_gadget_disconnect(udc-gadget); + udc-driver-disconnect(udc-gadget); udc-driver-unbind(udc-gadget); usb_gadget_udc_stop(udc-gadget, udc-driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver-unbind(udc-gadget); goto err1; } - usb_gadget_connect(udc-gadget); + + /* + * NOTICE: if gadget driver wants to control + * pullups, it needs to make sure its calls + * to usb_function_activate() and + * usb_function_deactivate() are balanced, + * otherwise gadget_driver will never enumerate. + * + * We are truly trusting the gadget driver here. + */ + if (!driver-controls_pullups) + usb_gadget_connect(udc-gadget); kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 32b734d88d6b..87971fa38f08 100644 ---
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote: Hi Felipe, On 04/28/2015 06:40 PM, Felipe Balbi wrote: On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi ba...@ti.com Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi ba...@ti.com diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver-name = composite; driver-gadget_driver = composite_driver_template; - gadget_driver = driver-gadget_driver; + gadget_driver = driver-gadget_driver; + gadget_driver-controls_pullups = driver-controls_pullups; gadget_driver-function = (char *) driver-name; gadget_driver-driver.name = driver-name; gadget_driver-max_speed = driver-max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc-gadget); + /* +* NOTICE: if gadget driver wants to control +* pullup, it needs to make sure that when +* user tries to rmmod the gadget driver, it +* will disconnect the pullups before returning +* from its -unbind() method. +* +* We are truly trusting the gadget driver here. +*/ + if (!udc-driver-controls_pullups) + usb_gadget_disconnect(udc-gadget); + udc-driver-disconnect(udc-gadget); udc-driver-unbind(udc-gadget); usb_gadget_udc_stop(udc-gadget, udc-driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver-unbind(udc-gadget); goto err1; } - usb_gadget_connect(udc-gadget); + + /* +* NOTICE: if gadget driver wants to control +* pullups, it needs to make sure its calls +* to usb_function_activate() and +* usb_function_deactivate() are balanced, +* otherwise gadget_driver will never enumerate. +* +* We are truly trusting the gadget driver here. +*/ + if (!driver-controls_pullups) + usb_gadget_connect(udc-gadget); kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git a/include/linux/usb/gadget.h
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: > These functions allows to deactivate gadget to make it not visible to > host and make it active again when gadget driver is finally ready. > > They are needed to fix usb_function_activate() and usb_function_deactivate() > functions which currently are not working as usb_gadget_connect() is > called immediately after function bind regardless to previous calls of > usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver->name = "composite"; driver->gadget_driver = composite_driver_template; - gadget_driver = >gadget_driver; + gadget_driver = >gadget_driver; + gadget_driver->controls_pullups = driver->controls_pullups; gadget_driver->function = (char *) driver->name; gadget_driver->driver.name = driver->name; gadget_driver->max_speed = driver->max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(>dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc->gadget); + /* +* NOTICE: if gadget driver wants to control +* pullup, it needs to make sure that when +* user tries to rmmod the gadget driver, it +* will disconnect the pullups before returning +* from its ->unbind() method. +* +* We are truly trusting the gadget driver here. +*/ + if (!udc->driver->controls_pullups) + usb_gadget_disconnect(udc->gadget); + udc->driver->disconnect(udc->gadget); udc->driver->unbind(udc->gadget); usb_gadget_udc_stop(udc->gadget, udc->driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver->unbind(udc->gadget); goto err1; } - usb_gadget_connect(udc->gadget); + + /* +* NOTICE: if gadget driver wants to control +* pullups, it needs to make sure its calls +* to usb_function_activate() and +* usb_function_deactivate() are balanced, +* otherwise gadget_driver will never enumerate. +* +* We are truly trusting the gadget driver here. +*/ + if (!driver->controls_pullups) + usb_gadget_connect(udc->gadget); kobject_uevent(>dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 32b734d88d6b..87971fa38f08 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -774,6 +774,7 @@
Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote: These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. and that's what needs to be fixed, a long time ago I wrote the patch below which I never got to finishing: commit a23800e2463ae1f4eafa7c0a15bb44afee75994f Author: Felipe Balbi ba...@ti.com Date: Thu Jul 26 14:23:44 2012 +0300 usb: gadget: let gadgets control pullup on their own This is useful on gadgets that depend on userland daemons to function properly. We can delay connection to the host until userland is ready. Signed-off-by: Felipe Balbi ba...@ti.com diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..790ccf29f2ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver) driver-name = composite; driver-gadget_driver = composite_driver_template; - gadget_driver = driver-gadget_driver; + gadget_driver = driver-gadget_driver; + gadget_driver-controls_pullups = driver-controls_pullups; gadget_driver-function = (char *) driver-name; gadget_driver-driver.name = driver-name; gadget_driver-max_speed = driver-max_speed; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..c0f4fca9384b 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); - usb_gadget_disconnect(udc-gadget); + /* +* NOTICE: if gadget driver wants to control +* pullup, it needs to make sure that when +* user tries to rmmod the gadget driver, it +* will disconnect the pullups before returning +* from its -unbind() method. +* +* We are truly trusting the gadget driver here. +*/ + if (!udc-driver-controls_pullups) + usb_gadget_disconnect(udc-gadget); + udc-driver-disconnect(udc-gadget); udc-driver-unbind(udc-gadget); usb_gadget_udc_stop(udc-gadget, udc-driver); @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver-unbind(udc-gadget); goto err1; } - usb_gadget_connect(udc-gadget); + + /* +* NOTICE: if gadget driver wants to control +* pullups, it needs to make sure its calls +* to usb_function_activate() and +* usb_function_deactivate() are balanced, +* otherwise gadget_driver will never enumerate. +* +* We are truly trusting the gadget driver here. +*/ + if (!driver-controls_pullups) + usb_gadget_connect(udc-gadget); kobject_uevent(udc-dev.kobj, KOBJ_CHANGE); return 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3c671c1b37f6..7ae797c85cb9 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -157,6 +157,7 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); + /* private: */ /* internals */ struct list_headlist; @@ -279,6 +280,8 @@ enum { * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. + * @controls_pullups: this driver will control pullup and udc-core shouldn't + * enable it by default * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -308,6 +311,7 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; enum usb_device_speed max_speed; unsignedneeds_serial:1; + unsignedcontrols_pullups:1; int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 32b734d88d6b..87971fa38f08 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -774,6
[PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. Signed-off-by: Robert Baldyga --- include/linux/usb/gadget.h | 100 ++--- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 4f3dfb7..15604bb 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -526,6 +526,9 @@ struct usb_gadget_ops { * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to * MaxPacketSize. * @is_selfpowered: if the gadget is self-powered. + * @deactivated: True if gadget is deactivated - in deactivated state it cannot + * be connected. + * @connected: True if gadget is connected. * * Gadgets have a mostly-portable "gadget driver" implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -568,6 +571,8 @@ struct usb_gadget { unsigneda_alt_hnp_support:1; unsignedquirk_ep_out_aligned_size:1; unsignedis_selfpowered:1; + unsigneddeactivated:1; + unsignedconnected:1; }; #define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) @@ -771,9 +776,24 @@ static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) */ static inline int usb_gadget_connect(struct usb_gadget *gadget) { + int ret; + if (!gadget->ops->pullup) return -EOPNOTSUPP; - return gadget->ops->pullup(gadget, 1); + + if (gadget->deactivated) { + /* +* If gadget is deactivated we only save new state. +* Gadget will be connected automatically after activation. +*/ + gadget->connected = true; + return 0; + } + + ret = gadget->ops->pullup(gadget, 1); + if (!ret) + gadget->connected = 1; + return ret; } /** @@ -784,20 +804,88 @@ static inline int usb_gadget_connect(struct usb_gadget *gadget) * as a disconnect (when a VBUS session is active). Not all systems * support software pullup controls. * + * Returns zero on success, else negative errno. + */ +static inline int usb_gadget_disconnect(struct usb_gadget *gadget) +{ + int ret; + + if (!gadget->ops->pullup) + return -EOPNOTSUPP; + + if (gadget->deactivated) { + /* +* If gadget is deactivated we only save new state. +* Gadget will stay disconnected after activation. +*/ + gadget->connected = false; + return 0; + } + + ret = gadget->ops->pullup(gadget, 0); + if (!ret) + gadget->connected = 0; + return ret; +} + +/** + * usb_gadget_deactivate - deactivate function which is not ready to work + * @gadget: the peripheral being deactivated + * * This routine may be used during the gadget driver bind() call to prevent * the peripheral from ever being visible to the USB host, unless later - * usb_gadget_connect() is called. For example, user mode components may + * usb_gadget_activate() is called. For example, user mode components may * need to be activated before the system can talk to hosts. * * Returns zero on success, else negative errno. */ -static inline int usb_gadget_disconnect(struct usb_gadget *gadget) +static inline int usb_gadget_deactivate(struct usb_gadget *gadget) { - if (!gadget->ops->pullup) - return -EOPNOTSUPP; - return gadget->ops->pullup(gadget, 0); + int ret; + + if (gadget->deactivated) + return 0; + + if (gadget->connected) { + ret = usb_gadget_disconnect(gadget); + if (ret) + return ret; + /* +* If gadget was being connected before deactivation, we want +* to reconnect it in usb_gadget_activate(). +*/ + gadget->connected = true; + } + gadget->deactivated = true; + + return 0; } +/** + * usb_gadget_activate - activate function which is not ready to work + * @gadget: the peripheral being activated + * + * This routine activates gadget which was previously deactivated with + * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. + * + * Returns zero on success, else negative errno. + */ +static inline int usb_gadget_activate(struct usb_gadget *gadget) +{ + if (!gadget->deactivated) + return 0; + +
[PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate functions
These functions allows to deactivate gadget to make it not visible to host and make it active again when gadget driver is finally ready. They are needed to fix usb_function_activate() and usb_function_deactivate() functions which currently are not working as usb_gadget_connect() is called immediately after function bind regardless to previous calls of usb_gadget_disconnect() function. Signed-off-by: Robert Baldyga r.bald...@samsung.com --- include/linux/usb/gadget.h | 100 ++--- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 4f3dfb7..15604bb 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -526,6 +526,9 @@ struct usb_gadget_ops { * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to * MaxPacketSize. * @is_selfpowered: if the gadget is self-powered. + * @deactivated: True if gadget is deactivated - in deactivated state it cannot + * be connected. + * @connected: True if gadget is connected. * * Gadgets have a mostly-portable gadget driver implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -568,6 +571,8 @@ struct usb_gadget { unsigneda_alt_hnp_support:1; unsignedquirk_ep_out_aligned_size:1; unsignedis_selfpowered:1; + unsigneddeactivated:1; + unsignedconnected:1; }; #define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) @@ -771,9 +776,24 @@ static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) */ static inline int usb_gadget_connect(struct usb_gadget *gadget) { + int ret; + if (!gadget-ops-pullup) return -EOPNOTSUPP; - return gadget-ops-pullup(gadget, 1); + + if (gadget-deactivated) { + /* +* If gadget is deactivated we only save new state. +* Gadget will be connected automatically after activation. +*/ + gadget-connected = true; + return 0; + } + + ret = gadget-ops-pullup(gadget, 1); + if (!ret) + gadget-connected = 1; + return ret; } /** @@ -784,20 +804,88 @@ static inline int usb_gadget_connect(struct usb_gadget *gadget) * as a disconnect (when a VBUS session is active). Not all systems * support software pullup controls. * + * Returns zero on success, else negative errno. + */ +static inline int usb_gadget_disconnect(struct usb_gadget *gadget) +{ + int ret; + + if (!gadget-ops-pullup) + return -EOPNOTSUPP; + + if (gadget-deactivated) { + /* +* If gadget is deactivated we only save new state. +* Gadget will stay disconnected after activation. +*/ + gadget-connected = false; + return 0; + } + + ret = gadget-ops-pullup(gadget, 0); + if (!ret) + gadget-connected = 0; + return ret; +} + +/** + * usb_gadget_deactivate - deactivate function which is not ready to work + * @gadget: the peripheral being deactivated + * * This routine may be used during the gadget driver bind() call to prevent * the peripheral from ever being visible to the USB host, unless later - * usb_gadget_connect() is called. For example, user mode components may + * usb_gadget_activate() is called. For example, user mode components may * need to be activated before the system can talk to hosts. * * Returns zero on success, else negative errno. */ -static inline int usb_gadget_disconnect(struct usb_gadget *gadget) +static inline int usb_gadget_deactivate(struct usb_gadget *gadget) { - if (!gadget-ops-pullup) - return -EOPNOTSUPP; - return gadget-ops-pullup(gadget, 0); + int ret; + + if (gadget-deactivated) + return 0; + + if (gadget-connected) { + ret = usb_gadget_disconnect(gadget); + if (ret) + return ret; + /* +* If gadget was being connected before deactivation, we want +* to reconnect it in usb_gadget_activate(). +*/ + gadget-connected = true; + } + gadget-deactivated = true; + + return 0; } +/** + * usb_gadget_activate - activate function which is not ready to work + * @gadget: the peripheral being activated + * + * This routine activates gadget which was previously deactivated with + * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. + * + * Returns zero on success, else negative errno. + */ +static inline int usb_gadget_activate(struct usb_gadget *gadget) +{ + if (!gadget-deactivated) + return 0; + +