Commit 6a740aa4 authored by Bruno Prémont's avatar Bruno Prémont Committed by Jiri Kosina

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: default avatarBruno Prémont <bonbons@linux-vserver.org>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent ab195c58
...@@ -1290,6 +1290,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1290,6 +1290,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
{ {
set_bit(HID_REPORTED_IDLE, &usbhid->iofl); set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
if (hid->driver && hid->driver->suspend) {
status = hid->driver->suspend(hid, message);
if (status < 0)
return status;
}
} else { } else {
usbhid_mark_busy(usbhid); usbhid_mark_busy(usbhid);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
...@@ -1297,6 +1302,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1297,6 +1302,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
} }
} else { } else {
if (hid->driver && hid->driver->suspend) {
status = hid->driver->suspend(hid, message);
if (status < 0)
return status;
}
spin_lock_irq(&usbhid->lock); spin_lock_irq(&usbhid->lock);
set_bit(HID_REPORTED_IDLE, &usbhid->iofl); set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
...@@ -1351,6 +1361,11 @@ static int hid_resume(struct usb_interface *intf) ...@@ -1351,6 +1361,11 @@ static int hid_resume(struct usb_interface *intf)
hid_io_error(hid); hid_io_error(hid);
usbhid_restart_queues(usbhid); usbhid_restart_queues(usbhid);
if (status >= 0 && hid->driver && hid->driver->resume) {
int ret = hid->driver->resume(hid);
if (ret < 0)
status = ret;
}
dev_dbg(&intf->dev, "resume status %d\n", status); dev_dbg(&intf->dev, "resume status %d\n", status);
return 0; return 0;
} }
...@@ -1359,9 +1374,16 @@ static int hid_reset_resume(struct usb_interface *intf) ...@@ -1359,9 +1374,16 @@ static int hid_reset_resume(struct usb_interface *intf)
{ {
struct hid_device *hid = usb_get_intfdata(intf); struct hid_device *hid = usb_get_intfdata(intf);
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
int status;
clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);
return hid_post_reset(intf); status = hid_post_reset(intf);
if (status >= 0 && hid->driver && hid->driver->reset_resume) {
int ret = hid->driver->reset_resume(hid);
if (ret < 0)
status = ret;
}
return status;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
...@@ -589,6 +589,9 @@ struct hid_usage_id { ...@@ -589,6 +589,9 @@ struct hid_usage_id {
* @report_fixup: called before report descriptor parsing (NULL means nop) * @report_fixup: called before report descriptor parsing (NULL means nop)
* @input_mapping: invoked on input registering before mapping an usage * @input_mapping: invoked on input registering before mapping an usage
* @input_mapped: invoked on input registering after mapping an usage * @input_mapped: invoked on input registering after mapping an usage
* @suspend: invoked on suspend (NULL means nop)
* @resume: invoked on resume if device was not reset (NULL means nop)
* @reset_resume: invoked on resume if device was reset (NULL means nop)
* *
* raw_event and event should return 0 on no action performed, 1 when no * raw_event and event should return 0 on no action performed, 1 when no
* further processing should be done and negative on error * further processing should be done and negative on error
...@@ -629,6 +632,11 @@ struct hid_driver { ...@@ -629,6 +632,11 @@ struct hid_driver {
int (*input_mapped)(struct hid_device *hdev, int (*input_mapped)(struct hid_device *hdev,
struct hid_input *hidinput, struct hid_field *field, struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max); struct hid_usage *usage, unsigned long **bit, int *max);
#ifdef CONFIG_PM
int (*suspend)(struct hid_device *hdev, pm_message_t message);
int (*resume)(struct hid_device *hdev);
int (*reset_resume)(struct hid_device *hdev);
#endif
/* private: */ /* private: */
struct device_driver driver; struct device_driver driver;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment