diff options
author | Oliver Neukum <oliver@neukum.org> | 2010-07-01 12:01:50 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-07-03 16:13:23 -0400 |
commit | 866d7d7b4a4e1d502b136bcc8af605091fe4c7b5 (patch) | |
tree | 770e175bfcea2de9156630c2c91611d8d4dad1b8 /drivers/input/input.c | |
parent | 3eac5c7e44f35eb07f0ecb28ce60f15b2dda1932 (diff) |
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>
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 9c79bd56b51a..240ad39da570 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -528,12 +528,30 @@ void input_close_device(struct input_handle *handle) | |||
528 | EXPORT_SYMBOL(input_close_device); | 528 | EXPORT_SYMBOL(input_close_device); |
529 | 529 | ||
530 | /* | 530 | /* |
531 | * Simulate keyup events for all keys that are marked as pressed. | ||
532 | * The function must be called with dev->event_lock held. | ||
533 | */ | ||
534 | static void input_dev_release_keys(struct input_dev *dev) | ||
535 | { | ||
536 | int code; | ||
537 | |||
538 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { | ||
539 | for (code = 0; code <= KEY_MAX; code++) { | ||
540 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
541 | __test_and_clear_bit(code, dev->key)) { | ||
542 | input_pass_event(dev, EV_KEY, code, 0); | ||
543 | } | ||
544 | } | ||
545 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | /* | ||
531 | * Prepare device for unregistering | 550 | * Prepare device for unregistering |
532 | */ | 551 | */ |
533 | static void input_disconnect_device(struct input_dev *dev) | 552 | static void input_disconnect_device(struct input_dev *dev) |
534 | { | 553 | { |
535 | struct input_handle *handle; | 554 | struct input_handle *handle; |
536 | int code; | ||
537 | 555 | ||
538 | /* | 556 | /* |
539 | * Mark device as going away. Note that we take dev->mutex here | 557 | * 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) | |||
552 | * generate events even after we done here but they will not | 570 | * generate events even after we done here but they will not |
553 | * reach any handlers. | 571 | * reach any handlers. |
554 | */ | 572 | */ |
555 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { | 573 | input_dev_release_keys(dev); |
556 | for (code = 0; code <= KEY_MAX; code++) { | ||
557 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
558 | __test_and_clear_bit(code, dev->key)) { | ||
559 | input_pass_event(dev, EV_KEY, code, 0); | ||
560 | } | ||
561 | } | ||
562 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
563 | } | ||
564 | 574 | ||
565 | list_for_each_entry(handle, &dev->h_list, d_node) | 575 | list_for_each_entry(handle, &dev->h_list, d_node) |
566 | handle->open = 0; | 576 | handle->open = 0; |
@@ -1433,6 +1443,15 @@ static int input_dev_resume(struct device *dev) | |||
1433 | 1443 | ||
1434 | mutex_lock(&input_dev->mutex); | 1444 | mutex_lock(&input_dev->mutex); |
1435 | input_dev_reset(input_dev, true); | 1445 | input_dev_reset(input_dev, true); |
1446 | |||
1447 | /* | ||
1448 | * Keys that have been pressed at suspend time are unlikely | ||
1449 | * to be still pressed when we resume. | ||
1450 | */ | ||
1451 | spin_lock_irq(&input_dev->event_lock); | ||
1452 | input_dev_release_keys(input_dev); | ||
1453 | spin_unlock_irq(&input_dev->event_lock); | ||
1454 | |||
1436 | mutex_unlock(&input_dev->mutex); | 1455 | mutex_unlock(&input_dev->mutex); |
1437 | 1456 | ||
1438 | return 0; | 1457 | return 0; |