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 | |
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>
-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: |