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