| // SPDX-License-Identifier: GPL-2.0-only | 
 | /* | 
 |  * Support for polling mode for input devices. | 
 |  */ | 
 |  | 
 | #include <linux/device.h> | 
 | #include <linux/input.h> | 
 | #include <linux/jiffies.h> | 
 | #include <linux/mutex.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/types.h> | 
 | #include <linux/workqueue.h> | 
 | #include "input-poller.h" | 
 |  | 
 | struct input_dev_poller { | 
 | 	void (*poll)(struct input_dev *dev); | 
 |  | 
 | 	unsigned int poll_interval; /* msec */ | 
 | 	unsigned int poll_interval_max; /* msec */ | 
 | 	unsigned int poll_interval_min; /* msec */ | 
 |  | 
 | 	struct input_dev *input; | 
 | 	struct delayed_work work; | 
 | }; | 
 |  | 
 | static void input_dev_poller_queue_work(struct input_dev_poller *poller) | 
 | { | 
 | 	unsigned long delay; | 
 |  | 
 | 	delay = msecs_to_jiffies(poller->poll_interval); | 
 | 	if (delay >= HZ) | 
 | 		delay = round_jiffies_relative(delay); | 
 |  | 
 | 	queue_delayed_work(system_freezable_wq, &poller->work, delay); | 
 | } | 
 |  | 
 | static void input_dev_poller_work(struct work_struct *work) | 
 | { | 
 | 	struct input_dev_poller *poller = | 
 | 		container_of(work, struct input_dev_poller, work.work); | 
 |  | 
 | 	poller->poll(poller->input); | 
 | 	input_dev_poller_queue_work(poller); | 
 | } | 
 |  | 
 | void input_dev_poller_finalize(struct input_dev_poller *poller) | 
 | { | 
 | 	if (!poller->poll_interval) | 
 | 		poller->poll_interval = 500; | 
 | 	if (!poller->poll_interval_max) | 
 | 		poller->poll_interval_max = poller->poll_interval; | 
 | } | 
 |  | 
 | void input_dev_poller_start(struct input_dev_poller *poller) | 
 | { | 
 | 	/* Only start polling if polling is enabled */ | 
 | 	if (poller->poll_interval > 0) { | 
 | 		poller->poll(poller->input); | 
 | 		input_dev_poller_queue_work(poller); | 
 | 	} | 
 | } | 
 |  | 
 | void input_dev_poller_stop(struct input_dev_poller *poller) | 
 | { | 
 | 	cancel_delayed_work_sync(&poller->work); | 
 | } | 
 |  | 
 | int input_setup_polling(struct input_dev *dev, | 
 | 			void (*poll_fn)(struct input_dev *dev)) | 
 | { | 
 | 	struct input_dev_poller *poller; | 
 |  | 
 | 	poller = kzalloc(sizeof(*poller), GFP_KERNEL); | 
 | 	if (!poller) { | 
 | 		/* | 
 | 		 * We want to show message even though kzalloc() may have | 
 | 		 * printed backtrace as knowing what instance of input | 
 | 		 * device we were dealing with is helpful. | 
 | 		 */ | 
 | 		dev_err(dev->dev.parent ?: &dev->dev, | 
 | 			"%s: unable to allocate poller structure\n", __func__); | 
 | 		return -ENOMEM; | 
 | 	} | 
 |  | 
 | 	INIT_DELAYED_WORK(&poller->work, input_dev_poller_work); | 
 | 	poller->input = dev; | 
 | 	poller->poll = poll_fn; | 
 |  | 
 | 	dev->poller = poller; | 
 | 	return 0; | 
 | } | 
 | EXPORT_SYMBOL(input_setup_polling); | 
 |  | 
 | static bool input_dev_ensure_poller(struct input_dev *dev) | 
 | { | 
 | 	if (!dev->poller) { | 
 | 		dev_err(dev->dev.parent ?: &dev->dev, | 
 | 			"poller structure has not been set up\n"); | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	return true; | 
 | } | 
 |  | 
 | void input_set_poll_interval(struct input_dev *dev, unsigned int interval) | 
 | { | 
 | 	if (input_dev_ensure_poller(dev)) | 
 | 		dev->poller->poll_interval = interval; | 
 | } | 
 | EXPORT_SYMBOL(input_set_poll_interval); | 
 |  | 
 | void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval) | 
 | { | 
 | 	if (input_dev_ensure_poller(dev)) | 
 | 		dev->poller->poll_interval_min = interval; | 
 | } | 
 | EXPORT_SYMBOL(input_set_min_poll_interval); | 
 |  | 
 | void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval) | 
 | { | 
 | 	if (input_dev_ensure_poller(dev)) | 
 | 		dev->poller->poll_interval_max = interval; | 
 | } | 
 | EXPORT_SYMBOL(input_set_max_poll_interval); | 
 |  | 
 | int input_get_poll_interval(struct input_dev *dev) | 
 | { | 
 | 	if (!dev->poller) | 
 | 		return -EINVAL; | 
 |  | 
 | 	return dev->poller->poll_interval; | 
 | } | 
 | EXPORT_SYMBOL(input_get_poll_interval); | 
 |  | 
 | /* SYSFS interface */ | 
 |  | 
 | static ssize_t input_dev_get_poll_interval(struct device *dev, | 
 | 					   struct device_attribute *attr, | 
 | 					   char *buf) | 
 | { | 
 | 	struct input_dev *input = to_input_dev(dev); | 
 |  | 
 | 	return sprintf(buf, "%d\n", input->poller->poll_interval); | 
 | } | 
 |  | 
 | static ssize_t input_dev_set_poll_interval(struct device *dev, | 
 | 					   struct device_attribute *attr, | 
 | 					   const char *buf, size_t count) | 
 | { | 
 | 	struct input_dev *input = to_input_dev(dev); | 
 | 	struct input_dev_poller *poller = input->poller; | 
 | 	unsigned int interval; | 
 | 	int err; | 
 |  | 
 | 	err = kstrtouint(buf, 0, &interval); | 
 | 	if (err) | 
 | 		return err; | 
 |  | 
 | 	if (interval < poller->poll_interval_min) | 
 | 		return -EINVAL; | 
 |  | 
 | 	if (interval > poller->poll_interval_max) | 
 | 		return -EINVAL; | 
 |  | 
 | 	mutex_lock(&input->mutex); | 
 |  | 
 | 	poller->poll_interval = interval; | 
 |  | 
 | 	if (input_device_enabled(input)) { | 
 | 		cancel_delayed_work_sync(&poller->work); | 
 | 		if (poller->poll_interval > 0) | 
 | 			input_dev_poller_queue_work(poller); | 
 | 	} | 
 |  | 
 | 	mutex_unlock(&input->mutex); | 
 |  | 
 | 	return count; | 
 | } | 
 |  | 
 | static DEVICE_ATTR(poll, 0644, | 
 | 		   input_dev_get_poll_interval, input_dev_set_poll_interval); | 
 |  | 
 | static ssize_t input_dev_get_poll_max(struct device *dev, | 
 | 				      struct device_attribute *attr, char *buf) | 
 | { | 
 | 	struct input_dev *input = to_input_dev(dev); | 
 |  | 
 | 	return sprintf(buf, "%d\n", input->poller->poll_interval_max); | 
 | } | 
 |  | 
 | static DEVICE_ATTR(max, 0444, input_dev_get_poll_max, NULL); | 
 |  | 
 | static ssize_t input_dev_get_poll_min(struct device *dev, | 
 | 				     struct device_attribute *attr, char *buf) | 
 | { | 
 | 	struct input_dev *input = to_input_dev(dev); | 
 |  | 
 | 	return sprintf(buf, "%d\n", input->poller->poll_interval_min); | 
 | } | 
 |  | 
 | static DEVICE_ATTR(min, 0444, input_dev_get_poll_min, NULL); | 
 |  | 
 | static umode_t input_poller_attrs_visible(struct kobject *kobj, | 
 | 					  struct attribute *attr, int n) | 
 | { | 
 | 	struct device *dev = kobj_to_dev(kobj); | 
 | 	struct input_dev *input = to_input_dev(dev); | 
 |  | 
 | 	return input->poller ? attr->mode : 0; | 
 | } | 
 |  | 
 | static struct attribute *input_poller_attrs[] = { | 
 | 	&dev_attr_poll.attr, | 
 | 	&dev_attr_max.attr, | 
 | 	&dev_attr_min.attr, | 
 | 	NULL | 
 | }; | 
 |  | 
 | struct attribute_group input_poller_attribute_group = { | 
 | 	.is_visible	= input_poller_attrs_visible, | 
 | 	.attrs		= input_poller_attrs, | 
 | }; |