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