diff options
-rw-r--r-- | drivers/usb/gadget/f_loopback.c | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/f_sourcesink.c | 52 | ||||
-rw-r--r-- | drivers/usb/gadget/g_zero.h | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/zero.c | 70 |
4 files changed, 74 insertions, 58 deletions
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 83301bdcdd1a..eb6ddfc20857 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c | |||
@@ -359,7 +359,7 @@ static struct usb_configuration loopback_driver = { | |||
359 | * loopback_add - add a loopback testing configuration to a device | 359 | * loopback_add - add a loopback testing configuration to a device |
360 | * @cdev: the device to support the loopback configuration | 360 | * @cdev: the device to support the loopback configuration |
361 | */ | 361 | */ |
362 | int __init loopback_add(struct usb_composite_dev *cdev) | 362 | int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume) |
363 | { | 363 | { |
364 | int id; | 364 | int id; |
365 | 365 | ||
@@ -372,6 +372,10 @@ int __init loopback_add(struct usb_composite_dev *cdev) | |||
372 | loopback_intf.iInterface = id; | 372 | loopback_intf.iInterface = id; |
373 | loopback_driver.iConfiguration = id; | 373 | loopback_driver.iConfiguration = id; |
374 | 374 | ||
375 | /* support autoresume for remote wakeup testing */ | ||
376 | if (autoresume) | ||
377 | sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | ||
378 | |||
375 | /* support OTG systems */ | 379 | /* support OTG systems */ |
376 | if (gadget_is_otg(cdev->gadget)) { | 380 | if (gadget_is_otg(cdev->gadget)) { |
377 | loopback_driver.descriptors = otg_desc; | 381 | loopback_driver.descriptors = otg_desc; |
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6aca5c81414a..bffe91d525f9 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c | |||
@@ -59,7 +59,6 @@ struct f_sourcesink { | |||
59 | 59 | ||
60 | struct usb_ep *in_ep; | 60 | struct usb_ep *in_ep; |
61 | struct usb_ep *out_ep; | 61 | struct usb_ep *out_ep; |
62 | struct timer_list resume; | ||
63 | }; | 62 | }; |
64 | 63 | ||
65 | static inline struct f_sourcesink *func_to_ss(struct usb_function *f) | 64 | static inline struct f_sourcesink *func_to_ss(struct usb_function *f) |
@@ -67,10 +66,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f) | |||
67 | return container_of(f, struct f_sourcesink, function); | 66 | return container_of(f, struct f_sourcesink, function); |
68 | } | 67 | } |
69 | 68 | ||
70 | static unsigned autoresume; | ||
71 | module_param(autoresume, uint, 0); | ||
72 | MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); | ||
73 | |||
74 | static unsigned pattern; | 69 | static unsigned pattern; |
75 | module_param(pattern, uint, 0); | 70 | module_param(pattern, uint, 0); |
76 | MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); | 71 | MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); |
@@ -155,21 +150,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = { | |||
155 | 150 | ||
156 | /*-------------------------------------------------------------------------*/ | 151 | /*-------------------------------------------------------------------------*/ |
157 | 152 | ||
158 | static void sourcesink_autoresume(unsigned long _c) | ||
159 | { | ||
160 | struct usb_composite_dev *cdev = (void *)_c; | ||
161 | struct usb_gadget *g = cdev->gadget; | ||
162 | |||
163 | /* Normally the host would be woken up for something | ||
164 | * more significant than just a timer firing; likely | ||
165 | * because of some direct user request. | ||
166 | */ | ||
167 | if (g->speed != USB_SPEED_UNKNOWN) { | ||
168 | int status = usb_gadget_wakeup(g); | ||
169 | DBG(cdev, "%s --> %d\n", __func__, status); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static int __init | 153 | static int __init |
174 | sourcesink_bind(struct usb_configuration *c, struct usb_function *f) | 154 | sourcesink_bind(struct usb_configuration *c, struct usb_function *f) |
175 | { | 155 | { |
@@ -198,9 +178,6 @@ autoconf_fail: | |||
198 | goto autoconf_fail; | 178 | goto autoconf_fail; |
199 | ss->out_ep->driver_data = cdev; /* claim */ | 179 | ss->out_ep->driver_data = cdev; /* claim */ |
200 | 180 | ||
201 | setup_timer(&ss->resume, sourcesink_autoresume, | ||
202 | (unsigned long) c->cdev); | ||
203 | |||
204 | /* support high speed hardware */ | 181 | /* support high speed hardware */ |
205 | if (gadget_is_dualspeed(c->cdev->gadget)) { | 182 | if (gadget_is_dualspeed(c->cdev->gadget)) { |
206 | hs_source_desc.bEndpointAddress = | 183 | hs_source_desc.bEndpointAddress = |
@@ -359,7 +336,6 @@ static void disable_source_sink(struct f_sourcesink *ss) | |||
359 | 336 | ||
360 | cdev = ss->function.config->cdev; | 337 | cdev = ss->function.config->cdev; |
361 | disable_endpoints(cdev, ss->in_ep, ss->out_ep); | 338 | disable_endpoints(cdev, ss->in_ep, ss->out_ep); |
362 | del_timer(&ss->resume); | ||
363 | VDBG(cdev, "%s disabled\n", ss->function.name); | 339 | VDBG(cdev, "%s disabled\n", ss->function.name); |
364 | } | 340 | } |
365 | 341 | ||
@@ -426,30 +402,6 @@ static void sourcesink_disable(struct usb_function *f) | |||
426 | disable_source_sink(ss); | 402 | disable_source_sink(ss); |
427 | } | 403 | } |
428 | 404 | ||
429 | static void sourcesink_suspend(struct usb_function *f) | ||
430 | { | ||
431 | struct f_sourcesink *ss = func_to_ss(f); | ||
432 | struct usb_composite_dev *cdev = f->config->cdev; | ||
433 | |||
434 | if (cdev->gadget->speed == USB_SPEED_UNKNOWN) | ||
435 | return; | ||
436 | |||
437 | if (autoresume) { | ||
438 | mod_timer(&ss->resume, jiffies + (HZ * autoresume)); | ||
439 | DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); | ||
440 | } else | ||
441 | DBG(cdev, "%s\n", __func__); | ||
442 | } | ||
443 | |||
444 | static void sourcesink_resume(struct usb_function *f) | ||
445 | { | ||
446 | struct f_sourcesink *ss = func_to_ss(f); | ||
447 | struct usb_composite_dev *cdev = f->config->cdev; | ||
448 | |||
449 | DBG(cdev, "%s\n", __func__); | ||
450 | del_timer(&ss->resume); | ||
451 | } | ||
452 | |||
453 | /*-------------------------------------------------------------------------*/ | 405 | /*-------------------------------------------------------------------------*/ |
454 | 406 | ||
455 | static int __init sourcesink_bind_config(struct usb_configuration *c) | 407 | static int __init sourcesink_bind_config(struct usb_configuration *c) |
@@ -467,8 +419,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) | |||
467 | ss->function.unbind = sourcesink_unbind; | 419 | ss->function.unbind = sourcesink_unbind; |
468 | ss->function.set_alt = sourcesink_set_alt; | 420 | ss->function.set_alt = sourcesink_set_alt; |
469 | ss->function.disable = sourcesink_disable; | 421 | ss->function.disable = sourcesink_disable; |
470 | ss->function.suspend = sourcesink_suspend; | ||
471 | ss->function.resume = sourcesink_resume; | ||
472 | 422 | ||
473 | status = usb_add_function(c, &ss->function); | 423 | status = usb_add_function(c, &ss->function); |
474 | if (status) | 424 | if (status) |
@@ -559,7 +509,7 @@ static struct usb_configuration sourcesink_driver = { | |||
559 | * sourcesink_add - add a source/sink testing configuration to a device | 509 | * sourcesink_add - add a source/sink testing configuration to a device |
560 | * @cdev: the device to support the configuration | 510 | * @cdev: the device to support the configuration |
561 | */ | 511 | */ |
562 | int __init sourcesink_add(struct usb_composite_dev *cdev) | 512 | int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) |
563 | { | 513 | { |
564 | int id; | 514 | int id; |
565 | 515 | ||
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index dd2f16ad5a88..e84b3c47ed3c 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h | |||
@@ -19,7 +19,7 @@ void disable_endpoints(struct usb_composite_dev *cdev, | |||
19 | struct usb_ep *in, struct usb_ep *out); | 19 | struct usb_ep *in, struct usb_ep *out); |
20 | 20 | ||
21 | /* configuration-specific linkup */ | 21 | /* configuration-specific linkup */ |
22 | int sourcesink_add(struct usb_composite_dev *cdev); | 22 | int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume); |
23 | int loopback_add(struct usb_composite_dev *cdev); | 23 | int loopback_add(struct usb_composite_dev *cdev, bool autoresume); |
24 | 24 | ||
25 | #endif /* __G_ZERO_H */ | 25 | #endif /* __G_ZERO_H */ |
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 | */ | ||
116 | unsigned autoresume = DEFAULT_AUTORESUME; | ||
117 | module_param(autoresume, uint, S_IRUGO); | ||
118 | MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); | ||
119 | |||
110 | /*-------------------------------------------------------------------------*/ | 120 | /*-------------------------------------------------------------------------*/ |
111 | 121 | ||
112 | static struct usb_device_descriptor device_desc = { | 122 | static struct usb_device_descriptor device_desc = { |
@@ -212,6 +222,47 @@ void disable_endpoints(struct usb_composite_dev *cdev, | |||
212 | 222 | ||
213 | /*-------------------------------------------------------------------------*/ | 223 | /*-------------------------------------------------------------------------*/ |
214 | 224 | ||
225 | static struct timer_list autoresume_timer; | ||
226 | |||
227 | static 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 | |||
246 | static 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 | |||
258 | static void zero_resume(struct usb_composite_dev *cdev) | ||
259 | { | ||
260 | DBG(cdev, "%s\n", __func__); | ||
261 | del_timer(&autoresume_timer); | ||
262 | } | ||
263 | |||
264 | /*-------------------------------------------------------------------------*/ | ||
265 | |||
215 | static int __init zero_bind(struct usb_composite_dev *cdev) | 266 | static 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 | ||
334 | static int zero_unbind(struct usb_composite_dev *cdev) | ||
335 | { | ||
336 | del_timer_sync(&autoresume_timer); | ||
337 | return 0; | ||
338 | } | ||
339 | |||
281 | static struct usb_composite_driver zero_driver = { | 340 | static 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 | ||
288 | MODULE_AUTHOR("David Brownell"); | 350 | MODULE_AUTHOR("David Brownell"); |