Input: release pressed keys when resuming device

As the kernel has no way to know whether a key was released
while the system was asleep, keys need to be reported released
as the system is resumed, lest autorepeat set in.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Oliver Neukum 2010-07-01 09:01:50 -07:00 committed by Dmitry Torokhov
parent 3eac5c7e44
commit 866d7d7b4a

View file

@ -527,13 +527,31 @@ void input_close_device(struct input_handle *handle)
}
EXPORT_SYMBOL(input_close_device);
/*
* Simulate keyup events for all keys that are marked as pressed.
* The function must be called with dev->event_lock held.
*/
static void input_dev_release_keys(struct input_dev *dev)
{
int code;
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
}
}
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
}
}
/*
* Prepare device for unregistering
*/
static void input_disconnect_device(struct input_dev *dev)
{
struct input_handle *handle;
int code;
/*
* Mark device as going away. Note that we take dev->mutex here
@ -552,15 +570,7 @@ static void input_disconnect_device(struct input_dev *dev)
* generate events even after we done here but they will not
* reach any handlers.
*/
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
}
}
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
}
input_dev_release_keys(dev);
list_for_each_entry(handle, &dev->h_list, d_node)
handle->open = 0;
@ -1433,6 +1443,15 @@ static int input_dev_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, true);
/*
* Keys that have been pressed at suspend time are unlikely
* to be still pressed when we resume.
*/
spin_lock_irq(&input_dev->event_lock);
input_dev_release_keys(input_dev);
spin_unlock_irq(&input_dev->event_lock);
mutex_unlock(&input_dev->mutex);
return 0;