|
@@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex);
|
|
|
|
|
|
static struct input_handler *input_table[8];
|
|
static struct input_handler *input_table[8];
|
|
|
|
|
|
|
|
+static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
|
|
|
|
+
|
|
static inline int is_event_supported(unsigned int code,
|
|
static inline int is_event_supported(unsigned int code,
|
|
unsigned long *bm, unsigned int max)
|
|
unsigned long *bm, unsigned int max)
|
|
{
|
|
{
|
|
@@ -90,46 +92,81 @@ static void input_stop_autorepeat(struct input_dev *dev)
|
|
* filtered out, through all open handles. This function is called with
|
|
* filtered out, through all open handles. This function is called with
|
|
* dev->event_lock held and interrupts disabled.
|
|
* dev->event_lock held and interrupts disabled.
|
|
*/
|
|
*/
|
|
-static void input_pass_event(struct input_dev *dev,
|
|
|
|
- unsigned int type, unsigned int code, int value)
|
|
|
|
|
|
+static unsigned int input_to_handler(struct input_handle *handle,
|
|
|
|
+ struct input_value *vals, unsigned int count)
|
|
{
|
|
{
|
|
- struct input_handler *handler;
|
|
|
|
- struct input_handle *handle;
|
|
|
|
|
|
+ struct input_handler *handler = handle->handler;
|
|
|
|
+ struct input_value *end = vals;
|
|
|
|
+ struct input_value *v;
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
|
|
|
+ for (v = vals; v != vals + count; v++) {
|
|
|
|
+ if (handler->filter &&
|
|
|
|
+ handler->filter(handle, v->type, v->code, v->value))
|
|
|
|
+ continue;
|
|
|
|
+ if (end != v)
|
|
|
|
+ *end = *v;
|
|
|
|
+ end++;
|
|
|
|
+ }
|
|
|
|
|
|
- handle = rcu_dereference(dev->grab);
|
|
|
|
- if (handle)
|
|
|
|
- handle->handler->event(handle, type, code, value);
|
|
|
|
- else {
|
|
|
|
- bool filtered = false;
|
|
|
|
|
|
+ count = end - vals;
|
|
|
|
+ if (!count)
|
|
|
|
+ return 0;
|
|
|
|
|
|
- list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
|
|
|
|
- if (!handle->open)
|
|
|
|
- continue;
|
|
|
|
|
|
+ if (handler->events)
|
|
|
|
+ handler->events(handle, vals, count);
|
|
|
|
+ else if (handler->event)
|
|
|
|
+ for (v = vals; v != end; v++)
|
|
|
|
+ handler->event(handle, v->type, v->code, v->value);
|
|
|
|
+
|
|
|
|
+ return count;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Pass values 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_values(struct input_dev *dev,
|
|
|
|
+ struct input_value *vals, unsigned int count)
|
|
|
|
+{
|
|
|
|
+ struct input_handle *handle;
|
|
|
|
+ struct input_value *v;
|
|
|
|
|
|
- handler = handle->handler;
|
|
|
|
- if (!handler->filter) {
|
|
|
|
- if (filtered)
|
|
|
|
- break;
|
|
|
|
|
|
+ if (!count)
|
|
|
|
+ return;
|
|
|
|
|
|
- handler->event(handle, type, code, value);
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
|
- } else if (handler->filter(handle, type, code, value))
|
|
|
|
- filtered = true;
|
|
|
|
- }
|
|
|
|
|
|
+ handle = rcu_dereference(dev->grab);
|
|
|
|
+ if (handle) {
|
|
|
|
+ count = input_to_handler(handle, vals, count);
|
|
|
|
+ } else {
|
|
|
|
+ list_for_each_entry_rcu(handle, &dev->h_list, d_node)
|
|
|
|
+ if (handle->open)
|
|
|
|
+ count = input_to_handler(handle, vals, count);
|
|
}
|
|
}
|
|
|
|
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
+ add_input_randomness(vals->type, vals->code, vals->value);
|
|
|
|
+
|
|
/* trigger auto repeat for key events */
|
|
/* trigger auto repeat for key events */
|
|
- if (type == EV_KEY && value != 2) {
|
|
|
|
- if (value)
|
|
|
|
- input_start_autorepeat(dev, code);
|
|
|
|
- else
|
|
|
|
- input_stop_autorepeat(dev);
|
|
|
|
|
|
+ for (v = vals; v != vals + count; v++) {
|
|
|
|
+ if (v->type == EV_KEY && v->value != 2) {
|
|
|
|
+ if (v->value)
|
|
|
|
+ input_start_autorepeat(dev, v->code);
|
|
|
|
+ else
|
|
|
|
+ input_stop_autorepeat(dev);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
|
|
|
|
+static void input_pass_event(struct input_dev *dev,
|
|
|
|
+ unsigned int type, unsigned int code, int value)
|
|
|
|
+{
|
|
|
|
+ struct input_value vals[] = { { type, code, value } };
|
|
|
|
+
|
|
|
|
+ input_pass_values(dev, vals, ARRAY_SIZE(vals));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -146,18 +183,12 @@ static void input_repeat_key(unsigned long data)
|
|
|
|
|
|
if (test_bit(dev->repeat_key, dev->key) &&
|
|
if (test_bit(dev->repeat_key, dev->key) &&
|
|
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
|
|
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
|
|
|
|
+ struct input_value vals[] = {
|
|
|
|
+ { EV_KEY, dev->repeat_key, 2 },
|
|
|
|
+ input_value_sync
|
|
|
|
+ };
|
|
|
|
|
|
- input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
|
|
|
|
-
|
|
|
|
- if (dev->sync) {
|
|
|
|
- /*
|
|
|
|
- * Only send SYN_REPORT if we are not in a middle
|
|
|
|
- * of driver parsing a new hardware packet.
|
|
|
|
- * Otherwise assume that the driver will send
|
|
|
|
- * SYN_REPORT once it's done.
|
|
|
|
- */
|
|
|
|
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
|
|
|
- }
|
|
|
|
|
|
+ input_pass_values(dev, vals, ARRAY_SIZE(vals));
|
|
|
|
|
|
if (dev->rep[REP_PERIOD])
|
|
if (dev->rep[REP_PERIOD])
|
|
mod_timer(&dev->timer, jiffies +
|
|
mod_timer(&dev->timer, jiffies +
|
|
@@ -170,6 +201,8 @@ static void input_repeat_key(unsigned long data)
|
|
#define INPUT_IGNORE_EVENT 0
|
|
#define INPUT_IGNORE_EVENT 0
|
|
#define INPUT_PASS_TO_HANDLERS 1
|
|
#define INPUT_PASS_TO_HANDLERS 1
|
|
#define INPUT_PASS_TO_DEVICE 2
|
|
#define INPUT_PASS_TO_DEVICE 2
|
|
|
|
+#define INPUT_SLOT 4
|
|
|
|
+#define INPUT_FLUSH 8
|
|
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
|
|
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
|
|
|
|
|
|
static int input_handle_abs_event(struct input_dev *dev,
|
|
static int input_handle_abs_event(struct input_dev *dev,
|
|
@@ -216,14 +249,14 @@ static int input_handle_abs_event(struct input_dev *dev,
|
|
/* Flush pending "slot" event */
|
|
/* Flush pending "slot" event */
|
|
if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
|
|
if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
|
|
input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
|
|
input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
|
|
- input_pass_event(dev, EV_ABS, ABS_MT_SLOT, mt->slot);
|
|
|
|
|
|
+ return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
|
|
}
|
|
}
|
|
|
|
|
|
return INPUT_PASS_TO_HANDLERS;
|
|
return INPUT_PASS_TO_HANDLERS;
|
|
}
|
|
}
|
|
|
|
|
|
-static void input_handle_event(struct input_dev *dev,
|
|
|
|
- unsigned int type, unsigned int code, int value)
|
|
|
|
|
|
+static int input_get_disposition(struct input_dev *dev,
|
|
|
|
+ unsigned int type, unsigned int code, int value)
|
|
{
|
|
{
|
|
int disposition = INPUT_IGNORE_EVENT;
|
|
int disposition = INPUT_IGNORE_EVENT;
|
|
|
|
|
|
@@ -236,13 +269,9 @@ static void input_handle_event(struct input_dev *dev,
|
|
break;
|
|
break;
|
|
|
|
|
|
case SYN_REPORT:
|
|
case SYN_REPORT:
|
|
- if (!dev->sync) {
|
|
|
|
- dev->sync = true;
|
|
|
|
- disposition = INPUT_PASS_TO_HANDLERS;
|
|
|
|
- }
|
|
|
|
|
|
+ disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH;
|
|
break;
|
|
break;
|
|
case SYN_MT_REPORT:
|
|
case SYN_MT_REPORT:
|
|
- dev->sync = false;
|
|
|
|
disposition = INPUT_PASS_TO_HANDLERS;
|
|
disposition = INPUT_PASS_TO_HANDLERS;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -327,14 +356,48 @@ static void input_handle_event(struct input_dev *dev,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
|
|
|
|
- dev->sync = false;
|
|
|
|
|
|
+ return disposition;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void input_handle_event(struct input_dev *dev,
|
|
|
|
+ unsigned int type, unsigned int code, int value)
|
|
|
|
+{
|
|
|
|
+ int disposition;
|
|
|
|
+
|
|
|
|
+ disposition = input_get_disposition(dev, type, code, value);
|
|
|
|
|
|
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
|
|
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
|
|
dev->event(dev, type, code, value);
|
|
dev->event(dev, type, code, value);
|
|
|
|
|
|
- if (disposition & INPUT_PASS_TO_HANDLERS)
|
|
|
|
- input_pass_event(dev, type, code, value);
|
|
|
|
|
|
+ if (!dev->vals)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (disposition & INPUT_PASS_TO_HANDLERS) {
|
|
|
|
+ struct input_value *v;
|
|
|
|
+
|
|
|
|
+ if (disposition & INPUT_SLOT) {
|
|
|
|
+ v = &dev->vals[dev->num_vals++];
|
|
|
|
+ v->type = EV_ABS;
|
|
|
|
+ v->code = ABS_MT_SLOT;
|
|
|
|
+ v->value = dev->mt->slot;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ v = &dev->vals[dev->num_vals++];
|
|
|
|
+ v->type = type;
|
|
|
|
+ v->code = code;
|
|
|
|
+ v->value = value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (disposition & INPUT_FLUSH) {
|
|
|
|
+ if (dev->num_vals >= 2)
|
|
|
|
+ input_pass_values(dev, dev->vals, dev->num_vals);
|
|
|
|
+ dev->num_vals = 0;
|
|
|
|
+ } else if (dev->num_vals >= dev->max_vals - 2) {
|
|
|
|
+ dev->vals[dev->num_vals++] = input_value_sync;
|
|
|
|
+ input_pass_values(dev, dev->vals, dev->num_vals);
|
|
|
|
+ dev->num_vals = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -362,7 +425,6 @@ void input_event(struct input_dev *dev,
|
|
if (is_event_supported(type, dev->evbit, EV_MAX)) {
|
|
if (is_event_supported(type, dev->evbit, EV_MAX)) {
|
|
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
- add_input_randomness(type, code, value);
|
|
|
|
input_handle_event(dev, type, code, value);
|
|
input_handle_event(dev, type, code, value);
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
}
|
|
}
|
|
@@ -841,10 +903,12 @@ int input_set_keycode(struct input_dev *dev,
|
|
if (test_bit(EV_KEY, dev->evbit) &&
|
|
if (test_bit(EV_KEY, dev->evbit) &&
|
|
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
|
|
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
|
|
__test_and_clear_bit(old_keycode, dev->key)) {
|
|
__test_and_clear_bit(old_keycode, dev->key)) {
|
|
|
|
+ struct input_value vals[] = {
|
|
|
|
+ { EV_KEY, old_keycode, 0 },
|
|
|
|
+ input_value_sync
|
|
|
|
+ };
|
|
|
|
|
|
- input_pass_event(dev, EV_KEY, old_keycode, 0);
|
|
|
|
- if (dev->sync)
|
|
|
|
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
|
|
|
|
|
+ input_pass_values(dev, vals, ARRAY_SIZE(vals));
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
out:
|
|
@@ -1426,6 +1490,7 @@ static void input_dev_release(struct device *device)
|
|
input_ff_destroy(dev);
|
|
input_ff_destroy(dev);
|
|
input_mt_destroy_slots(dev);
|
|
input_mt_destroy_slots(dev);
|
|
kfree(dev->absinfo);
|
|
kfree(dev->absinfo);
|
|
|
|
+ kfree(dev->vals);
|
|
kfree(dev);
|
|
kfree(dev);
|
|
|
|
|
|
module_put(THIS_MODULE);
|
|
module_put(THIS_MODULE);
|
|
@@ -1846,6 +1911,11 @@ int input_register_device(struct input_dev *dev)
|
|
if (dev->hint_events_per_packet < packet_size)
|
|
if (dev->hint_events_per_packet < packet_size)
|
|
dev->hint_events_per_packet = packet_size;
|
|
dev->hint_events_per_packet = packet_size;
|
|
|
|
|
|
|
|
+ dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
|
|
|
|
+ dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
|
|
|
|
+ if (!dev->vals)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* If delay and period are pre-set by the driver, then autorepeating
|
|
* If delay and period are pre-set by the driver, then autorepeating
|
|
* is handled by the driver itself and we don't do it in input.c.
|
|
* is handled by the driver itself and we don't do it in input.c.
|