diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-11-09 00:51:25 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-11-11 04:01:26 -0500 |
| commit | 5fdbe44d033d059cc56c2803e6b4dbd8cb4e5e39 (patch) | |
| tree | 18dcde03df9d44a7e91a20472449f1f95b57da25 /drivers | |
| parent | 17d01f28e160f8a9c9ecda2e335d0047ec9e7388 (diff) | |
Input: do not pass injected events back to the originating handler
Sometimes input handlers (as opposed to input devices) have a need to
inject (or re-inject) events back into input core. For example sysrq
filter may want to inject previously suppressed Alt-SysRq so that user
can take a screen print. In this case we do not want to pass such events
back to the same same handler that injected them to avoid loops.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/input/input.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 75bed635b98d..7f26ca6ecf75 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -74,6 +74,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) | |||
| 74 | * dev->event_lock held and interrupts disabled. | 74 | * dev->event_lock held and interrupts disabled. |
| 75 | */ | 75 | */ |
| 76 | static void input_pass_event(struct input_dev *dev, | 76 | static void input_pass_event(struct input_dev *dev, |
| 77 | struct input_handler *src_handler, | ||
| 77 | unsigned int type, unsigned int code, int value) | 78 | unsigned int type, unsigned int code, int value) |
| 78 | { | 79 | { |
| 79 | struct input_handler *handler; | 80 | struct input_handler *handler; |
| @@ -92,6 +93,15 @@ static void input_pass_event(struct input_dev *dev, | |||
| 92 | continue; | 93 | continue; |
| 93 | 94 | ||
| 94 | handler = handle->handler; | 95 | handler = handle->handler; |
| 96 | |||
| 97 | /* | ||
| 98 | * If this is the handler that injected this | ||
| 99 | * particular event we want to skip it to avoid | ||
| 100 | * filters firing again and again. | ||
| 101 | */ | ||
| 102 | if (handler == src_handler) | ||
| 103 | continue; | ||
| 104 | |||
| 95 | if (!handler->filter) { | 105 | if (!handler->filter) { |
| 96 | if (filtered) | 106 | if (filtered) |
| 97 | break; | 107 | break; |
| @@ -121,7 +131,7 @@ static void input_repeat_key(unsigned long data) | |||
| 121 | if (test_bit(dev->repeat_key, dev->key) && | 131 | if (test_bit(dev->repeat_key, dev->key) && |
| 122 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { | 132 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { |
| 123 | 133 | ||
| 124 | input_pass_event(dev, EV_KEY, dev->repeat_key, 2); | 134 | input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2); |
| 125 | 135 | ||
| 126 | if (dev->sync) { | 136 | if (dev->sync) { |
| 127 | /* | 137 | /* |
| @@ -130,7 +140,7 @@ static void input_repeat_key(unsigned long data) | |||
| 130 | * Otherwise assume that the driver will send | 140 | * Otherwise assume that the driver will send |
| 131 | * SYN_REPORT once it's done. | 141 | * SYN_REPORT once it's done. |
| 132 | */ | 142 | */ |
| 133 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | 143 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); |
| 134 | } | 144 | } |
| 135 | 145 | ||
| 136 | if (dev->rep[REP_PERIOD]) | 146 | if (dev->rep[REP_PERIOD]) |
| @@ -163,6 +173,7 @@ static void input_stop_autorepeat(struct input_dev *dev) | |||
| 163 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) | 173 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) |
| 164 | 174 | ||
| 165 | static int input_handle_abs_event(struct input_dev *dev, | 175 | static int input_handle_abs_event(struct input_dev *dev, |
| 176 | struct input_handler *src_handler, | ||
| 166 | unsigned int code, int *pval) | 177 | unsigned int code, int *pval) |
| 167 | { | 178 | { |
| 168 | bool is_mt_event; | 179 | bool is_mt_event; |
| @@ -206,13 +217,15 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
| 206 | /* Flush pending "slot" event */ | 217 | /* Flush pending "slot" event */ |
| 207 | if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { | 218 | if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { |
| 208 | input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); | 219 | input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); |
| 209 | input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); | 220 | input_pass_event(dev, src_handler, |
| 221 | EV_ABS, ABS_MT_SLOT, dev->slot); | ||
| 210 | } | 222 | } |
| 211 | 223 | ||
| 212 | return INPUT_PASS_TO_HANDLERS; | 224 | return INPUT_PASS_TO_HANDLERS; |
| 213 | } | 225 | } |
| 214 | 226 | ||
| 215 | static void input_handle_event(struct input_dev *dev, | 227 | static void input_handle_event(struct input_dev *dev, |
| 228 | struct input_handler *src_handler, | ||
| 216 | unsigned int type, unsigned int code, int value) | 229 | unsigned int type, unsigned int code, int value) |
| 217 | { | 230 | { |
| 218 | int disposition = INPUT_IGNORE_EVENT; | 231 | int disposition = INPUT_IGNORE_EVENT; |
| @@ -265,7 +278,8 @@ static void input_handle_event(struct input_dev *dev, | |||
| 265 | 278 | ||
| 266 | case EV_ABS: | 279 | case EV_ABS: |
| 267 | if (is_event_supported(code, dev->absbit, ABS_MAX)) | 280 | if (is_event_supported(code, dev->absbit, ABS_MAX)) |
| 268 | disposition = input_handle_abs_event(dev, code, &value); | 281 | disposition = input_handle_abs_event(dev, src_handler, |
| 282 | code, &value); | ||
| 269 | 283 | ||
| 270 | break; | 284 | break; |
| 271 | 285 | ||
| @@ -323,7 +337,7 @@ static void input_handle_event(struct input_dev *dev, | |||
| 323 | dev->event(dev, type, code, value); | 337 | dev->event(dev, type, code, value); |
| 324 | 338 | ||
| 325 | if (disposition & INPUT_PASS_TO_HANDLERS) | 339 | if (disposition & INPUT_PASS_TO_HANDLERS) |
| 326 | input_pass_event(dev, type, code, value); | 340 | input_pass_event(dev, src_handler, type, code, value); |
| 327 | } | 341 | } |
| 328 | 342 | ||
| 329 | /** | 343 | /** |
| @@ -352,7 +366,7 @@ void input_event(struct input_dev *dev, | |||
| 352 | 366 | ||
| 353 | spin_lock_irqsave(&dev->event_lock, flags); | 367 | spin_lock_irqsave(&dev->event_lock, flags); |
| 354 | add_input_randomness(type, code, value); | 368 | add_input_randomness(type, code, value); |
| 355 | input_handle_event(dev, type, code, value); | 369 | input_handle_event(dev, NULL, type, code, value); |
| 356 | spin_unlock_irqrestore(&dev->event_lock, flags); | 370 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 357 | } | 371 | } |
| 358 | } | 372 | } |
| @@ -382,7 +396,8 @@ void input_inject_event(struct input_handle *handle, | |||
| 382 | rcu_read_lock(); | 396 | rcu_read_lock(); |
| 383 | grab = rcu_dereference(dev->grab); | 397 | grab = rcu_dereference(dev->grab); |
| 384 | if (!grab || grab == handle) | 398 | if (!grab || grab == handle) |
| 385 | input_handle_event(dev, type, code, value); | 399 | input_handle_event(dev, handle->handler, |
| 400 | type, code, value); | ||
| 386 | rcu_read_unlock(); | 401 | rcu_read_unlock(); |
| 387 | 402 | ||
| 388 | spin_unlock_irqrestore(&dev->event_lock, flags); | 403 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| @@ -595,10 +610,10 @@ static void input_dev_release_keys(struct input_dev *dev) | |||
| 595 | for (code = 0; code <= KEY_MAX; code++) { | 610 | for (code = 0; code <= KEY_MAX; code++) { |
| 596 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | 611 | if (is_event_supported(code, dev->keybit, KEY_MAX) && |
| 597 | __test_and_clear_bit(code, dev->key)) { | 612 | __test_and_clear_bit(code, dev->key)) { |
| 598 | input_pass_event(dev, EV_KEY, code, 0); | 613 | input_pass_event(dev, NULL, EV_KEY, code, 0); |
| 599 | } | 614 | } |
| 600 | } | 615 | } |
| 601 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | 616 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); |
| 602 | } | 617 | } |
| 603 | } | 618 | } |
| 604 | 619 | ||
| @@ -873,9 +888,9 @@ int input_set_keycode(struct input_dev *dev, | |||
| 873 | !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && | 888 | !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && |
| 874 | __test_and_clear_bit(old_keycode, dev->key)) { | 889 | __test_and_clear_bit(old_keycode, dev->key)) { |
| 875 | 890 | ||
| 876 | input_pass_event(dev, EV_KEY, old_keycode, 0); | 891 | input_pass_event(dev, NULL, EV_KEY, old_keycode, 0); |
| 877 | if (dev->sync) | 892 | if (dev->sync) |
| 878 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | 893 | input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); |
| 879 | } | 894 | } |
| 880 | 895 | ||
| 881 | out: | 896 | out: |
