Re: [RFC] usb: gadget: Ensure correct functionality for gadgets that wish to 'connect' only when directed by user-space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Thu, Jul 26, 2012 at 06:28:36PM +0800, Bhupesh SHARMA wrote:
> > I just doesn't work :-) Calling usb_gadget_disconnect() during bind
> > doesn't
> > prevent the device from being visible to the USB host. Bhupesh has
> > analyzed
> > the problem and submitted this RFC as a possible fix.

how about something like this instead:

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 3f72110..3390af2 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1640,6 +1640,8 @@ int usb_composite_probe(struct usb_composite_driver *driver,
 	composite = driver;
 	composite_gadget_bind = bind;
 
+	composite_driver.controls_pullup = driver->controls_pullup;
+
 	return usb_gadget_probe_driver(&composite_driver, composite_bind);
 }
 
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index e5e44f8..d8b4dc3 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -263,7 +263,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
 	if (udc_is_newstyle(udc)) {
 		udc->driver->disconnect(udc->gadget);
-		usb_gadget_disconnect(udc->gadget);
+
+		if (!udc->driver->controls_pullup)
+			usb_gadget_disconnect(udc->gadget);
+
 		udc->driver->unbind(udc->gadget);
 		usb_gadget_udc_stop(udc->gadget, udc->driver);
 	} else {
@@ -347,7 +350,9 @@ found:
 			driver->unbind(udc->gadget);
 			goto err1;
 		}
-		usb_gadget_connect(udc->gadget);
+
+		if (!driver->controls_pullup)
+			usb_gadget_connect(udc->gadget);
 	} else {
 
 		ret = usb_gadget_start(udc->gadget, driver, bind);
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index 120e134..1cfd951 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -396,6 +396,8 @@ static struct usb_composite_driver webcam_driver = {
 	.strings	= webcam_device_strings,
 	.max_speed	= USB_SPEED_SUPER,
 	.unbind		= webcam_unbind,
+
+	.controls_pullup = true,
 };
 
 static int __init
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 9d8c3b6..28326e5 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -262,6 +262,8 @@ void usb_remove_config(struct usb_composite_dev *,
  * @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_pullup: this driver will control pullup and udc-core shouldn't
+ *	enable it by default
  * @unbind: Reverses bind; called as a side effect of unregistering
  *	this driver.
  * @disconnect: optional driver disconnect method
@@ -290,6 +292,7 @@ struct usb_composite_driver {
 	struct usb_gadget_strings		**strings;
 	enum usb_device_speed			max_speed;
 	unsigned		needs_serial:1;
+	unsigned		controls_pullup:1;
 
 	int			(*unbind)(struct usb_composite_dev *);
 
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 9517466..eaa50ab 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -787,6 +787,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
  * @suspend: Invoked on USB suspend.  May be called in_interrupt.
  * @resume: Invoked on USB resume.  May be called in_interrupt.
  * @driver: Driver model state for this driver.
+ * @controls_pullup: tells udc-core to not enable pullups by default
  *
  * Devices are disabled till a gadget driver successfully bind()s, which
  * means the driver will handle setup() requests needed to enumerate (and
@@ -844,6 +845,8 @@ struct usb_gadget_driver {
 
 	/* FIXME support safe rmmod */
 	struct device_driver	driver;
+
+	unsigned		controls_pullup:1;
 };
 
 

All that's missing now is for uvc gadget to call
usb_function_activate/usb_function_deactivate() and the correct
locations. Make sure to call it from your ->disconnect() method as
udc-core won't do that for you by default.

> Yes. Felipe, plz go through the problem description as mentioned in the patch log
> message which can be seen here:
> http://permalink.gmane.org/gmane.linux.usb.general/66585

sure, please see above patch. The difference is that this has no impact
on the controller drivers.

-- 
balbi

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux