aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/input.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 6c161e220868..7080a9d4b840 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -86,12 +86,14 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
86} 86}
87 87
88/* 88/*
89 * Pass event through all open handles. This function is called with 89 * Pass event first through all filters and then, if event has not been
90 * filtered out, through all open handles. This function is called with
90 * dev->event_lock held and interrupts disabled. 91 * dev->event_lock held and interrupts disabled.
91 */ 92 */
92static void input_pass_event(struct input_dev *dev, 93static void input_pass_event(struct input_dev *dev,
93 unsigned int type, unsigned int code, int value) 94 unsigned int type, unsigned int code, int value)
94{ 95{
96 struct input_handler *handler;
95 struct input_handle *handle; 97 struct input_handle *handle;
96 98
97 rcu_read_lock(); 99 rcu_read_lock();
@@ -99,11 +101,25 @@ static void input_pass_event(struct input_dev *dev,
99 handle = rcu_dereference(dev->grab); 101 handle = rcu_dereference(dev->grab);
100 if (handle) 102 if (handle)
101 handle->handler->event(handle, type, code, value); 103 handle->handler->event(handle, type, code, value);
102 else 104 else {
103 list_for_each_entry_rcu(handle, &dev->h_list, d_node) 105 bool filtered = false;
104 if (handle->open) 106
105 handle->handler->event(handle, 107 list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
106 type, code, value); 108 if (!handle->open)
109 continue;
110
111 handler = handle->handler;
112 if (!handler->filter) {
113 if (filtered)
114 break;
115
116 handler->event(handle, type, code, value);
117
118 } else if (handler->filter(handle, type, code, value))
119 filtered = true;
120 }
121 }
122
107 rcu_read_unlock(); 123 rcu_read_unlock();
108} 124}
109 125
@@ -990,6 +1006,8 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v)
990 union input_seq_state *state = (union input_seq_state *)&seq->private; 1006 union input_seq_state *state = (union input_seq_state *)&seq->private;
991 1007
992 seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); 1008 seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
1009 if (handler->filter)
1010 seq_puts(seq, " (filter)");
993 if (handler->fops) 1011 if (handler->fops)
994 seq_printf(seq, " Minor=%d", handler->minor); 1012 seq_printf(seq, " Minor=%d", handler->minor);
995 seq_putc(seq, '\n'); 1013 seq_putc(seq, '\n');
@@ -1803,7 +1821,16 @@ int input_register_handle(struct input_handle *handle)
1803 error = mutex_lock_interruptible(&dev->mutex); 1821 error = mutex_lock_interruptible(&dev->mutex);
1804 if (error) 1822 if (error)
1805 return error; 1823 return error;
1806 list_add_tail_rcu(&handle->d_node, &dev->h_list); 1824
1825 /*
1826 * Filters go to the head of the list, normal handlers
1827 * to the tail.
1828 */
1829 if (handler->filter)
1830 list_add_rcu(&handle->d_node, &dev->h_list);
1831 else
1832 list_add_tail_rcu(&handle->d_node, &dev->h_list);
1833
1807 mutex_unlock(&dev->mutex); 1834 mutex_unlock(&dev->mutex);
1808 1835
1809 /* 1836 /*