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
6# Each configuration option enables a list of files.6# Each configuration option enables a list of files.
7 7
8obj-$(CONFIG_INPUT) += input-core.o8obj-$(CONFIG_INPUT) += input-core.o
9input-core-y := input.o input-compat.o input-mt.o ff-core.o9input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o
10 10
11obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o11obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
12obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o12obj-$(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
15struct 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
26static 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
37static 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
46void 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
54void 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
63void input_dev_poller_stop(struct input_dev_poller *poller)
64{
65 cancel_delayed_work_sync(&poller->work);
66}
67
68int 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}
92EXPORT_SYMBOL(input_setup_polling);
93
94static 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
105void 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}
110EXPORT_SYMBOL(input_set_poll_interval);
111
112void 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}
117EXPORT_SYMBOL(input_set_min_poll_interval);
118
119void 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}
124EXPORT_SYMBOL(input_set_max_poll_interval);
125
126/* SYSFS interface */
127
128static 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
137static 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
171static DEVICE_ATTR(poll, 0644,
172 input_dev_get_poll_interval, input_dev_set_poll_interval);
173
174static 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
182static DEVICE_ATTR(max, 0444, input_dev_get_poll_max, NULL);
183
184static 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
192static DEVICE_ATTR(min, 0444, input_dev_get_poll_min, NULL);
193
194static 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
203static struct attribute *input_poller_attrs[] = {
204 &dev_attr_poll.attr,
205 &dev_attr_max.attr,
206 &dev_attr_min.attr,
207 NULL
208};
209
210struct 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
10struct input_dev_poller;
11
12void input_dev_poller_finalize(struct input_dev_poller *poller);
13void input_dev_poller_start(struct input_dev_poller *poller);
14void input_dev_poller_stop(struct input_dev_poller *poller);
15
16extern 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
24#include <linux/mutex.h>24#include <linux/mutex.h>
25#include <linux/rcupdate.h>25#include <linux/rcupdate.h>
26#include "input-compat.h"26#include "input-compat.h"
27#include "input-poller.h"
27 28
28MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");29MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
29MODULE_DESCRIPTION("Input core");30MODULE_DESCRIPTION("Input core");
@@ -603,20 +604,31 @@ int input_open_device(struct input_handle *handle) · 573 unmodified lines
603 604
604 handle->open++;605 handle->open++;
605 606
606 if (!dev->users++ && dev->open)607 if (dev->users++) {
607 retval = dev->open(dev);608 /*
609 * Device is already opened, so we can exit immediately and
610 * report success.
611 */
612 goto out;
613 }
608 614
609 if (retval) {615 if (dev->open) {
610 dev->users--;616 retval = dev->open(dev);
611 if (!--handle->open) {617 if (retval) {
618 dev->users--;
619 handle->open--;
612 /*620 /*
613 * Make sure we are not delivering any more events621 * Make sure we are not delivering any more events
614 * through this handle622 * through this handle
615 */623 */
616 synchronize_rcu();624 synchronize_rcu();
625 goto out;
617 }626 }
618 }627 }
619 628
629 if (dev->poller)
630 input_dev_poller_start(dev->poller);
631
620 out:632 out:
621 mutex_unlock(&dev->mutex);633 mutex_unlock(&dev->mutex);
622 return retval;634 return retval;
@@ -655,8 +667,13 @@ void input_close_device(struct input_handle *handle) · 32 unmodified lines
655 667
656 __input_release_device(handle);668 __input_release_device(handle);
657 669
658 if (!--dev->users && dev->close)670 if (!--dev->users) {
659 dev->close(dev);671 if (dev->poller)
672 input_dev_poller_stop(dev->poller);
673
674 if (dev->close)
675 dev->close(dev);
676 }
660 677
661 if (!--handle->open) {678 if (!--handle->open) {
662 /*679 /*
@@ -1502,6 +1519,7 @@ static const struct attribute_group *input_dev_attr_groups[] = { · 839 unmodified lines
1502 &input_dev_attr_group,1519 &input_dev_attr_group,
1503 &input_dev_id_attr_group,1520 &input_dev_id_attr_group,
1504 &input_dev_caps_attr_group,1521 &input_dev_caps_attr_group,
1522 &input_poller_attribute_group,
1505 NULL1523 NULL
1506};1524};
1507 1525
@@ -1511,6 +1529,7 @@ static void input_dev_release(struct device *device) · 3 unmodified lines
1511 1529
1512 input_ff_destroy(dev);1530 input_ff_destroy(dev);
1513 input_mt_destroy_slots(dev);1531 input_mt_destroy_slots(dev);
1532 kfree(dev->poller);
1514 kfree(dev->absinfo);1533 kfree(dev->absinfo);
1515 kfree(dev->vals);1534 kfree(dev->vals);
1516 kfree(dev);1535 kfree(dev);
@@ -2175,6 +2194,9 @@ int input_register_device(struct input_dev *dev) · 658 unmodified lines
2175 if (!dev->setkeycode)2194 if (!dev->setkeycode)
2176 dev->setkeycode = input_default_setkeycode;2195 dev->setkeycode = input_default_setkeycode;
2177 2196
2197 if (dev->poller)
2198 input_dev_poller_finalize(dev->poller);
2199
2178 error = device_add(&dev->dev);2200 error = device_add(&dev->dev);
2179 if (error)2201 if (error)
2180 goto err_free_vals;2202 goto err_free_vals;
include/linux/input.h+12−0
@@ -21,6 +21,8 @@ · 20 unmodified lines
21#include <linux/timer.h>21#include <linux/timer.h>
22#include <linux/mod_devicetable.h>22#include <linux/mod_devicetable.h>
23 23
24struct input_dev_poller;
25
24/**26/**
25 * struct input_value - input value representation27 * struct input_value - input value representation
26 * @type: type of value (EV_KEY, EV_ABS, etc)28 * @type: type of value (EV_KEY, EV_ABS, etc)
@@ -71,6 +73,8 @@ enum input_clock_type { · 44 unmodified lines
71 * not sleep73 * not sleep
72 * @ff: force feedback structure associated with the device if device74 * @ff: force feedback structure associated with the device if device
73 * supports force feedback effects75 * supports force feedback effects
76 * @poller: poller structure associated with the device if device is
77 * set up to use polling mode
74 * @repeat_key: stores key code of the last key pressed; used to implement78 * @repeat_key: stores key code of the last key pressed; used to implement
75 * software autorepeat79 * software autorepeat
76 * @timer: timer for software autorepeat80 * @timer: timer for software autorepeat
@@ -156,6 +160,8 @@ struct input_dev { · 79 unmodified lines
156 160
157 struct ff_device *ff;161 struct ff_device *ff;
158 162
163 struct input_dev_poller *poller;
164
159 unsigned int repeat_key;165 unsigned int repeat_key;
160 struct timer_list timer;166 struct timer_list timer;
161 167
@@ -372,6 +378,12 @@ void input_unregister_device(struct input_dev *); · 210 unmodified lines
372 378
373void input_reset_device(struct input_dev *);379void input_reset_device(struct input_dev *);
374 380
381int input_setup_polling(struct input_dev *dev,
382 void (*poll_fn)(struct input_dev *dev));
383void input_set_poll_interval(struct input_dev *dev, unsigned int interval);
384void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval);
385void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval);
386
375int __must_check input_register_handler(struct input_handler *);387int __must_check input_register_handler(struct input_handler *);
376void input_unregister_handler(struct input_handler *);388void input_unregister_handler(struct input_handler *);
377 389

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