From e95656ea15e54d4e6a192d560d84008b53fc1eb5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 18 Apr 2017 17:28:30 -0700 Subject: Input: add support for polling to input devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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áč Acked-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index 7494a0dede79..c08aa3596144 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@ #include #include #include "input-compat.h" +#include "input-poller.h" MODULE_AUTHOR("Vojtech Pavlik "); 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; -- cgit v1.2.3