Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add support for polling to input devices

Separating "normal" and "polled" input devices was a mistake, as often we
want to allow the very same device work on both interrupt-driven and
polled mode, depending on the board on which the device is used.

This introduces new APIs:

- input_setup_polling
- input_set_poll_interval
- input_set_min_poll_interval
- input_set_max_poll_interval

These new APIs allow switching an input device into polled mode with sysfs
attributes matching drivers using input_polled_dev APIs that will be
eventually removed.

Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+273 -8
+1 -1
drivers/input/Makefile
··· 6 6 # Each configuration option enables a list of files. 7 7 8 8 obj-$(CONFIG_INPUT) += input-core.o 9 - input-core-y := input.o input-compat.o input-mt.o ff-core.o 9 + input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o 10 10 11 11 obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o 12 12 obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
+213
drivers/input/input-poller.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Support for polling mode for input devices. 4 + */ 5 + 6 + #include <linux/device.h> 7 + #include <linux/input.h> 8 + #include <linux/jiffies.h> 9 + #include <linux/mutex.h> 10 + #include <linux/slab.h> 11 + #include <linux/types.h> 12 + #include <linux/workqueue.h> 13 + #include "input-poller.h" 14 + 15 + struct input_dev_poller { 16 + void (*poll)(struct input_dev *dev); 17 + 18 + unsigned int poll_interval; /* msec */ 19 + unsigned int poll_interval_max; /* msec */ 20 + unsigned int poll_interval_min; /* msec */ 21 + 22 + struct input_dev *input; 23 + struct delayed_work work; 24 + }; 25 + 26 + static void input_dev_poller_queue_work(struct input_dev_poller *poller) 27 + { 28 + unsigned long delay; 29 + 30 + delay = msecs_to_jiffies(poller->poll_interval); 31 + if (delay >= HZ) 32 + delay = round_jiffies_relative(delay); 33 + 34 + queue_delayed_work(system_freezable_wq, &poller->work, delay); 35 + } 36 + 37 + static void input_dev_poller_work(struct work_struct *work) 38 + { 39 + struct input_dev_poller *poller = 40 + container_of(work, struct input_dev_poller, work.work); 41 + 42 + poller->poll(poller->input); 43 + input_dev_poller_queue_work(poller); 44 + } 45 + 46 + void input_dev_poller_finalize(struct input_dev_poller *poller) 47 + { 48 + if (!poller->poll_interval) 49 + poller->poll_interval = 500; 50 + if (!poller->poll_interval_max) 51 + poller->poll_interval_max = poller->poll_interval; 52 + } 53 + 54 + void input_dev_poller_start(struct input_dev_poller *poller) 55 + { 56 + /* Only start polling if polling is enabled */ 57 + if (poller->poll_interval > 0) { 58 + poller->poll(poller->input); 59 + input_dev_poller_queue_work(poller); 60 + } 61 + } 62 + 63 + void input_dev_poller_stop(struct input_dev_poller *poller) 64 + { 65 + cancel_delayed_work_sync(&poller->work); 66 + } 67 + 68 + int input_setup_polling(struct input_dev *dev, 69 + void (*poll_fn)(struct input_dev *dev)) 70 + { 71 + struct input_dev_poller *poller; 72 + 73 + poller = kzalloc(sizeof(*poller), GFP_KERNEL); 74 + if (!poller) { 75 + /* 76 + * We want to show message even though kzalloc() may have 77 + * printed backtrace as knowing what instance of input 78 + * device we were dealing with is helpful. 79 + */ 80 + dev_err(dev->dev.parent ?: &dev->dev, 81 + "%s: unable to allocate poller structure\n", __func__); 82 + return -ENOMEM; 83 + } 84 + 85 + INIT_DELAYED_WORK(&poller->work, input_dev_poller_work); 86 + poller->input = dev; 87 + poller->poll = poll_fn; 88 + 89 + dev->poller = poller; 90 + return 0; 91 + } 92 + EXPORT_SYMBOL(input_setup_polling); 93 + 94 + static bool input_dev_ensure_poller(struct input_dev *dev) 95 + { 96 + if (!dev->poller) { 97 + dev_err(dev->dev.parent ?: &dev->dev, 98 + "poller structure has not been set up\n"); 99 + return false; 100 + } 101 + 102 + return true; 103 + } 104 + 105 + void input_set_poll_interval(struct input_dev *dev, unsigned int interval) 106 + { 107 + if (input_dev_ensure_poller(dev)) 108 + dev->poller->poll_interval = interval; 109 + } 110 + EXPORT_SYMBOL(input_set_poll_interval); 111 + 112 + void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval) 113 + { 114 + if (input_dev_ensure_poller(dev)) 115 + dev->poller->poll_interval_min = interval; 116 + } 117 + EXPORT_SYMBOL(input_set_min_poll_interval); 118 + 119 + void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval) 120 + { 121 + if (input_dev_ensure_poller(dev)) 122 + dev->poller->poll_interval_max = interval; 123 + } 124 + EXPORT_SYMBOL(input_set_max_poll_interval); 125 + 126 + /* SYSFS interface */ 127 + 128 + static ssize_t input_dev_get_poll_interval(struct device *dev, 129 + struct device_attribute *attr, 130 + char *buf) 131 + { 132 + struct input_dev *input = to_input_dev(dev); 133 + 134 + return sprintf(buf, "%d\n", input->poller->poll_interval); 135 + } 136 + 137 + static ssize_t input_dev_set_poll_interval(struct device *dev, 138 + struct device_attribute *attr, 139 + const char *buf, size_t count) 140 + { 141 + struct input_dev *input = to_input_dev(dev); 142 + struct input_dev_poller *poller = input->poller; 143 + unsigned int interval; 144 + int err; 145 + 146 + err = kstrtouint(buf, 0, &interval); 147 + if (err) 148 + return err; 149 + 150 + if (interval < poller->poll_interval_min) 151 + return -EINVAL; 152 + 153 + if (interval > poller->poll_interval_max) 154 + return -EINVAL; 155 + 156 + mutex_lock(&input->mutex); 157 + 158 + poller->poll_interval = interval; 159 + 160 + if (input->users) { 161 + cancel_delayed_work_sync(&poller->work); 162 + if (poller->poll_interval > 0) 163 + input_dev_poller_queue_work(poller); 164 + } 165 + 166 + mutex_unlock(&input->mutex); 167 + 168 + return count; 169 + } 170 + 171 + static DEVICE_ATTR(poll, 0644, 172 + input_dev_get_poll_interval, input_dev_set_poll_interval); 173 + 174 + static ssize_t input_dev_get_poll_max(struct device *dev, 175 + struct device_attribute *attr, char *buf) 176 + { 177 + struct input_dev *input = to_input_dev(dev); 178 + 179 + return sprintf(buf, "%d\n", input->poller->poll_interval_max); 180 + } 181 + 182 + static DEVICE_ATTR(max, 0444, input_dev_get_poll_max, NULL); 183 + 184 + static ssize_t input_dev_get_poll_min(struct device *dev, 185 + struct device_attribute *attr, char *buf) 186 + { 187 + struct input_dev *input = to_input_dev(dev); 188 + 189 + return sprintf(buf, "%d\n", input->poller->poll_interval_min); 190 + } 191 + 192 + static DEVICE_ATTR(min, 0444, input_dev_get_poll_min, NULL); 193 + 194 + static umode_t input_poller_attrs_visible(struct kobject *kobj, 195 + struct attribute *attr, int n) 196 + { 197 + struct device *dev = kobj_to_dev(kobj); 198 + struct input_dev *input = to_input_dev(dev); 199 + 200 + return input->poller ? attr->mode : 0; 201 + } 202 + 203 + static struct attribute *input_poller_attrs[] = { 204 + &dev_attr_poll.attr, 205 + &dev_attr_max.attr, 206 + &dev_attr_min.attr, 207 + NULL 208 + }; 209 + 210 + struct attribute_group input_poller_attribute_group = { 211 + .is_visible = input_poller_attrs_visible, 212 + .attrs = input_poller_attrs, 213 + };
+18
drivers/input/input-poller.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + #ifndef _INPUT_POLLER_H 3 + #define _INPUT_POLLER_H 4 + 5 + /* 6 + * Support for polling mode for input devices. 7 + */ 8 + #include <linux/sysfs.h> 9 + 10 + struct input_dev_poller; 11 + 12 + void input_dev_poller_finalize(struct input_dev_poller *poller); 13 + void input_dev_poller_start(struct input_dev_poller *poller); 14 + void input_dev_poller_stop(struct input_dev_poller *poller); 15 + 16 + extern struct attribute_group input_poller_attribute_group; 17 + 18 + #endif /* _INPUT_POLLER_H */
+29 -7
drivers/input/input.c
··· 24 24 #include <linux/mutex.h> 25 25 #include <linux/rcupdate.h> 26 26 #include "input-compat.h" 27 + #include "input-poller.h" 27 28 28 29 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); 29 30 MODULE_DESCRIPTION("Input core"); ··· 604 603 605 604 handle->open++; 606 605 607 - if (!dev->users++ && dev->open) 608 - retval = dev->open(dev); 606 + if (dev->users++) { 607 + /* 608 + * Device is already opened, so we can exit immediately and 609 + * report success. 610 + */ 611 + goto out; 612 + } 609 613 610 - if (retval) { 611 - dev->users--; 612 - if (!--handle->open) { 614 + if (dev->open) { 615 + retval = dev->open(dev); 616 + if (retval) { 617 + dev->users--; 618 + handle->open--; 613 619 /* 614 620 * Make sure we are not delivering any more events 615 621 * through this handle 616 622 */ 617 623 synchronize_rcu(); 624 + goto out; 618 625 } 619 626 } 627 + 628 + if (dev->poller) 629 + input_dev_poller_start(dev->poller); 620 630 621 631 out: 622 632 mutex_unlock(&dev->mutex); ··· 667 655 668 656 __input_release_device(handle); 669 657 670 - if (!--dev->users && dev->close) 671 - dev->close(dev); 658 + if (!--dev->users) { 659 + if (dev->poller) 660 + input_dev_poller_stop(dev->poller); 661 + 662 + if (dev->close) 663 + dev->close(dev); 664 + } 672 665 673 666 if (!--handle->open) { 674 667 /* ··· 1519 1502 &input_dev_attr_group, 1520 1503 &input_dev_id_attr_group, 1521 1504 &input_dev_caps_attr_group, 1505 + &input_poller_attribute_group, 1522 1506 NULL 1523 1507 }; 1524 1508 ··· 1529 1511 1530 1512 input_ff_destroy(dev); 1531 1513 input_mt_destroy_slots(dev); 1514 + kfree(dev->poller); 1532 1515 kfree(dev->absinfo); 1533 1516 kfree(dev->vals); 1534 1517 kfree(dev); ··· 2193 2174 2194 2175 if (!dev->setkeycode) 2195 2176 dev->setkeycode = input_default_setkeycode; 2177 + 2178 + if (dev->poller) 2179 + input_dev_poller_finalize(dev->poller); 2196 2180 2197 2181 error = device_add(&dev->dev); 2198 2182 if (error)
+12
include/linux/input.h
··· 21 21 #include <linux/timer.h> 22 22 #include <linux/mod_devicetable.h> 23 23 24 + struct input_dev_poller; 25 + 24 26 /** 25 27 * struct input_value - input value representation 26 28 * @type: type of value (EV_KEY, EV_ABS, etc) ··· 73 71 * not sleep 74 72 * @ff: force feedback structure associated with the device if device 75 73 * supports force feedback effects 74 + * @poller: poller structure associated with the device if device is 75 + * set up to use polling mode 76 76 * @repeat_key: stores key code of the last key pressed; used to implement 77 77 * software autorepeat 78 78 * @timer: timer for software autorepeat ··· 159 155 struct input_keymap_entry *ke); 160 156 161 157 struct ff_device *ff; 158 + 159 + struct input_dev_poller *poller; 162 160 163 161 unsigned int repeat_key; 164 162 struct timer_list timer; ··· 377 371 void input_unregister_device(struct input_dev *); 378 372 379 373 void input_reset_device(struct input_dev *); 374 + 375 + int input_setup_polling(struct input_dev *dev, 376 + void (*poll_fn)(struct input_dev *dev)); 377 + void input_set_poll_interval(struct input_dev *dev, unsigned int interval); 378 + void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval); 379 + void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval); 380 380 381 381 int __must_check input_register_handler(struct input_handler *); 382 382 void input_unregister_handler(struct input_handler *);