split out flags
[ms2-fixes] / debounce.c
CommitLineData
b422e333 1#include <linux/module.h>
d1ff9643
MG
2#include <linux/device.h>
3#include <linux/platform_device.h>
4#include <linux/gpio_event.h>
5
ab5ed215
MG
6#define PREFIX "debounce: "
7
a4838b14 8static int debounce_delay = 15;
ab5ed215 9
a4838b14 10static unsigned old_flags = 0;
bb65757a
MG
11ktime_t old_debounce_delay;
12ktime_t old_settle_time;
13ktime_t old_poll_time;
1e65c113
MG
14static struct gpio_event_matrix_info *gpio_evmi = NULL;
15
b2b792eb 16module_param(debounce_delay, int, S_IRUSR | S_IRGRP | S_IROTH);
a4838b14 17MODULE_PARM_DESC(debounce_delay, "debouncing delay (ms), default: 15");
ab5ed215
MG
18
19static int find_ms2_dev(struct device *dev, void *data)
d1ff9643
MG
20{
21 if (!strncmp((char*)data, dev_name(dev), strlen((char*)data))) {
ab5ed215 22 printk(KERN_INFO PREFIX "Found it\n");
d1ff9643
MG
23 return 1;
24 }
25 return 0;
26}
b422e333 27
f7cb07b2
MG
28static ssize_t show_debounce_delay(struct device *dev, struct device_attribute *attr, char *buf)
29{
30 if (!gpio_evmi)
31 return -ENODEV;
32
33 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->debounce_delay.tv.nsec / NSEC_PER_MSEC));
34}
35
36static void set_debounce_delay(long delay)
37{
38 if (gpio_evmi->debounce_delay.tv.nsec != delay * NSEC_PER_MSEC) {
39 printk(KERN_INFO PREFIX "Changing debounce_delay\n");
40 gpio_evmi->debounce_delay.tv.nsec = delay * NSEC_PER_MSEC;
41 debounce_delay = delay;
42 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
43 }
44
fc215caa 45#if 0
f7cb07b2
MG
46 if (gpio_evmi->debounce_delay.tv.nsec != 0) {
47 if (!(gpio_evmi->flags & GPIOKPF_DEBOUNCE)) {
48 printk(KERN_INFO PREFIX "Activating debounce\n");
49 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
50 }
51 } else {
52 if (gpio_evmi->flags & GPIOKPF_DEBOUNCE) {
53 printk(KERN_INFO PREFIX "Deactivating debounce\n");
54 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
55 }
56 }
fc215caa 57#endif
f7cb07b2
MG
58}
59
60static ssize_t store_debounce_delay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
61{
62 long int delay;
63
64 if (!gpio_evmi)
65 return -ENODEV;
66
67 sscanf(buf, "%ld", &delay);
68 set_debounce_delay(delay);
69
fc215caa 70 return count;
f7cb07b2
MG
71}
72
73static ssize_t show_settle_time(struct device *dev, struct device_attribute *attr, char *buf)
74{
75 if (!gpio_evmi)
76 return -ENODEV;
77
78 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->settle_time.tv.nsec / NSEC_PER_USEC));
79}
80
81static ssize_t store_settle_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
82{
83 long int delay;
84
85 if (!gpio_evmi)
86 return -ENODEV;
87
88 sscanf(buf, "%ld", &delay);
89 gpio_evmi->settle_time.tv.nsec = delay * NSEC_PER_USEC;
90
fc215caa 91 return count;
f7cb07b2
MG
92}
93
94static ssize_t show_poll_time(struct device *dev, struct device_attribute *attr, char *buf)
95{
96 if (!gpio_evmi)
97 return -ENODEV;
98
99 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->poll_time.tv.nsec / NSEC_PER_MSEC));
100}
101
102static ssize_t store_poll_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
103{
104 long int delay;
105
106 if (!gpio_evmi)
107 return -ENODEV;
108
109 sscanf(buf, "%ld", &delay);
110 gpio_evmi->poll_time.tv.nsec = delay * NSEC_PER_MSEC;
111
fc215caa 112 return count;
f7cb07b2
MG
113}
114
115static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
116{
117 if (!gpio_evmi)
118 return -ENODEV;
119
120 return snprintf(buf, PAGE_SIZE, "0x%x\n", gpio_evmi->flags);
121}
122
123static ssize_t store_flags(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
124{
125 unsigned flags;
126
127 if (!gpio_evmi)
128 return -ENODEV;
129
130 sscanf(buf, "0x%x", &flags);
fc215caa
MG
131
132 printk(KERN_INFO PREFIX "flags: 0x%x\n", flags);
133
134 if (flags & GPIOKPF_DRIVE_INACTIVE)
135 return count;
136
f7cb07b2
MG
137 gpio_evmi->flags = flags;
138
fc215caa
MG
139 return count;
140}
141
142static ssize_t show_debounce_flag(struct device *dev, struct device_attribute *attr, char *buf)
143{
144 if (!gpio_evmi)
145 return -ENODEV;
146
147 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DEBOUNCE) ? 1 : 0);
f7cb07b2
MG
148}
149
fc215caa
MG
150static ssize_t store_debounce_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
151{
152 unsigned flag;
153
154 if (!gpio_evmi)
155 return -ENODEV;
156
157 sscanf(buf, "%u", &flag);
158
159 if (flag) {
160 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
161 } else {
162 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
163 }
164
165 return count;
166}
167
168static ssize_t show_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
169{
170 if (!gpio_evmi)
171 return -ENODEV;
172
173 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS) ? 1 : 0);
174}
175
176static ssize_t store_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
177{
178 unsigned flag;
179
180 if (!gpio_evmi)
181 return -ENODEV;
182
183 sscanf(buf, "%u", &flag);
184
185 if (flag) {
186 gpio_evmi->flags |= GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
187 } else {
188 gpio_evmi->flags &= ~GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
189 }
190
191 return count;
192}
193
194static ssize_t show_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
195{
196 if (!gpio_evmi)
197 return -ENODEV;
198
199 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS) ? 1 : 0);
200}
201
202static ssize_t store_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
203{
204 unsigned flag;
205
206 if (!gpio_evmi)
207 return -ENODEV;
208
209 sscanf(buf, "%u", &flag);
210
211 if (flag) {
212 gpio_evmi->flags |= GPIOKPF_PRINT_UNMAPPED_KEYS;
213 } else {
214 gpio_evmi->flags &= ~GPIOKPF_PRINT_UNMAPPED_KEYS;
215 }
216
217 return count;
218}
219
220static ssize_t show_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
221{
222 if (!gpio_evmi)
223 return -ENODEV;
224
225 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_MAPPED_KEYS) ? 1 : 0);
226}
227
228static ssize_t store_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
229{
230 unsigned flag;
231
232 if (!gpio_evmi)
233 return -ENODEV;
234
235 sscanf(buf, "%u", &flag);
236
237 if (flag) {
238 gpio_evmi->flags |= GPIOKPF_PRINT_MAPPED_KEYS;
239 } else {
240 gpio_evmi->flags &= ~GPIOKPF_PRINT_MAPPED_KEYS;
241 }
242
243 return count;
244}
245
246static ssize_t show_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
247{
248 if (!gpio_evmi)
249 return -ENODEV;
250
251 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_PHANTOM_KEYS) ? 1 : 0);
252}
253
254static ssize_t store_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
255{
256 unsigned flag;
257
258 if (!gpio_evmi)
259 return -ENODEV;
260
261 sscanf(buf, "%u", &flag);
262
263 if (flag) {
264 gpio_evmi->flags |= GPIOKPF_PRINT_PHANTOM_KEYS;
265 } else {
266 gpio_evmi->flags &= ~GPIOKPF_PRINT_PHANTOM_KEYS;
267 }
268
269 return count;
270}
271
272static DEVICE_ATTR(debounce_delay, (S_IRUGO | S_IWUGO), show_debounce_delay, store_debounce_delay);
273static DEVICE_ATTR(settle_time, (S_IRUGO | S_IWUGO), show_settle_time, store_settle_time);
274static DEVICE_ATTR(poll_time, (S_IRUGO | S_IWUGO), show_poll_time, store_poll_time);
275static DEVICE_ATTR(flags, (S_IRUGO), show_flags, store_flags);
276static DEVICE_ATTR(debounce_flag, (S_IRUGO | S_IWUGO), show_debounce_flag, store_debounce_flag);
277static DEVICE_ATTR(remove_some_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_remove_some_phantom_keys_flag, store_remove_some_phantom_keys_flag);
278static DEVICE_ATTR(print_unmapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_unmapped_keys_flag, store_print_unmapped_keys_flag);
279static DEVICE_ATTR(print_mapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_mapped_keys_flag, store_print_mapped_keys_flag);
280static DEVICE_ATTR(print_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_print_phantom_keys_flag, store_print_phantom_keys_flag);
f7cb07b2
MG
281
282static void debounce_release(struct device *dev)
283{
284}
285
286static struct device debounce_device = {
287 .init_name = "debounce",
288 .release = debounce_release,
289};
290
b422e333
MG
291static int __init debounce_init(void)
292{
d1ff9643
MG
293 struct device *event_dev = NULL;
294 struct gpio_event_platform_data *gpio_epd;
295 struct gpio_event_info *gpio_ei;
f7cb07b2 296 int err = 0;
d1ff9643 297
ab5ed215 298 printk(KERN_INFO PREFIX "Searching for " GPIO_EVENT_DEV_NAME "...\n");
d1ff9643
MG
299
300 event_dev = device_find_child(&platform_bus, GPIO_EVENT_DEV_NAME, find_ms2_dev);
301 if (event_dev == NULL)
302 return -ENODEV;
303
304 gpio_epd = (struct gpio_event_platform_data*)event_dev->platform_data;
ab5ed215 305 printk(KERN_INFO PREFIX "And there is a %s connected...\n", gpio_epd->name);
d1ff9643
MG
306 if (strcmp(gpio_epd->name, "sholes-keypad"))
307 return -ENODEV;
308
309 gpio_ei = (struct gpio_event_info*)gpio_epd->info[0];
310 gpio_evmi = container_of(gpio_ei, struct gpio_event_matrix_info, info);
311
f7cb07b2
MG
312 err = device_register(&debounce_device);
313 if (err) {
314 return err;
315 }
316
317 err = device_create_file(&debounce_device, &dev_attr_debounce_delay);
318 err = device_create_file(&debounce_device, &dev_attr_settle_time);
319 err = device_create_file(&debounce_device, &dev_attr_poll_time);
320 err = device_create_file(&debounce_device, &dev_attr_flags);
fc215caa
MG
321 err = device_create_file(&debounce_device, &dev_attr_debounce_flag);
322 err = device_create_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
323 err = device_create_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
324 err = device_create_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
325 err = device_create_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
f7cb07b2 326
ab5ed215
MG
327 printk(KERN_INFO PREFIX "settle_time: %u\n", gpio_evmi->settle_time.tv.nsec);
328 printk(KERN_INFO PREFIX "poll_time: %u\n", gpio_evmi->poll_time.tv.nsec);
329 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
330 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
20bf1c9e 331
bb65757a
MG
332 old_debounce_delay = gpio_evmi->debounce_delay;
333 old_settle_time = gpio_evmi->settle_time;
334 old_poll_time = gpio_evmi->poll_time;
335 old_flags = gpio_evmi->flags;
1e65c113 336
f7cb07b2 337 set_debounce_delay(debounce_delay);
fc215caa 338
a4838b14
MG
339 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
340
b422e333
MG
341 return 0;
342}
343
344static void __exit debounce_exit(void)
345{
1e65c113 346 if (gpio_evmi) {
bb65757a 347 if (gpio_evmi->debounce_delay.tv.nsec != old_debounce_delay.tv.nsec) {
1e65c113 348 printk(KERN_INFO PREFIX "Restoring debounce_delay\n");
bb65757a 349 gpio_evmi->debounce_delay = old_debounce_delay;
1e65c113
MG
350 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
351 }
a4838b14
MG
352 if (gpio_evmi->flags != old_flags) {
353 printk(KERN_INFO PREFIX "Restoring flags\n");
354 gpio_evmi->flags = old_flags;
355 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
356 }
bb65757a
MG
357 gpio_evmi->settle_time = old_settle_time;
358 gpio_evmi->poll_time = old_poll_time;
1e65c113 359 }
f7cb07b2
MG
360 device_remove_file(&debounce_device, &dev_attr_debounce_delay);
361 device_remove_file(&debounce_device, &dev_attr_settle_time);
362 device_remove_file(&debounce_device, &dev_attr_poll_time);
363 device_remove_file(&debounce_device, &dev_attr_flags);
fc215caa
MG
364 device_remove_file(&debounce_device, &dev_attr_debounce_flag);
365 device_remove_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
366 device_remove_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
367 device_remove_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
368 device_remove_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
f7cb07b2 369 device_unregister(&debounce_device);
b422e333
MG
370}
371
372module_init(debounce_init);
373module_exit(debounce_exit);
374
375MODULE_LICENSE("GPL");
376MODULE_AUTHOR("Michael Gernoth <michael@gernoth.net>");
Impressum, Datenschutz