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>
This commit is contained in:
Dmitry Torokhov
2017-04-18 17:28:30 -07:00
parent 2da9d2b5b9
commit e95656ea15
5 changed files with 273 additions and 8 deletions

View File

@@ -24,6 +24,7 @@
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include "input-compat.h"
#include "input-poller.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
@@ -603,20 +604,31 @@ int input_open_device(struct input_handle *handle)
handle->open++;
if (!dev->users++ && dev->open)
retval = dev->open(dev);
if (dev->users++) {
/*
* Device is already opened, so we can exit immediately and
* report success.
*/
goto out;
}
if (retval) {
dev->users--;
if (!--handle->open) {
if (dev->open) {
retval = dev->open(dev);
if (retval) {
dev->users--;
handle->open--;
/*
* Make sure we are not delivering any more events
* through this handle
*/
synchronize_rcu();
goto out;
}
}
if (dev->poller)
input_dev_poller_start(dev->poller);
out:
mutex_unlock(&dev->mutex);
return retval;
@@ -655,8 +667,13 @@ void input_close_device(struct input_handle *handle)
__input_release_device(handle);
if (!--dev->users && dev->close)
dev->close(dev);
if (!--dev->users) {
if (dev->poller)
input_dev_poller_stop(dev->poller);
if (dev->close)
dev->close(dev);
}
if (!--handle->open) {
/*
@@ -1502,6 +1519,7 @@ static const struct attribute_group *input_dev_attr_groups[] = {
&input_dev_attr_group,
&input_dev_id_attr_group,
&input_dev_caps_attr_group,
&input_poller_attribute_group,
NULL
};
@@ -1511,6 +1529,7 @@ static void input_dev_release(struct device *device)
input_ff_destroy(dev);
input_mt_destroy_slots(dev);
kfree(dev->poller);
kfree(dev->absinfo);
kfree(dev->vals);
kfree(dev);
@@ -2175,6 +2194,9 @@ int input_register_device(struct input_dev *dev)
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
if (dev->poller)
input_dev_poller_finalize(dev->poller);
error = device_add(&dev->dev);
if (error)
goto err_free_vals;