aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/zero.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-03-19 17:16:09 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:45 -0400
commitab943a2e125b098489ccaa0166c2c52f8266d9ed (patch)
treeb50c7e28683f0cb0d982f0e9f164d2b5844eefef /drivers/usb/gadget/zero.c
parent8942939a6c83f34615de5ae041cc9ca846923f94 (diff)
USB: gadget: gadget zero uses new suspend/resume hooks
Use the new device-level suspend/resume hooks for Gadget Zero; always enable them with the OTG test mode; and support remote wakeup on both configurations even in non-OTG mode. This ensures that both configurations can pass the USBCV remote wakeup tests when the OTG test mode is enabled. This changes behavior by adding autoresume support to the loopback config even in non-OTG mode; the test failure was that it didn't work in OTG mode. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/zero.c')
-rw-r--r--drivers/usb/gadget/zero.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 20614dce8db9..2d772401b7ad 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -102,11 +102,21 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
102#ifndef CONFIG_USB_ZERO_HNPTEST 102#ifndef CONFIG_USB_ZERO_HNPTEST
103#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ 103#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
104#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ 104#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */
105#define DEFAULT_AUTORESUME 0
105#else 106#else
106#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ 107#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */
107#define DRIVER_PRODUCT_NUM 0xbadd 108#define DRIVER_PRODUCT_NUM 0xbadd
109#define DEFAULT_AUTORESUME 5
108#endif 110#endif
109 111
112/* If the optional "autoresume" mode is enabled, it provides good
113 * functional coverage for the "USBCV" test harness from USB-IF.
114 * It's always set if OTG mode is enabled.
115 */
116unsigned autoresume = DEFAULT_AUTORESUME;
117module_param(autoresume, uint, S_IRUGO);
118MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
119
110/*-------------------------------------------------------------------------*/ 120/*-------------------------------------------------------------------------*/
111 121
112static struct usb_device_descriptor device_desc = { 122static struct usb_device_descriptor device_desc = {
@@ -212,6 +222,47 @@ void disable_endpoints(struct usb_composite_dev *cdev,
212 222
213/*-------------------------------------------------------------------------*/ 223/*-------------------------------------------------------------------------*/
214 224
225static struct timer_list autoresume_timer;
226
227static void zero_autoresume(unsigned long _c)
228{
229 struct usb_composite_dev *cdev = (void *)_c;
230 struct usb_gadget *g = cdev->gadget;
231
232 /* unconfigured devices can't issue wakeups */
233 if (!cdev->config)
234 return;
235
236 /* Normally the host would be woken up for something
237 * more significant than just a timer firing; likely
238 * because of some direct user request.
239 */
240 if (g->speed != USB_SPEED_UNKNOWN) {
241 int status = usb_gadget_wakeup(g);
242 INFO(cdev, "%s --> %d\n", __func__, status);
243 }
244}
245
246static void zero_suspend(struct usb_composite_dev *cdev)
247{
248 if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
249 return;
250
251 if (autoresume) {
252 mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
253 DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
254 } else
255 DBG(cdev, "%s\n", __func__);
256}
257
258static void zero_resume(struct usb_composite_dev *cdev)
259{
260 DBG(cdev, "%s\n", __func__);
261 del_timer(&autoresume_timer);
262}
263
264/*-------------------------------------------------------------------------*/
265
215static int __init zero_bind(struct usb_composite_dev *cdev) 266static int __init zero_bind(struct usb_composite_dev *cdev)
216{ 267{
217 int gcnum; 268 int gcnum;
@@ -239,17 +290,19 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
239 strings_dev[STRING_SERIAL_IDX].id = id; 290 strings_dev[STRING_SERIAL_IDX].id = id;
240 device_desc.iSerialNumber = id; 291 device_desc.iSerialNumber = id;
241 292
293 setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
294
242 /* Register primary, then secondary configuration. Note that 295 /* Register primary, then secondary configuration. Note that
243 * SH3 only allows one config... 296 * SH3 only allows one config...
244 */ 297 */
245 if (loopdefault) { 298 if (loopdefault) {
246 loopback_add(cdev); 299 loopback_add(cdev, autoresume != 0);
247 if (!gadget_is_sh(gadget)) 300 if (!gadget_is_sh(gadget))
248 sourcesink_add(cdev); 301 sourcesink_add(cdev, autoresume != 0);
249 } else { 302 } else {
250 sourcesink_add(cdev); 303 sourcesink_add(cdev, autoresume != 0);
251 if (!gadget_is_sh(gadget)) 304 if (!gadget_is_sh(gadget))
252 loopback_add(cdev); 305 loopback_add(cdev, autoresume != 0);
253 } 306 }
254 307
255 gcnum = usb_gadget_controller_number(gadget); 308 gcnum = usb_gadget_controller_number(gadget);
@@ -278,11 +331,20 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
278 return 0; 331 return 0;
279} 332}
280 333
334static int zero_unbind(struct usb_composite_dev *cdev)
335{
336 del_timer_sync(&autoresume_timer);
337 return 0;
338}
339
281static struct usb_composite_driver zero_driver = { 340static struct usb_composite_driver zero_driver = {
282 .name = "zero", 341 .name = "zero",
283 .dev = &device_desc, 342 .dev = &device_desc,
284 .strings = dev_strings, 343 .strings = dev_strings,
285 .bind = zero_bind, 344 .bind = zero_bind,
345 .unbind = zero_unbind,
346 .suspend = zero_suspend,
347 .resume = zero_resume,
286}; 348};
287 349
288MODULE_AUTHOR("David Brownell"); 350MODULE_AUTHOR("David Brownell");