diff options
| author | Oliver Neukum <oliver@neukum.org> | 2008-04-15 01:31:57 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-04-15 01:31:57 -0400 |
| commit | e722409445fbe718f09f6d5e03d0ae84cf0954d0 (patch) | |
| tree | 490d1fd96cec28b3e5a00ab0ce401d52d720f3cb /drivers/input | |
| parent | 04021e4e401d7ac2051839dd5b00a701c9119dd9 (diff) | |
Input: wacom - implement suspend and autosuspend
This implements suspend and autosuspend support for wacom devices.
It works by using the usb last busy functionality triggered in the
completion callback.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/tablet/wacom.h | 3 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_sys.c | 76 |
2 files changed, 69 insertions, 10 deletions
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index acf9830698cb..706619d06f71 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
| @@ -101,8 +101,11 @@ struct wacom { | |||
| 101 | dma_addr_t data_dma; | 101 | dma_addr_t data_dma; |
| 102 | struct input_dev *dev; | 102 | struct input_dev *dev; |
| 103 | struct usb_device *usbdev; | 103 | struct usb_device *usbdev; |
| 104 | struct usb_interface *intf; | ||
| 104 | struct urb *irq; | 105 | struct urb *irq; |
| 105 | struct wacom_wac * wacom_wac; | 106 | struct wacom_wac * wacom_wac; |
| 107 | struct mutex lock; | ||
| 108 | int open:1; | ||
| 106 | char phys[32]; | 109 | char phys[32]; |
| 107 | }; | 110 | }; |
| 108 | 111 | ||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 41caaef8e2d7..71cc0c140790 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -70,6 +70,7 @@ static void wacom_sys_irq(struct urb *urb) | |||
| 70 | input_sync(get_input_dev(&wcombo)); | 70 | input_sync(get_input_dev(&wcombo)); |
| 71 | 71 | ||
| 72 | exit: | 72 | exit: |
| 73 | usb_mark_last_busy(wacom->usbdev); | ||
| 73 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 74 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
| 74 | if (retval) | 75 | if (retval) |
| 75 | err ("%s - usb_submit_urb failed with result %d", | 76 | err ("%s - usb_submit_urb failed with result %d", |
| @@ -124,10 +125,25 @@ static int wacom_open(struct input_dev *dev) | |||
| 124 | { | 125 | { |
| 125 | struct wacom *wacom = input_get_drvdata(dev); | 126 | struct wacom *wacom = input_get_drvdata(dev); |
| 126 | 127 | ||
| 128 | mutex_lock(&wacom->lock); | ||
| 129 | |||
| 127 | wacom->irq->dev = wacom->usbdev; | 130 | wacom->irq->dev = wacom->usbdev; |
| 128 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | 131 | |
| 132 | if (usb_autopm_get_interface(wacom->intf) < 0) { | ||
| 133 | mutex_unlock(&wacom->lock); | ||
| 129 | return -EIO; | 134 | return -EIO; |
| 135 | } | ||
| 136 | |||
| 137 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { | ||
| 138 | usb_autopm_put_interface(wacom->intf); | ||
| 139 | mutex_unlock(&wacom->lock); | ||
| 140 | return -EIO; | ||
| 141 | } | ||
| 142 | |||
| 143 | wacom->open = 1; | ||
| 144 | wacom->intf->needs_remote_wakeup = 1; | ||
| 130 | 145 | ||
| 146 | mutex_unlock(&wacom->lock); | ||
| 131 | return 0; | 147 | return 0; |
| 132 | } | 148 | } |
| 133 | 149 | ||
| @@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev) | |||
| 135 | { | 151 | { |
| 136 | struct wacom *wacom = input_get_drvdata(dev); | 152 | struct wacom *wacom = input_get_drvdata(dev); |
| 137 | 153 | ||
| 154 | mutex_lock(&wacom->lock); | ||
| 138 | usb_kill_urb(wacom->irq); | 155 | usb_kill_urb(wacom->irq); |
| 156 | wacom->open = 0; | ||
| 157 | wacom->intf->needs_remote_wakeup = 0; | ||
| 158 | mutex_unlock(&wacom->lock); | ||
| 139 | } | 159 | } |
| 140 | 160 | ||
| 141 | void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 161 | void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| @@ -243,6 +263,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 243 | 263 | ||
| 244 | wacom->usbdev = dev; | 264 | wacom->usbdev = dev; |
| 245 | wacom->dev = input_dev; | 265 | wacom->dev = input_dev; |
| 266 | wacom->intf = intf; | ||
| 267 | mutex_init(&wacom->lock); | ||
| 246 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | 268 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); |
| 247 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | 269 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); |
| 248 | 270 | ||
| @@ -304,23 +326,57 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 304 | 326 | ||
| 305 | static void wacom_disconnect(struct usb_interface *intf) | 327 | static void wacom_disconnect(struct usb_interface *intf) |
| 306 | { | 328 | { |
| 307 | struct wacom *wacom = usb_get_intfdata (intf); | 329 | struct wacom *wacom = usb_get_intfdata(intf); |
| 308 | 330 | ||
| 309 | usb_set_intfdata(intf, NULL); | 331 | usb_set_intfdata(intf, NULL); |
| 310 | if (wacom) { | 332 | |
| 311 | usb_kill_urb(wacom->irq); | 333 | usb_kill_urb(wacom->irq); |
| 312 | input_unregister_device(wacom->dev); | 334 | input_unregister_device(wacom->dev); |
| 313 | usb_free_urb(wacom->irq); | 335 | usb_free_urb(wacom->irq); |
| 314 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); | 336 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); |
| 315 | kfree(wacom->wacom_wac); | 337 | kfree(wacom->wacom_wac); |
| 316 | kfree(wacom); | 338 | kfree(wacom); |
| 317 | } | 339 | } |
| 340 | |||
| 341 | static int wacom_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 342 | { | ||
| 343 | struct wacom *wacom = usb_get_intfdata(intf); | ||
| 344 | |||
| 345 | mutex_lock(&wacom->lock); | ||
| 346 | usb_kill_urb(wacom->irq); | ||
| 347 | mutex_unlock(&wacom->lock); | ||
| 348 | |||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | static int wacom_resume(struct usb_interface *intf) | ||
| 353 | { | ||
| 354 | struct wacom *wacom = usb_get_intfdata(intf); | ||
| 355 | int rv; | ||
| 356 | |||
| 357 | mutex_lock(&wacom->lock); | ||
| 358 | if (wacom->open) | ||
| 359 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | ||
| 360 | else | ||
| 361 | rv = 0; | ||
| 362 | mutex_unlock(&wacom->lock); | ||
| 363 | |||
| 364 | return rv; | ||
| 365 | } | ||
| 366 | |||
| 367 | static int wacom_reset_resume(struct usb_interface *intf) | ||
| 368 | { | ||
| 369 | return wacom_resume(intf); | ||
| 318 | } | 370 | } |
| 319 | 371 | ||
| 320 | static struct usb_driver wacom_driver = { | 372 | static struct usb_driver wacom_driver = { |
| 321 | .name = "wacom", | 373 | .name = "wacom", |
| 322 | .probe = wacom_probe, | 374 | .probe = wacom_probe, |
| 323 | .disconnect = wacom_disconnect, | 375 | .disconnect = wacom_disconnect, |
| 376 | .suspend = wacom_suspend, | ||
| 377 | .resume = wacom_resume, | ||
| 378 | .reset_resume = wacom_reset_resume, | ||
| 379 | .supports_autosuspend = 1, | ||
| 324 | }; | 380 | }; |
| 325 | 381 | ||
| 326 | static int __init wacom_init(void) | 382 | static int __init wacom_init(void) |
