aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSamu Onkalo <samu.p.onkalo@nokia.com>2009-11-14 00:13:22 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-11-20 03:52:09 -0500
commitdad725d089b94bce8bbc769b7471dcfba3fbda0e (patch)
tree5010ad0f241530511bd5e80b7f5437556527641a /drivers
parentbc8f1eaf68a8aa1d993492f1ad2d74502665f578 (diff)
Input: input-polldev - add sysfs interface for controlling poll interval
Sysfs entry for reading and setting of the polling interval. If the interval is set to 0, polling is stopped. Polling is restarted when interval is changed to non-zero. sysfs entries: poll = current polling interval in msec (RW) max = max allowed polling interval (RO) min = min allowed polling interval (RO) Minimum and maximum limit for interval can be set while setting up the device. Interval can be adjusted even if the input device is not currently open. [dtor@mail.ru: add kernel doc markup for the new fields] Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/input-polldev.c111
1 files changed, 105 insertions, 6 deletions
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 910220c127cb..31874275fed0 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -56,14 +56,10 @@ static void input_polldev_stop_workqueue(void)
56 mutex_unlock(&polldev_mutex); 56 mutex_unlock(&polldev_mutex);
57} 57}
58 58
59static void input_polled_device_work(struct work_struct *work) 59static void input_polldev_queue_work(struct input_polled_dev *dev)
60{ 60{
61 struct input_polled_dev *dev =
62 container_of(work, struct input_polled_dev, work.work);
63 unsigned long delay; 61 unsigned long delay;
64 62
65 dev->poll(dev);
66
67 delay = msecs_to_jiffies(dev->poll_interval); 63 delay = msecs_to_jiffies(dev->poll_interval);
68 if (delay >= HZ) 64 if (delay >= HZ)
69 delay = round_jiffies_relative(delay); 65 delay = round_jiffies_relative(delay);
@@ -71,6 +67,15 @@ static void input_polled_device_work(struct work_struct *work)
71 queue_delayed_work(polldev_wq, &dev->work, delay); 67 queue_delayed_work(polldev_wq, &dev->work, delay);
72} 68}
73 69
70static void input_polled_device_work(struct work_struct *work)
71{
72 struct input_polled_dev *dev =
73 container_of(work, struct input_polled_dev, work.work);
74
75 dev->poll(dev);
76 input_polldev_queue_work(dev);
77}
78
74static int input_open_polled_device(struct input_dev *input) 79static int input_open_polled_device(struct input_dev *input)
75{ 80{
76 struct input_polled_dev *dev = input_get_drvdata(input); 81 struct input_polled_dev *dev = input_get_drvdata(input);
@@ -100,6 +105,83 @@ static void input_close_polled_device(struct input_dev *input)
100 dev->close(dev); 105 dev->close(dev);
101} 106}
102 107
108/* SYSFS interface */
109
110static ssize_t input_polldev_get_poll(struct device *dev,
111 struct device_attribute *attr, char *buf)
112{
113 struct input_polled_dev *polldev = dev_get_drvdata(dev);
114
115 return sprintf(buf, "%d\n", polldev->poll_interval);
116}
117
118static ssize_t input_polldev_set_poll(struct device *dev,
119 struct device_attribute *attr, const char *buf,
120 size_t count)
121{
122 struct input_polled_dev *polldev = dev_get_drvdata(dev);
123 struct input_dev *input = polldev->input;
124 unsigned long interval;
125
126 if (strict_strtoul(buf, 0, &interval))
127 return -EINVAL;
128
129 if (interval < polldev->poll_interval_min)
130 return -EINVAL;
131
132 if (interval > polldev->poll_interval_max)
133 return -EINVAL;
134
135 mutex_lock(&input->mutex);
136
137 polldev->poll_interval = interval;
138
139 if (input->users) {
140 cancel_delayed_work_sync(&polldev->work);
141 if (polldev->poll_interval > 0)
142 input_polldev_queue_work(polldev);
143 }
144
145 mutex_unlock(&input->mutex);
146
147 return count;
148}
149
150static DEVICE_ATTR(poll, S_IRUGO | S_IWUSR, input_polldev_get_poll,
151 input_polldev_set_poll);
152
153
154static ssize_t input_polldev_get_max(struct device *dev,
155 struct device_attribute *attr, char *buf)
156{
157 struct input_polled_dev *polldev = dev_get_drvdata(dev);
158
159 return sprintf(buf, "%d\n", polldev->poll_interval_max);
160}
161
162static DEVICE_ATTR(max, S_IRUGO, input_polldev_get_max, NULL);
163
164static ssize_t input_polldev_get_min(struct device *dev,
165 struct device_attribute *attr, char *buf)
166{
167 struct input_polled_dev *polldev = dev_get_drvdata(dev);
168
169 return sprintf(buf, "%d\n", polldev->poll_interval_min);
170}
171
172static DEVICE_ATTR(min, S_IRUGO, input_polldev_get_min, NULL);
173
174static struct attribute *sysfs_attrs[] = {
175 &dev_attr_poll.attr,
176 &dev_attr_max.attr,
177 &dev_attr_min.attr,
178 NULL
179};
180
181static struct attribute_group input_polldev_attribute_group = {
182 .attrs = sysfs_attrs
183};
184
103/** 185/**
104 * input_allocate_polled_device - allocated memory polled device 186 * input_allocate_polled_device - allocated memory polled device
105 * 187 *
@@ -153,15 +235,29 @@ EXPORT_SYMBOL(input_free_polled_device);
153int input_register_polled_device(struct input_polled_dev *dev) 235int input_register_polled_device(struct input_polled_dev *dev)
154{ 236{
155 struct input_dev *input = dev->input; 237 struct input_dev *input = dev->input;
238 int error;
156 239
157 input_set_drvdata(input, dev); 240 input_set_drvdata(input, dev);
158 INIT_DELAYED_WORK(&dev->work, input_polled_device_work); 241 INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
159 if (!dev->poll_interval) 242 if (!dev->poll_interval)
160 dev->poll_interval = 500; 243 dev->poll_interval = 500;
244 if (!dev->poll_interval_max)
245 dev->poll_interval_max = dev->poll_interval;
161 input->open = input_open_polled_device; 246 input->open = input_open_polled_device;
162 input->close = input_close_polled_device; 247 input->close = input_close_polled_device;
163 248
164 return input_register_device(input); 249 error = input_register_device(input);
250 if (error)
251 return error;
252
253 error = sysfs_create_group(&input->dev.kobj,
254 &input_polldev_attribute_group);
255 if (error) {
256 input_unregister_device(input);
257 return error;
258 }
259
260 return 0;
165} 261}
166EXPORT_SYMBOL(input_register_polled_device); 262EXPORT_SYMBOL(input_register_polled_device);
167 263
@@ -177,6 +273,9 @@ EXPORT_SYMBOL(input_register_polled_device);
177 */ 273 */
178void input_unregister_polled_device(struct input_polled_dev *dev) 274void input_unregister_polled_device(struct input_polled_dev *dev)
179{ 275{
276 sysfs_remove_group(&dev->input->dev.kobj,
277 &input_polldev_attribute_group);
278
180 input_unregister_device(dev->input); 279 input_unregister_device(dev->input);
181 dev->input = NULL; 280 dev->input = NULL;
182} 281}