diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 725 |
1 files changed, 409 insertions, 316 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 711485437567..ec4346f20efd 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -96,48 +96,16 @@ static void input_start_autorepeat(struct input_dev *dev, int code) static void input_stop_autorepeat(struct input_dev *dev) { - del_timer(&dev->timer); -} - -/* - * 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 unsigned int input_to_handler(struct input_handle *handle, - struct input_value *vals, unsigned int count) -{ - struct input_handler *handler = handle->handler; - struct input_value *end = vals; - struct input_value *v; - - if (handler->filter) { - for (v = vals; v != vals + count; v++) { - if (handler->filter(handle, v->type, v->code, v->value)) - continue; - if (end != v) - *end = *v; - end++; - } - count = end - vals; - } - - if (!count) - return 0; - - if (handler->events) - handler->events(handle, vals, count); - else if (handler->event) - for (v = vals; v != vals + count; v++) - handler->event(handle, v->type, v->code, v->value); - - return count; + timer_delete(&dev->timer); } /* * 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. + * filtered out, through all open handles. This order is achieved by placing + * filters at the head of the list of handles attached to the device, and + * placing regular handles at the tail of the list. + * + * 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) @@ -147,25 +115,23 @@ static void input_pass_values(struct input_dev *dev, lockdep_assert_held(&dev->event_lock); - if (!count) - return; - - rcu_read_lock(); + scoped_guard(rcu) { + handle = rcu_dereference(dev->grab); + if (handle) { + count = handle->handle_events(handle, vals, count); + break; + } - 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) + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { if (handle->open) { - count = input_to_handler(handle, vals, count); + count = handle->handle_events(handle, vals, + count); if (!count) break; } + } } - rcu_read_unlock(); - /* trigger auto repeat for key events */ if (test_bit(EV_REP, dev->evbit) && test_bit(EV_KEY, dev->evbit)) { for (v = vals; v != vals + count; v++) { @@ -354,9 +320,6 @@ static void input_event_dispose(struct input_dev *dev, int disposition, if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (!dev->vals) - return; - if (disposition & INPUT_PASS_TO_HANDLERS) { struct input_value *v; @@ -427,13 +390,9 @@ void input_handle_event(struct input_dev *dev, void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - unsigned long flags; - if (is_event_supported(type, dev->evbit, EV_MAX)) { - - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); input_handle_event(dev, type, code, value); - spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_event); @@ -454,18 +413,15 @@ void input_inject_event(struct input_handle *handle, { struct input_dev *dev = handle->dev; struct input_handle *grab; - unsigned long flags; if (is_event_supported(type, dev->evbit, EV_MAX)) { - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); + guard(rcu)(); - rcu_read_lock(); grab = rcu_dereference(dev->grab); if (!grab || grab == handle) input_handle_event(dev, type, code, value); - rcu_read_unlock(); - spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_inject_event); @@ -563,22 +519,15 @@ EXPORT_SYMBOL(input_copy_abs); int input_grab_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - int retval; - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->grab) + return -EBUSY; - if (dev->grab) { - retval = -EBUSY; - goto out; + rcu_assign_pointer(dev->grab, handle); } - rcu_assign_pointer(dev->grab, handle); - - out: - mutex_unlock(&dev->mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_grab_device); @@ -613,9 +562,8 @@ void input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); __input_release_device(handle); - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_release_device); @@ -629,64 +577,57 @@ EXPORT_SYMBOL(input_release_device); int input_open_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - int retval; - - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + int error; - if (dev->going_away) { - retval = -ENODEV; - goto out; - } + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->going_away) + return -ENODEV; - handle->open++; + handle->open++; - if (dev->users++ || dev->inhibited) { - /* - * Device is already opened and/or inhibited, - * so we can exit immediately and report success. - */ - goto out; - } + if (handle->handler->passive_observer) + return 0; - if (dev->open) { - retval = dev->open(dev); - if (retval) { - dev->users--; - handle->open--; + if (dev->users++ || dev->inhibited) { /* - * Make sure we are not delivering any more events - * through this handle + * Device is already opened and/or inhibited, + * so we can exit immediately and report success. */ - synchronize_rcu(); - goto out; + return 0; } - } - if (dev->poller) - input_dev_poller_start(dev->poller); + if (dev->open) { + error = dev->open(dev); + if (error) { + dev->users--; + handle->open--; + /* + * Make sure we are not delivering any more + * events through this handle. + */ + synchronize_rcu(); + return error; + } + } - out: - mutex_unlock(&dev->mutex); - return retval; + if (dev->poller) + input_dev_poller_start(dev->poller); + } + + return 0; } EXPORT_SYMBOL(input_open_device); int input_flush_device(struct input_handle *handle, struct file *file) { struct input_dev *dev = handle->dev; - int retval; - - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; - if (dev->flush) - retval = dev->flush(dev, file); + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->flush) + return dev->flush(dev, file); + } - mutex_unlock(&dev->mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_flush_device); @@ -701,15 +642,17 @@ void input_close_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); __input_release_device(handle); - if (!--dev->users && !dev->inhibited) { - if (dev->poller) - input_dev_poller_stop(dev->poller); - if (dev->close) - dev->close(dev); + if (!handle->handler->passive_observer) { + if (!--dev->users && !dev->inhibited) { + if (dev->poller) + input_dev_poller_stop(dev->poller); + if (dev->close) + dev->close(dev); + } } if (!--handle->open) { @@ -720,8 +663,6 @@ void input_close_device(struct input_handle *handle) */ synchronize_rcu(); } - - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_close_device); @@ -758,11 +699,10 @@ static void input_disconnect_device(struct input_dev *dev) * not to protect access to dev->going_away but rather to ensure * that there are no threads in the middle of input_open_device() */ - mutex_lock(&dev->mutex); - dev->going_away = true; - mutex_unlock(&dev->mutex); + scoped_guard(mutex, &dev->mutex) + dev->going_away = true; - spin_lock_irq(&dev->event_lock); + guard(spinlock_irq)(&dev->event_lock); /* * Simulate keyup events for all pressed keys so that handlers @@ -775,8 +715,6 @@ static void input_disconnect_device(struct input_dev *dev) list_for_each_entry(handle, &dev->h_list, d_node) handle->open = 0; - - spin_unlock_irq(&dev->event_lock); } /** @@ -933,14 +871,9 @@ static int input_default_setkeycode(struct input_dev *dev, */ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) { - unsigned long flags; - int retval; - - spin_lock_irqsave(&dev->event_lock, flags); - retval = dev->getkeycode(dev, ke); - spin_unlock_irqrestore(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); - return retval; + return dev->getkeycode(dev, ke); } EXPORT_SYMBOL(input_get_keycode); @@ -955,18 +888,17 @@ EXPORT_SYMBOL(input_get_keycode); int input_set_keycode(struct input_dev *dev, const struct input_keymap_entry *ke) { - unsigned long flags; unsigned int old_keycode; - int retval; + int error; if (ke->keycode > KEY_MAX) return -EINVAL; - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); - retval = dev->setkeycode(dev, ke, &old_keycode); - if (retval) - goto out; + error = dev->setkeycode(dev, ke, &old_keycode); + if (error) + return error; /* Make sure KEY_RESERVED did not get enabled. */ __clear_bit(KEY_RESERVED, dev->keybit); @@ -994,10 +926,7 @@ int input_set_keycode(struct input_dev *dev, EV_SYN, SYN_REPORT, 1); } - out: - spin_unlock_irqrestore(&dev->event_lock, flags); - - return retval; + return 0; } EXPORT_SYMBOL(input_set_keycode); @@ -1116,33 +1045,31 @@ static inline void input_wakeup_procfs_readers(void) wake_up(&input_devices_poll_wait); } +struct input_seq_state { + unsigned short pos; + bool mutex_acquired; + int input_devices_state; +}; + static __poll_t input_proc_devices_poll(struct file *file, poll_table *wait) { + struct seq_file *seq = file->private_data; + struct input_seq_state *state = seq->private; + poll_wait(file, &input_devices_poll_wait, wait); - if (file->f_version != input_devices_state) { - file->f_version = input_devices_state; + if (state->input_devices_state != input_devices_state) { + state->input_devices_state = input_devices_state; return EPOLLIN | EPOLLRDNORM; } return 0; } -union input_seq_state { - struct { - unsigned short pos; - bool mutex_acquired; - }; - void *p; -}; - static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; int error; - /* We need to fit into seq->private pointer */ - BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private)); - error = mutex_lock_interruptible(&input_mutex); if (error) { state->mutex_acquired = false; @@ -1161,7 +1088,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void input_seq_stop(struct seq_file *seq, void *v) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; if (state->mutex_acquired) mutex_unlock(&input_mutex); @@ -1247,7 +1174,8 @@ static const struct seq_operations input_devices_seq_ops = { static int input_proc_devices_open(struct inode *inode, struct file *file) { - return seq_open(file, &input_devices_seq_ops); + return seq_open_private(file, &input_devices_seq_ops, + sizeof(struct input_seq_state)); } static const struct proc_ops input_devices_proc_ops = { @@ -1255,17 +1183,14 @@ static const struct proc_ops input_devices_proc_ops = { .proc_poll = input_proc_devices_poll, .proc_read = seq_read, .proc_lseek = seq_lseek, - .proc_release = seq_release, + .proc_release = seq_release_private, }; static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; int error; - /* We need to fit into seq->private pointer */ - BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private)); - error = mutex_lock_interruptible(&input_mutex); if (error) { state->mutex_acquired = false; @@ -1280,7 +1205,7 @@ static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; state->pos = *pos + 1; return seq_list_next(v, &input_handler_list, pos); @@ -1289,7 +1214,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) static int input_handlers_seq_show(struct seq_file *seq, void *v) { struct input_handler *handler = container_of(v, struct input_handler, node); - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); if (handler->filter) @@ -1310,14 +1235,15 @@ static const struct seq_operations input_handlers_seq_ops = { static int input_proc_handlers_open(struct inode *inode, struct file *file) { - return seq_open(file, &input_handlers_seq_ops); + return seq_open_private(file, &input_handlers_seq_ops, + sizeof(struct input_seq_state)); } static const struct proc_ops input_handlers_proc_ops = { .proc_open = input_proc_handlers_open, .proc_read = seq_read, .proc_lseek = seq_lseek, - .proc_release = seq_release, + .proc_release = seq_release_private, }; static int __init input_proc_init(void) @@ -1378,19 +1304,19 @@ static int input_print_modalias_bits(char *buf, int size, char name, const unsigned long *bm, unsigned int min_bit, unsigned int max_bit) { - int len = 0, i; + int bit = min_bit; + int len = 0; len += snprintf(buf, max(size, 0), "%c", name); - for (i = min_bit; i < max_bit; i++) - if (bm[BIT_WORD(i)] & BIT_MASK(i)) - len += snprintf(buf + len, max(size - len, 0), "%X,", i); + for_each_set_bit_from(bit, bm, max_bit) + len += snprintf(buf + len, max(size - len, 0), "%X,", bit); return len; } -static int input_print_modalias(char *buf, int size, const struct input_dev *id, - int add_cr) +static int input_print_modalias_parts(char *buf, int size, int full_len, + const struct input_dev *id) { - int len; + int len, klen, remainder, space; len = snprintf(buf, max(size, 0), "input:b%04Xv%04Xp%04Xe%04X-", @@ -1399,8 +1325,48 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, len += input_print_modalias_bits(buf + len, size - len, 'e', id->evbit, 0, EV_MAX); - len += input_print_modalias_bits(buf + len, size - len, + + /* + * Calculate the remaining space in the buffer making sure we + * have place for the terminating 0. + */ + space = max(size - (len + 1), 0); + + klen = input_print_modalias_bits(buf + len, size - len, 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); + len += klen; + + /* + * If we have more data than we can fit in the buffer, check + * if we can trim key data to fit in the rest. We will indicate + * that key data is incomplete by adding "+" sign at the end, like + * this: * "k1,2,3,45,+,". + * + * Note that we shortest key info (if present) is "k+," so we + * can only try to trim if key data is longer than that. + */ + if (full_len && size < full_len + 1 && klen > 3) { + remainder = full_len - len; + /* + * We can only trim if we have space for the remainder + * and also for at least "k+," which is 3 more characters. + */ + if (remainder <= space - 3) { + /* + * We are guaranteed to have 'k' in the buffer, so + * we need at least 3 additional bytes for storing + * "+," in addition to the remainder. + */ + for (int i = size - 1 - remainder - 3; i >= 0; i--) { + if (buf[i] == 'k' || buf[i] == ',') { + strcpy(buf + i + 1, "+,"); + len = i + 3; /* Not counting '\0' */ + break; + } + } + } + } + len += input_print_modalias_bits(buf + len, size - len, 'r', id->relbit, 0, REL_MAX); len += input_print_modalias_bits(buf + len, size - len, @@ -1416,12 +1382,25 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, len += input_print_modalias_bits(buf + len, size - len, 'w', id->swbit, 0, SW_MAX); - if (add_cr) - len += snprintf(buf + len, max(size - len, 0), "\n"); - return len; } +static int input_print_modalias(char *buf, int size, const struct input_dev *id) +{ + int full_len; + + /* + * Printing is done in 2 passes: first one figures out total length + * needed for the modalias string, second one will try to trim key + * data in case when buffer is too small for the entire modalias. + * If the buffer is too small regardless, it will fill as much as it + * can (without trimming key data) into the buffer and leave it to + * the caller to figure out what to do with the result. + */ + full_len = input_print_modalias_parts(NULL, 0, 0, id); + return input_print_modalias_parts(buf, size, full_len, id); +} + static ssize_t input_dev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) @@ -1429,7 +1408,9 @@ static ssize_t input_dev_show_modalias(struct device *dev, struct input_dev *id = to_input_dev(dev); ssize_t len; - len = input_print_modalias(buf, PAGE_SIZE, id, 1); + len = input_print_modalias(buf, PAGE_SIZE, id); + if (len < PAGE_SIZE - 2) + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); return min_t(int, len, PAGE_SIZE); } @@ -1641,6 +1622,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, return 0; } +/* + * This is a pretty gross hack. When building uevent data the driver core + * may try adding more environment variables to kobj_uevent_env without + * telling us, so we have no idea how much of the buffer we can use to + * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially + * reduce amount of memory we will use for the modalias environment variable. + * + * The potential additions are: + * + * SEQNUM=18446744073709551615 - (%llu - 28 bytes) + * HOME=/ (6 bytes) + * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes) + * + * 68 bytes total. Allow extra buffer - 96 bytes + */ +#define UEVENT_ENV_EXTRA_LEN 96 + static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, const struct input_dev *dev) { @@ -1650,9 +1648,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, return -ENOMEM; len = input_print_modalias(&env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen, - dev, 0); - if (len >= (sizeof(env->buf) - env->buflen)) + (int)sizeof(env->buf) - env->buflen - + UEVENT_ENV_EXTRA_LEN, + dev); + if (len >= ((int)sizeof(env->buf) - env->buflen - + UEVENT_ENV_EXTRA_LEN)) return -ENOMEM; env->buflen += len; @@ -1760,26 +1760,21 @@ static void input_dev_toggle(struct input_dev *dev, bool activate) */ void input_reset_device(struct input_dev *dev) { - unsigned long flags; - - mutex_lock(&dev->mutex); - spin_lock_irqsave(&dev->event_lock, flags); + guard(mutex)(&dev->mutex); + guard(spinlock_irqsave)(&dev->event_lock); input_dev_toggle(dev, true); if (input_dev_release_keys(dev)) input_handle_event(dev, EV_SYN, SYN_REPORT, 1); - - spin_unlock_irqrestore(&dev->event_lock, flags); - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_reset_device); static int input_inhibit_device(struct input_dev *dev) { - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); if (dev->inhibited) - goto out; + return 0; if (dev->users) { if (dev->close) @@ -1788,54 +1783,50 @@ static int input_inhibit_device(struct input_dev *dev) input_dev_poller_stop(dev->poller); } - spin_lock_irq(&dev->event_lock); - input_mt_release_slots(dev); - input_dev_release_keys(dev); - input_handle_event(dev, EV_SYN, SYN_REPORT, 1); - input_dev_toggle(dev, false); - spin_unlock_irq(&dev->event_lock); + scoped_guard(spinlock_irq, &dev->event_lock) { + input_mt_release_slots(dev); + input_dev_release_keys(dev); + input_handle_event(dev, EV_SYN, SYN_REPORT, 1); + input_dev_toggle(dev, false); + } dev->inhibited = true; -out: - mutex_unlock(&dev->mutex); return 0; } static int input_uninhibit_device(struct input_dev *dev) { - int ret = 0; + int error; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); if (!dev->inhibited) - goto out; + return 0; if (dev->users) { if (dev->open) { - ret = dev->open(dev); - if (ret) - goto out; + error = dev->open(dev); + if (error) + return error; } if (dev->poller) input_dev_poller_start(dev->poller); } dev->inhibited = false; - spin_lock_irq(&dev->event_lock); - input_dev_toggle(dev, true); - spin_unlock_irq(&dev->event_lock); -out: - mutex_unlock(&dev->mutex); - return ret; + scoped_guard(spinlock_irq, &dev->event_lock) + input_dev_toggle(dev, true); + + return 0; } static int input_dev_suspend(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* * Keys that are pressed now are unlikely to be @@ -1847,8 +1838,6 @@ static int input_dev_suspend(struct device *dev) /* Turn off LEDs and sounds, if any are active. */ input_dev_toggle(input_dev, false); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1856,13 +1845,11 @@ static int input_dev_resume(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* Restore state of LEDs and sounds, if any were active. */ input_dev_toggle(input_dev, true); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1870,7 +1857,7 @@ static int input_dev_freeze(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* * Keys that are pressed now are unlikely to be @@ -1879,8 +1866,6 @@ static int input_dev_freeze(struct device *dev) if (input_dev_release_keys(input_dev)) input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1888,13 +1873,11 @@ static int input_dev_poweroff(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* Turn off LEDs and sounds, if any are active. */ input_dev_toggle(input_dev, false); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1939,22 +1922,41 @@ struct input_dev *input_allocate_device(void) struct input_dev *dev; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev) { - dev->dev.type = &input_dev_type; - dev->dev.class = &input_class; - device_initialize(&dev->dev); - mutex_init(&dev->mutex); - spin_lock_init(&dev->event_lock); - timer_setup(&dev->timer, NULL, 0); - INIT_LIST_HEAD(&dev->h_list); - INIT_LIST_HEAD(&dev->node); - - dev_set_name(&dev->dev, "input%lu", - (unsigned long)atomic_inc_return(&input_no)); + if (!dev) + return NULL; - __module_get(THIS_MODULE); + /* + * Start with space for SYN_REPORT + 7 EV_KEY/EV_MSC events + 2 spare, + * see input_estimate_events_per_packet(). We will tune the number + * when we register the device. + */ + dev->max_vals = 10; + dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); + if (!dev->vals) { + kfree(dev); + return NULL; } + mutex_init(&dev->mutex); + spin_lock_init(&dev->event_lock); + timer_setup(&dev->timer, NULL, 0); + INIT_LIST_HEAD(&dev->h_list); + INIT_LIST_HEAD(&dev->node); + + dev->dev.type = &input_dev_type; + dev->dev.class = &input_class; + device_initialize(&dev->dev); + /* + * From this point on we can no longer simply "kfree(dev)", we need + * to use input_free_device() so that device core properly frees its + * resources associated with the input device. + */ + + dev_set_name(&dev->dev, "input%lu", + (unsigned long)atomic_inc_return(&input_no)); + + __module_get(THIS_MODULE); + return dev; } EXPORT_SYMBOL(input_allocate_device); @@ -2168,7 +2170,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) mt_slots = dev->mt->num_slots; } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - - dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, + dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1; mt_slots = clamp(mt_slots, 2, 32); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { mt_slots = 2; @@ -2216,18 +2218,16 @@ static void __input_unregister_device(struct input_dev *dev) input_disconnect_device(dev); - mutex_lock(&input_mutex); + scoped_guard(mutex, &input_mutex) { + list_for_each_entry_safe(handle, next, &dev->h_list, d_node) + handle->handler->disconnect(handle); + WARN_ON(!list_empty(&dev->h_list)); - list_for_each_entry_safe(handle, next, &dev->h_list, d_node) - handle->handler->disconnect(handle); - WARN_ON(!list_empty(&dev->h_list)); + timer_delete_sync(&dev->timer); + list_del_init(&dev->node); - del_timer_sync(&dev->timer); - list_del_init(&dev->node); - - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); + input_wakeup_procfs_readers(); + } device_del(&dev->dev); } @@ -2250,9 +2250,8 @@ static void devm_input_device_unregister(struct device *dev, void *res) static void input_repeat_key(struct timer_list *t) { struct input_dev *dev = from_timer(dev, t, timer); - unsigned long flags; - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); if (!dev->inhibited && test_bit(dev->repeat_key, dev->key) && @@ -2266,8 +2265,6 @@ static void input_repeat_key(struct timer_list *t) mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); } - - spin_unlock_irqrestore(&dev->event_lock, flags); } /** @@ -2294,6 +2291,35 @@ bool input_device_enabled(struct input_dev *dev) } EXPORT_SYMBOL_GPL(input_device_enabled); +static int input_device_tune_vals(struct input_dev *dev) +{ + struct input_value *vals; + unsigned int packet_size; + unsigned int max_vals; + + packet_size = input_estimate_events_per_packet(dev); + if (dev->hint_events_per_packet < packet_size) + dev->hint_events_per_packet = packet_size; + + max_vals = dev->hint_events_per_packet + 2; + if (dev->max_vals >= max_vals) + return 0; + + vals = kcalloc(max_vals, sizeof(*vals), GFP_KERNEL); + if (!vals) + return -ENOMEM; + + scoped_guard(spinlock_irq, &dev->event_lock) { + dev->max_vals = max_vals; + swap(dev->vals, vals); + } + + /* Because of swap() above, this frees the old vals memory */ + kfree(vals); + + return 0; +} + /** * input_register_device - register device with input core * @dev: device to be registered @@ -2321,7 +2347,6 @@ int input_register_device(struct input_dev *dev) { struct input_devres *devres = NULL; struct input_handler *handler; - unsigned int packet_size; const char *path; int error; @@ -2349,16 +2374,9 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - packet_size = input_estimate_events_per_packet(dev); - if (dev->hint_events_per_packet < packet_size) - dev->hint_events_per_packet = packet_size; - - dev->max_vals = dev->hint_events_per_packet + 2; - dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); - if (!dev->vals) { - error = -ENOMEM; + error = input_device_tune_vals(dev); + if (error) goto err_devres_free; - } /* * If delay and period are pre-set by the driver, then autorepeating @@ -2378,7 +2396,7 @@ int input_register_device(struct input_dev *dev) error = device_add(&dev->dev); if (error) - goto err_free_vals; + goto err_devres_free; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n", @@ -2386,18 +2404,15 @@ int input_register_device(struct input_dev *dev) path ? path : "N/A"); kfree(path); - error = mutex_lock_interruptible(&input_mutex); - if (error) - goto err_device_del; - - list_add_tail(&dev->node, &input_dev_list); + error = -EINTR; + scoped_cond_guard(mutex_intr, goto err_device_del, &input_mutex) { + list_add_tail(&dev->node, &input_dev_list); - list_for_each_entry(handler, &input_handler_list, node) - input_attach_handler(dev, handler); + list_for_each_entry(handler, &input_handler_list, node) + input_attach_handler(dev, handler); - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); + input_wakeup_procfs_readers(); + } if (dev->devres_managed) { dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n", @@ -2408,9 +2423,6 @@ int input_register_device(struct input_dev *dev) err_device_del: device_del(&dev->dev); -err_free_vals: - kfree(dev->vals); - dev->vals = NULL; err_devres_free: devres_free(devres); return error; @@ -2443,6 +2455,26 @@ void input_unregister_device(struct input_dev *dev) } EXPORT_SYMBOL(input_unregister_device); +static int input_handler_check_methods(const struct input_handler *handler) +{ + int count = 0; + + if (handler->filter) + count++; + if (handler->events) + count++; + if (handler->event) + count++; + + if (count > 1) { + pr_err("%s: only one event processing method can be defined (%s)\n", + __func__, handler->name); + return -EINVAL; + } + + return 0; +} + /** * input_register_handler - register a new input handler * @handler: handler to be registered @@ -2456,20 +2488,21 @@ int input_register_handler(struct input_handler *handler) struct input_dev *dev; int error; - error = mutex_lock_interruptible(&input_mutex); + error = input_handler_check_methods(handler); if (error) return error; - INIT_LIST_HEAD(&handler->h_list); + scoped_cond_guard(mutex_intr, return -EINTR, &input_mutex) { + INIT_LIST_HEAD(&handler->h_list); - list_add_tail(&handler->node, &input_handler_list); + list_add_tail(&handler->node, &input_handler_list); - list_for_each_entry(dev, &input_dev_list, node) - input_attach_handler(dev, handler); + list_for_each_entry(dev, &input_dev_list, node) + input_attach_handler(dev, handler); - input_wakeup_procfs_readers(); + input_wakeup_procfs_readers(); + } - mutex_unlock(&input_mutex); return 0; } EXPORT_SYMBOL(input_register_handler); @@ -2485,7 +2518,7 @@ void input_unregister_handler(struct input_handler *handler) { struct input_handle *handle, *next; - mutex_lock(&input_mutex); + guard(mutex)(&input_mutex); list_for_each_entry_safe(handle, next, &handler->h_list, h_node) handler->disconnect(handle); @@ -2494,8 +2527,6 @@ void input_unregister_handler(struct input_handler *handler) list_del_init(&handler->node); input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); } EXPORT_SYMBOL(input_unregister_handler); @@ -2515,22 +2546,89 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data, int (*fn)(struct input_handle *, void *)) { struct input_handle *handle; - int retval = 0; + int retval; - rcu_read_lock(); + guard(rcu)(); list_for_each_entry_rcu(handle, &handler->h_list, h_node) { retval = fn(handle, data); if (retval) - break; + return retval; } - rcu_read_unlock(); - - return retval; + return 0; } EXPORT_SYMBOL(input_handler_for_each_handle); +/* + * An implementation of input_handle's handle_events() method that simply + * invokes handler->event() method for each event one by one. + */ +static unsigned int input_handle_events_default(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *v; + + for (v = vals; v != vals + count; v++) + handler->event(handle, v->type, v->code, v->value); + + return count; +} + +/* + * An implementation of input_handle's handle_events() method that invokes + * handler->filter() method for each event one by one and removes events + * that were filtered out from the "vals" array. + */ +static unsigned int input_handle_events_filter(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *end = vals; + struct input_value *v; + + for (v = vals; v != vals + count; v++) { + if (handler->filter(handle, v->type, v->code, v->value)) + continue; + if (end != v) + *end = *v; + end++; + } + + return end - vals; +} + +/* + * An implementation of input_handle's handle_events() method that does nothing. + */ +static unsigned int input_handle_events_null(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + return count; +} + +/* + * Sets up appropriate handle->event_handler based on the input_handler + * associated with the handle. + */ +static void input_handle_setup_event_handler(struct input_handle *handle) +{ + struct input_handler *handler = handle->handler; + + if (handler->filter) + handle->handle_events = input_handle_events_filter; + else if (handler->event) + handle->handle_events = input_handle_events_default; + else if (handler->events) + handle->handle_events = handler->events; + else + handle->handle_events = input_handle_events_null; +} + /** * input_register_handle - register a new input handle * @handle: handle to register @@ -2546,26 +2644,22 @@ int input_register_handle(struct input_handle *handle) { struct input_handler *handler = handle->handler; struct input_dev *dev = handle->dev; - int error; + input_handle_setup_event_handler(handle); /* * We take dev->mutex here to prevent race with * input_release_device(). */ - error = mutex_lock_interruptible(&dev->mutex); - if (error) - return error; - - /* - * 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); + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + /* + * 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); + } /* * Since we are supposed to be called from ->connect() @@ -2601,9 +2695,8 @@ void input_unregister_handle(struct input_handle *handle) /* * Take dev->mutex to prevent race with input_release_device(). */ - mutex_lock(&dev->mutex); - list_del_rcu(&handle->d_node); - mutex_unlock(&dev->mutex); + scoped_guard(mutex, &dev->mutex) + list_del_rcu(&handle->d_node); synchronize_rcu(); } |