Input: implement input filters

Sometimes it is desirable to suppress certain events from reaching
input handlers and thus user space. One such example is Mac mouse
button emulation code which catches certain key presses and converts
them into button clicks as if they were emitted by a virtual mouse.
The original key press events should be completely suppressed,
otherwise user space will be confused, and while keyboard driver
does it on its own evdev is blissfully unaware of this arrangement.

This patch adds notion of 'filter' to the standard input handlers,
which may flag event as filtered thus preventing it from reaching
other input handlers. Filters don't (nor will they ever) have a
notion of priority relative to each other, input core will run all
of them first and any one of them may mark event as filtered.

This patch is inspired by similar patch by Matthew Garret but the
implementation and intended usage are quite different.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 6c161e2..7080a9d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -86,12 +86,14 @@
 }
 
 /*
- * Pass event through all open handles. This function is called with
+ * Pass event first through all filters and then, if event has not been
+ * filtered out, through all open handles. This function is called with
  * dev->event_lock held and interrupts disabled.
  */
 static void input_pass_event(struct input_dev *dev,
 			     unsigned int type, unsigned int code, int value)
 {
+	struct input_handler *handler;
 	struct input_handle *handle;
 
 	rcu_read_lock();
@@ -99,11 +101,25 @@
 	handle = rcu_dereference(dev->grab);
 	if (handle)
 		handle->handler->event(handle, type, code, value);
-	else
-		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
-			if (handle->open)
-				handle->handler->event(handle,
-							type, code, value);
+	else {
+		bool filtered = false;
+
+		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
+			if (!handle->open)
+				continue;
+
+			handler = handle->handler;
+			if (!handler->filter) {
+				if (filtered)
+					break;
+
+				handler->event(handle, type, code, value);
+
+			} else if (handler->filter(handle, type, code, value))
+				filtered = true;
+		}
+	}
+
 	rcu_read_unlock();
 }
 
@@ -990,6 +1006,8 @@
 	union input_seq_state *state = (union input_seq_state *)&seq->private;
 
 	seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
+	if (handler->filter)
+		seq_puts(seq, " (filter)");
 	if (handler->fops)
 		seq_printf(seq, " Minor=%d", handler->minor);
 	seq_putc(seq, '\n');
@@ -1803,7 +1821,16 @@
 	error = mutex_lock_interruptible(&dev->mutex);
 	if (error)
 		return error;
-	list_add_tail_rcu(&handle->d_node, &dev->h_list);
+
+	/*
+	 * Filters go to the head of the list, normal handlers
+	 * to the tail.
+	 */
+	if (handler->filter)
+		list_add_rcu(&handle->d_node, &dev->h_list);
+	else
+		list_add_tail_rcu(&handle->d_node, &dev->h_list);
+
 	mutex_unlock(&dev->mutex);
 
 	/*