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"); |
