History

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.

Dmitry Torokhov committed 9 years ago

Commit e95656e1 parent 2da9d2b5 files · +273 −8Browse files

Unified · Split

5 files
  1. drivers/input/Makefile +1 −1
  2. drivers/input/input-poller.c +213 −0
  3. drivers/input/input-poller.h +18 −0
  4. drivers/input/input.c +29 −7
  5. include/linux/input.h +12 −0
drivers/input/Makefile+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
66 # Each configuration option enables a list of files.
77
88 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
1010
1111 obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
1212 obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
drivers/input/input-poller.c+213−0
@@ -0,0 +1,213 @@
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+};
drivers/input/input-poller.h+18−0
@@ -0,0 +1,18 @@
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 */
drivers/input/input.c+29−7
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424 #include <linux/mutex.h>
2525 #include <linux/rcupdate.h>
2626 #include "input-compat.h"
27+#include "input-poller.h"
2728
2829 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
2930 MODULE_DESCRIPTION("Input core");
@@ -603,20 +604,31 @@ int input_open_device(struct input_handle *handle) · 573 unmodified lines
603604
604605 handle->open++;
605606
606− if (!dev->users++ && dev->open)
607− retval = dev->open(dev);
607+ if (dev->users++) {
608+ /*
609+ * Device is already opened, so we can exit immediately and
610+ * report success.
611+ */
612+ goto out;
613+ }
608614
609− if (retval) {
610− dev->users--;
611− if (!--handle->open) {
615+ if (dev->open) {
616+ retval = dev->open(dev);
617+ if (retval) {
618+ dev->users--;
619+ handle->open--;
612620 /*
613621 * Make sure we are not delivering any more events
614622 * through this handle
615623 */
616624 synchronize_rcu();
625+ goto out;
617626 }
618627 }
619628
629+ if (dev->poller)
630+ input_dev_poller_start(dev->poller);
631+
620632 out:
621633 mutex_unlock(&dev->mutex);
622634 return retval;
@@ -655,8 +667,13 @@ void input_close_device(struct input_handle *handle) · 32 unmodified lines
655667
656668 __input_release_device(handle);
657669
658− if (!--dev->users && dev->close)
659− dev->close(dev);
670+ if (!--dev->users) {
671+ if (dev->poller)
672+ input_dev_poller_stop(dev->poller);
673+
674+ if (dev->close)
675+ dev->close(dev);
676+ }
660677
661678 if (!--handle->open) {
662679 /*
@@ -1502,6 +1519,7 @@ static const struct attribute_group *input_dev_attr_groups[] = { · 839 unmodified lines
15021519 &input_dev_attr_group,
15031520 &input_dev_id_attr_group,
15041521 &input_dev_caps_attr_group,
1522+ &input_poller_attribute_group,
15051523 NULL
15061524 };
15071525
@@ -1511,6 +1529,7 @@ static void input_dev_release(struct device *device) · 3 unmodified lines
15111529
15121530 input_ff_destroy(dev);
15131531 input_mt_destroy_slots(dev);
1532+ kfree(dev->poller);
15141533 kfree(dev->absinfo);
15151534 kfree(dev->vals);
15161535 kfree(dev);
@@ -2175,6 +2194,9 @@ int input_register_device(struct input_dev *dev) · 658 unmodified lines
21752194 if (!dev->setkeycode)
21762195 dev->setkeycode = input_default_setkeycode;
21772196
2197+ if (dev->poller)
2198+ input_dev_poller_finalize(dev->poller);
2199+
21782200 error = device_add(&dev->dev);
21792201 if (error)
21802202 goto err_free_vals;
include/linux/input.h+12−0
@@ -21,6 +21,8 @@ · 20 unmodified lines
2121 #include <linux/timer.h>
2222 #include <linux/mod_devicetable.h>
2323
24+struct input_dev_poller;
25+
2426 /**
2527 * struct input_value - input value representation
2628 * @type: type of value (EV_KEY, EV_ABS, etc)
@@ -71,6 +73,8 @@ enum input_clock_type { · 44 unmodified lines
7173 * not sleep
7274 * @ff: force feedback structure associated with the device if device
7375 * supports force feedback effects
76+ * @poller: poller structure associated with the device if device is
77+ * set up to use polling mode
7478 * @repeat_key: stores key code of the last key pressed; used to implement
7579 * software autorepeat
7680 * @timer: timer for software autorepeat
@@ -156,6 +160,8 @@ struct input_dev { · 79 unmodified lines
156160
157161 struct ff_device *ff;
158162
163+ struct input_dev_poller *poller;
164+
159165 unsigned int repeat_key;
160166 struct timer_list timer;
161167
@@ -372,6 +378,12 @@ void input_unregister_device(struct input_dev *); · 210 unmodified lines
372378
373379 void input_reset_device(struct input_dev *);
374380
381+int input_setup_polling(struct input_dev *dev,
382+ void (*poll_fn)(struct input_dev *dev));
383+void input_set_poll_interval(struct input_dev *dev, unsigned int interval);
384+void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval);
385+void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval);
386+
375387 int __must_check input_register_handler(struct input_handler *);
376388 void input_unregister_handler(struct input_handler *);
377389

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t