diff options
author | Bruno Prémont <bonbons@linux-vserver.org> | 2010-04-25 15:40:03 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-04-27 09:22:00 -0400 |
commit | 6a740aa4f47b9f29bad5292cf51f008f3edad9b1 (patch) | |
tree | 179e1388bfb21bf17a93c045c29141d8bdc192b4 | |
parent | ab195c58b864802c15e494f06ae109413e12d50b (diff) |
HID: add suspend/resume hooks for hid drivers
Add suspend/resume hooks for HID drivers so these can do some
additional state adjustment when device gets suspended/resumed.
Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 24 | ||||
-rw-r--r-- | include/linux/hid.h | 8 |
2 files changed, 31 insertions, 1 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075b..14a67fba590e 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -1290,6 +1290,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1290 | { | 1290 | { |
1291 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1291 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1292 | spin_unlock_irq(&usbhid->lock); | 1292 | spin_unlock_irq(&usbhid->lock); |
1293 | if (hid->driver && hid->driver->suspend) { | ||
1294 | status = hid->driver->suspend(hid, message); | ||
1295 | if (status < 0) | ||
1296 | return status; | ||
1297 | } | ||
1293 | } else { | 1298 | } else { |
1294 | usbhid_mark_busy(usbhid); | 1299 | usbhid_mark_busy(usbhid); |
1295 | spin_unlock_irq(&usbhid->lock); | 1300 | spin_unlock_irq(&usbhid->lock); |
@@ -1297,6 +1302,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1297 | } | 1302 | } |
1298 | 1303 | ||
1299 | } else { | 1304 | } else { |
1305 | if (hid->driver && hid->driver->suspend) { | ||
1306 | status = hid->driver->suspend(hid, message); | ||
1307 | if (status < 0) | ||
1308 | return status; | ||
1309 | } | ||
1300 | spin_lock_irq(&usbhid->lock); | 1310 | spin_lock_irq(&usbhid->lock); |
1301 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1311 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1302 | spin_unlock_irq(&usbhid->lock); | 1312 | spin_unlock_irq(&usbhid->lock); |
@@ -1351,6 +1361,11 @@ static int hid_resume(struct usb_interface *intf) | |||
1351 | hid_io_error(hid); | 1361 | hid_io_error(hid); |
1352 | usbhid_restart_queues(usbhid); | 1362 | usbhid_restart_queues(usbhid); |
1353 | 1363 | ||
1364 | if (status >= 0 && hid->driver && hid->driver->resume) { | ||
1365 | int ret = hid->driver->resume(hid); | ||
1366 | if (ret < 0) | ||
1367 | status = ret; | ||
1368 | } | ||
1354 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1369 | dev_dbg(&intf->dev, "resume status %d\n", status); |
1355 | return 0; | 1370 | return 0; |
1356 | } | 1371 | } |
@@ -1359,9 +1374,16 @@ static int hid_reset_resume(struct usb_interface *intf) | |||
1359 | { | 1374 | { |
1360 | struct hid_device *hid = usb_get_intfdata(intf); | 1375 | struct hid_device *hid = usb_get_intfdata(intf); |
1361 | struct usbhid_device *usbhid = hid->driver_data; | 1376 | struct usbhid_device *usbhid = hid->driver_data; |
1377 | int status; | ||
1362 | 1378 | ||
1363 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1379 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1364 | return hid_post_reset(intf); | 1380 | status = hid_post_reset(intf); |
1381 | if (status >= 0 && hid->driver && hid->driver->reset_resume) { | ||
1382 | int ret = hid->driver->reset_resume(hid); | ||
1383 | if (ret < 0) | ||
1384 | status = ret; | ||
1385 | } | ||
1386 | return status; | ||
1365 | } | 1387 | } |
1366 | 1388 | ||
1367 | #endif /* CONFIG_PM */ | 1389 | #endif /* CONFIG_PM */ |
diff --git a/include/linux/hid.h b/include/linux/hid.h index b1344ec4b7fc..069e587ae8e6 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -589,6 +589,9 @@ struct hid_usage_id { | |||
589 | * @report_fixup: called before report descriptor parsing (NULL means nop) | 589 | * @report_fixup: called before report descriptor parsing (NULL means nop) |
590 | * @input_mapping: invoked on input registering before mapping an usage | 590 | * @input_mapping: invoked on input registering before mapping an usage |
591 | * @input_mapped: invoked on input registering after mapping an usage | 591 | * @input_mapped: invoked on input registering after mapping an usage |
592 | * @suspend: invoked on suspend (NULL means nop) | ||
593 | * @resume: invoked on resume if device was not reset (NULL means nop) | ||
594 | * @reset_resume: invoked on resume if device was reset (NULL means nop) | ||
592 | * | 595 | * |
593 | * raw_event and event should return 0 on no action performed, 1 when no | 596 | * raw_event and event should return 0 on no action performed, 1 when no |
594 | * further processing should be done and negative on error | 597 | * further processing should be done and negative on error |
@@ -629,6 +632,11 @@ struct hid_driver { | |||
629 | int (*input_mapped)(struct hid_device *hdev, | 632 | int (*input_mapped)(struct hid_device *hdev, |
630 | struct hid_input *hidinput, struct hid_field *field, | 633 | struct hid_input *hidinput, struct hid_field *field, |
631 | struct hid_usage *usage, unsigned long **bit, int *max); | 634 | struct hid_usage *usage, unsigned long **bit, int *max); |
635 | #ifdef CONFIG_PM | ||
636 | int (*suspend)(struct hid_device *hdev, pm_message_t message); | ||
637 | int (*resume)(struct hid_device *hdev); | ||
638 | int (*reset_resume)(struct hid_device *hdev); | ||
639 | #endif | ||
632 | /* private: */ | 640 | /* private: */ |
633 | struct device_driver driver; | 641 | struct device_driver driver; |
634 | }; | 642 | }; |