|
@@ -54,16 +54,9 @@ struct evdev_client {
|
|
|
static struct evdev *evdev_table[EVDEV_MINORS];
|
|
|
static DEFINE_MUTEX(evdev_table_mutex);
|
|
|
|
|
|
-static void evdev_pass_event(struct evdev_client *client,
|
|
|
- struct input_event *event,
|
|
|
- ktime_t mono, ktime_t real)
|
|
|
+static void __pass_event(struct evdev_client *client,
|
|
|
+ const struct input_event *event)
|
|
|
{
|
|
|
- event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
|
|
|
- mono : real);
|
|
|
-
|
|
|
- /* Interrupts are disabled, just acquire the lock. */
|
|
|
- spin_lock(&client->buffer_lock);
|
|
|
-
|
|
|
client->buffer[client->head++] = *event;
|
|
|
client->head &= client->bufsize - 1;
|
|
|
|
|
@@ -86,42 +79,74 @@ static void evdev_pass_event(struct evdev_client *client,
|
|
|
client->packet_head = client->head;
|
|
|
kill_fasync(&client->fasync, SIGIO, POLL_IN);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+static void evdev_pass_values(struct evdev_client *client,
|
|
|
+ const struct input_value *vals, unsigned int count,
|
|
|
+ ktime_t mono, ktime_t real)
|
|
|
+{
|
|
|
+ struct evdev *evdev = client->evdev;
|
|
|
+ const struct input_value *v;
|
|
|
+ struct input_event event;
|
|
|
+ bool wakeup = false;
|
|
|
+
|
|
|
+ event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
|
|
|
+ mono : real);
|
|
|
+
|
|
|
+ /* Interrupts are disabled, just acquire the lock. */
|
|
|
+ spin_lock(&client->buffer_lock);
|
|
|
+
|
|
|
+ for (v = vals; v != vals + count; v++) {
|
|
|
+ event.type = v->type;
|
|
|
+ event.code = v->code;
|
|
|
+ event.value = v->value;
|
|
|
+ __pass_event(client, &event);
|
|
|
+ if (v->type == EV_SYN && v->code == SYN_REPORT)
|
|
|
+ wakeup = true;
|
|
|
+ }
|
|
|
|
|
|
spin_unlock(&client->buffer_lock);
|
|
|
+
|
|
|
+ if (wakeup)
|
|
|
+ wake_up_interruptible(&evdev->wait);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Pass incoming event to all connected clients.
|
|
|
+ * Pass incoming events to all connected clients.
|
|
|
*/
|
|
|
-static void evdev_event(struct input_handle *handle,
|
|
|
- unsigned int type, unsigned int code, int value)
|
|
|
+static void evdev_events(struct input_handle *handle,
|
|
|
+ const struct input_value *vals, unsigned int count)
|
|
|
{
|
|
|
struct evdev *evdev = handle->private;
|
|
|
struct evdev_client *client;
|
|
|
- struct input_event event;
|
|
|
ktime_t time_mono, time_real;
|
|
|
|
|
|
time_mono = ktime_get();
|
|
|
time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
|
|
|
|
|
|
- event.type = type;
|
|
|
- event.code = code;
|
|
|
- event.value = value;
|
|
|
-
|
|
|
rcu_read_lock();
|
|
|
|
|
|
client = rcu_dereference(evdev->grab);
|
|
|
|
|
|
if (client)
|
|
|
- evdev_pass_event(client, &event, time_mono, time_real);
|
|
|
+ evdev_pass_values(client, vals, count, time_mono, time_real);
|
|
|
else
|
|
|
list_for_each_entry_rcu(client, &evdev->client_list, node)
|
|
|
- evdev_pass_event(client, &event, time_mono, time_real);
|
|
|
+ evdev_pass_values(client, vals, count,
|
|
|
+ time_mono, time_real);
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
+}
|
|
|
|
|
|
- if (type == EV_SYN && code == SYN_REPORT)
|
|
|
- wake_up_interruptible(&evdev->wait);
|
|
|
+/*
|
|
|
+ * Pass incoming event to all connected clients.
|
|
|
+ */
|
|
|
+static void evdev_event(struct input_handle *handle,
|
|
|
+ unsigned int type, unsigned int code, int value)
|
|
|
+{
|
|
|
+ struct input_value vals[] = { { type, code, value } };
|
|
|
+
|
|
|
+ evdev_events(handle, vals, 1);
|
|
|
}
|
|
|
|
|
|
static int evdev_fasync(int fd, struct file *file, int on)
|
|
@@ -1050,6 +1075,7 @@ MODULE_DEVICE_TABLE(input, evdev_ids);
|
|
|
|
|
|
static struct input_handler evdev_handler = {
|
|
|
.event = evdev_event,
|
|
|
+ .events = evdev_events,
|
|
|
.connect = evdev_connect,
|
|
|
.disconnect = evdev_disconnect,
|
|
|
.fops = &evdev_fops,
|