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 | |
| 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>
| -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 9c79bd56b51..240ad39da57 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; |
