Input: Make sure we follow all EV_KEY events
authorHenrik Rydberg <rydberg@euromail.se>
Fri, 10 Aug 2012 19:39:38 +0000 (21:39 +0200)
committerHenrik Rydberg <rydberg@euromail.se>
Wed, 19 Sep 2012 17:50:17 +0000 (19:50 +0200)
For some EV_KEY types, sending a larger-than-one value causes the
input state to oscillate. This patch makes sure this cannot happen,
clearing up the autorepeat bypass logic in the process.

Tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Tested-by: Ping Cheng <pingc@wacom.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
drivers/input/input.c

index fb3a2c112deb8cd52010d5c301567061de3d852e..f075fbbfb1e735c5dcebecbd8644108e20eaa8e1 100644 (file)
@@ -240,24 +240,30 @@ static void input_handle_event(struct input_dev *dev,
                break;
 
        case EV_KEY:
-               if (is_event_supported(code, dev->keybit, KEY_MAX) &&
-                   !!test_bit(code, dev->key) != value) {
+               if (is_event_supported(code, dev->keybit, KEY_MAX)) {
+
+                       /* auto-repeat bypasses state updates */
+                       if (value == 2) {
+                               disposition = INPUT_PASS_TO_HANDLERS;
+                               break;
+                       }
+
+                       if (!!test_bit(code, dev->key) != !!value) {
 
-                       if (value != 2) {
                                __change_bit(code, dev->key);
+                               disposition = INPUT_PASS_TO_HANDLERS;
+
                                if (value)
                                        input_start_autorepeat(dev, code);
                                else
                                        input_stop_autorepeat(dev);
                        }
-
-                       disposition = INPUT_PASS_TO_HANDLERS;
                }
                break;
 
        case EV_SW:
                if (is_event_supported(code, dev->swbit, SW_MAX) &&
-                   !!test_bit(code, dev->sw) != value) {
+                   !!test_bit(code, dev->sw) != !!value) {
 
                        __change_bit(code, dev->sw);
                        disposition = INPUT_PASS_TO_HANDLERS;
@@ -284,7 +290,7 @@ static void input_handle_event(struct input_dev *dev,
 
        case EV_LED:
                if (is_event_supported(code, dev->ledbit, LED_MAX) &&
-                   !!test_bit(code, dev->led) != value) {
+                   !!test_bit(code, dev->led) != !!value) {
 
                        __change_bit(code, dev->led);
                        disposition = INPUT_PASS_TO_ALL;