mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
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>
This commit is contained in:
parent
17d01f28e1
commit
5fdbe44d03
@ -74,6 +74,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
|
||||
* dev->event_lock held and interrupts disabled.
|
||||
*/
|
||||
static void input_pass_event(struct input_dev *dev,
|
||||
struct input_handler *src_handler,
|
||||
unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
struct input_handler *handler;
|
||||
@ -92,6 +93,15 @@ static void input_pass_event(struct input_dev *dev,
|
||||
continue;
|
||||
|
||||
handler = handle->handler;
|
||||
|
||||
/*
|
||||
* If this is the handler that injected this
|
||||
* particular event we want to skip it to avoid
|
||||
* filters firing again and again.
|
||||
*/
|
||||
if (handler == src_handler)
|
||||
continue;
|
||||
|
||||
if (!handler->filter) {
|
||||
if (filtered)
|
||||
break;
|
||||
@ -121,7 +131,7 @@ static void input_repeat_key(unsigned long data)
|
||||
if (test_bit(dev->repeat_key, dev->key) &&
|
||||
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
|
||||
|
||||
input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
|
||||
input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);
|
||||
|
||||
if (dev->sync) {
|
||||
/*
|
||||
@ -130,7 +140,7 @@ static void input_repeat_key(unsigned long data)
|
||||
* Otherwise assume that the driver will send
|
||||
* SYN_REPORT once it's done.
|
||||
*/
|
||||
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
||||
}
|
||||
|
||||
if (dev->rep[REP_PERIOD])
|
||||
@ -163,6 +173,7 @@ static void input_stop_autorepeat(struct input_dev *dev)
|
||||
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
|
||||
|
||||
static int input_handle_abs_event(struct input_dev *dev,
|
||||
struct input_handler *src_handler,
|
||||
unsigned int code, int *pval)
|
||||
{
|
||||
bool is_mt_event;
|
||||
@ -206,13 +217,15 @@ static int input_handle_abs_event(struct input_dev *dev,
|
||||
/* Flush pending "slot" event */
|
||||
if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
|
||||
input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
|
||||
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
|
||||
input_pass_event(dev, src_handler,
|
||||
EV_ABS, ABS_MT_SLOT, dev->slot);
|
||||
}
|
||||
|
||||
return INPUT_PASS_TO_HANDLERS;
|
||||
}
|
||||
|
||||
static void input_handle_event(struct input_dev *dev,
|
||||
struct input_handler *src_handler,
|
||||
unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
int disposition = INPUT_IGNORE_EVENT;
|
||||
@ -265,7 +278,8 @@ static void input_handle_event(struct input_dev *dev,
|
||||
|
||||
case EV_ABS:
|
||||
if (is_event_supported(code, dev->absbit, ABS_MAX))
|
||||
disposition = input_handle_abs_event(dev, code, &value);
|
||||
disposition = input_handle_abs_event(dev, src_handler,
|
||||
code, &value);
|
||||
|
||||
break;
|
||||
|
||||
@ -323,7 +337,7 @@ static void input_handle_event(struct input_dev *dev,
|
||||
dev->event(dev, type, code, value);
|
||||
|
||||
if (disposition & INPUT_PASS_TO_HANDLERS)
|
||||
input_pass_event(dev, type, code, value);
|
||||
input_pass_event(dev, src_handler, type, code, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,7 +366,7 @@ void input_event(struct input_dev *dev,
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
add_input_randomness(type, code, value);
|
||||
input_handle_event(dev, type, code, value);
|
||||
input_handle_event(dev, NULL, type, code, value);
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
}
|
||||
}
|
||||
@ -382,7 +396,8 @@ void input_inject_event(struct input_handle *handle,
|
||||
rcu_read_lock();
|
||||
grab = rcu_dereference(dev->grab);
|
||||
if (!grab || grab == handle)
|
||||
input_handle_event(dev, type, code, value);
|
||||
input_handle_event(dev, handle->handler,
|
||||
type, code, value);
|
||||
rcu_read_unlock();
|
||||
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
@ -595,10 +610,10 @@ static void input_dev_release_keys(struct input_dev *dev)
|
||||
for (code = 0; code <= KEY_MAX; code++) {
|
||||
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
|
||||
__test_and_clear_bit(code, dev->key)) {
|
||||
input_pass_event(dev, EV_KEY, code, 0);
|
||||
input_pass_event(dev, NULL, EV_KEY, code, 0);
|
||||
}
|
||||
}
|
||||
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,9 +888,9 @@ int input_set_keycode(struct input_dev *dev,
|
||||
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
|
||||
__test_and_clear_bit(old_keycode, dev->key)) {
|
||||
|
||||
input_pass_event(dev, EV_KEY, old_keycode, 0);
|
||||
input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
|
||||
if (dev->sync)
|
||||
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
||||
}
|
||||
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user