add (disabled) fixup-handler
[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>
f4286301
MG
5#include <linux/interrupt.h>
6#include <linux/irq.h>
62a453fc
MG
7#include <mach/gpio.h>
8
ab5ed215
MG
9#define PREFIX "debounce: "
10
a4838b14 11static unsigned old_flags = 0;
29bad272
MG
12static ktime_t old_debounce_delay;
13static ktime_t old_settle_time;
14static ktime_t old_poll_time;
e063f9d5 15static int (*old_sw_fixup)(int index);
1e65c113 16static struct gpio_event_matrix_info *gpio_evmi = NULL;
29bad272
MG
17static int hw_debounce = 0;
18static int hw_debounce_time = 0;
1e65c113 19
ab5ed215 20static int find_ms2_dev(struct device *dev, void *data)
d1ff9643
MG
21{
22 if (!strncmp((char*)data, dev_name(dev), strlen((char*)data))) {
ab5ed215 23 printk(KERN_INFO PREFIX "Found it\n");
d1ff9643
MG
24 return 1;
25 }
26 return 0;
27}
b422e333 28
29bad272
MG
29/* hardware debounce: (time + 1) * 31us */
30static void hw_debounce_set(int enable, int time) {
31 int i;
32
33 if (gpio_evmi == NULL)
34 return;
35
36 for (i = 0; i < gpio_evmi->ninputs; i++) {
37 int gpio = gpio_evmi->input_gpios[i];
38
308fc1a5 39 if ((time != -1) && (time != hw_debounce_time) && hw_debounce) {
5df3a8e0 40 printk(KERN_INFO PREFIX "Setting hardware debounce time for GPIO %d to %d (%dus)\n", gpio, time, (time+1)*31);
29bad272
MG
41 omap_set_gpio_debounce_time(gpio, time);
42 }
308fc1a5
MG
43
44 if ((enable != -1) && (enable != hw_debounce)) {
45 printk(KERN_INFO PREFIX "%sabling hardware debounce for GPIO %d\n", (enable?"En":"Dis"), gpio);
46 omap_set_gpio_debounce(gpio, enable);
47 }
29bad272
MG
48 }
49}
50
f4286301
MG
51static void set_irq_types(void) {
52 int err;
53 unsigned int irq;
54 unsigned long type;
55 int i;
56
57 if (gpio_evmi == NULL)
58 return;
59
60 switch (gpio_evmi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
61 default:
62 type = IRQ_TYPE_EDGE_FALLING;
63 break;
64 case GPIOKPF_ACTIVE_HIGH:
65 type = IRQ_TYPE_EDGE_RISING;
66 break;
67 case GPIOKPF_LEVEL_TRIGGERED_IRQ:
68 type = IRQ_TYPE_LEVEL_LOW;
69 break;
70 case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
71 type = IRQ_TYPE_LEVEL_HIGH;
72 break;
73 }
74
75 printk(KERN_INFO PREFIX "Settinhg IRQ type to 0x%lx\n", type);
76
77 for (i = 0; i < gpio_evmi->ninputs; i++) {
78
79 err = irq = gpio_to_irq(gpio_evmi->input_gpios[i]);
80
81 if (err < 0)
82 return;
83
84 err = set_irq_type(irq, type);
85 }
86}
29bad272 87
f7cb07b2
MG
88static ssize_t show_debounce_delay(struct device *dev, struct device_attribute *attr, char *buf)
89{
90 if (!gpio_evmi)
91 return -ENODEV;
92
93 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->debounce_delay.tv.nsec / NSEC_PER_MSEC));
94}
95
96static void set_debounce_delay(long delay)
97{
98 if (gpio_evmi->debounce_delay.tv.nsec != delay * NSEC_PER_MSEC) {
99 printk(KERN_INFO PREFIX "Changing debounce_delay\n");
100 gpio_evmi->debounce_delay.tv.nsec = delay * NSEC_PER_MSEC;
f7cb07b2
MG
101 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
102 }
103
fc215caa 104#if 0
f7cb07b2
MG
105 if (gpio_evmi->debounce_delay.tv.nsec != 0) {
106 if (!(gpio_evmi->flags & GPIOKPF_DEBOUNCE)) {
107 printk(KERN_INFO PREFIX "Activating debounce\n");
108 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
109 }
110 } else {
111 if (gpio_evmi->flags & GPIOKPF_DEBOUNCE) {
112 printk(KERN_INFO PREFIX "Deactivating debounce\n");
113 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
114 }
115 }
fc215caa 116#endif
f7cb07b2
MG
117}
118
119static ssize_t store_debounce_delay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
120{
121 long int delay;
122
123 if (!gpio_evmi)
124 return -ENODEV;
125
126 sscanf(buf, "%ld", &delay);
127 set_debounce_delay(delay);
128
fc215caa 129 return count;
f7cb07b2
MG
130}
131
132static ssize_t show_settle_time(struct device *dev, struct device_attribute *attr, char *buf)
133{
134 if (!gpio_evmi)
135 return -ENODEV;
136
137 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->settle_time.tv.nsec / NSEC_PER_USEC));
138}
139
140static ssize_t store_settle_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
141{
142 long int delay;
143
144 if (!gpio_evmi)
145 return -ENODEV;
146
147 sscanf(buf, "%ld", &delay);
148 gpio_evmi->settle_time.tv.nsec = delay * NSEC_PER_USEC;
149
fc215caa 150 return count;
f7cb07b2
MG
151}
152
153static ssize_t show_poll_time(struct device *dev, struct device_attribute *attr, char *buf)
154{
155 if (!gpio_evmi)
156 return -ENODEV;
157
158 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->poll_time.tv.nsec / NSEC_PER_MSEC));
159}
160
161static ssize_t store_poll_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
162{
163 long int delay;
164
165 if (!gpio_evmi)
166 return -ENODEV;
167
168 sscanf(buf, "%ld", &delay);
169 gpio_evmi->poll_time.tv.nsec = delay * NSEC_PER_MSEC;
170
fc215caa 171 return count;
f7cb07b2
MG
172}
173
174static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
175{
176 if (!gpio_evmi)
177 return -ENODEV;
178
179 return snprintf(buf, PAGE_SIZE, "0x%x\n", gpio_evmi->flags);
180}
181
182static ssize_t store_flags(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
183{
184 unsigned flags;
185
186 if (!gpio_evmi)
187 return -ENODEV;
188
189 sscanf(buf, "0x%x", &flags);
fc215caa
MG
190
191 printk(KERN_INFO PREFIX "flags: 0x%x\n", flags);
192
f7cb07b2
MG
193 gpio_evmi->flags = flags;
194
fc215caa
MG
195 return count;
196}
197
198static ssize_t show_debounce_flag(struct device *dev, struct device_attribute *attr, char *buf)
199{
200 if (!gpio_evmi)
201 return -ENODEV;
202
203 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DEBOUNCE) ? 1 : 0);
f7cb07b2
MG
204}
205
fc215caa
MG
206static ssize_t store_debounce_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
207{
208 unsigned flag;
209
210 if (!gpio_evmi)
211 return -ENODEV;
212
213 sscanf(buf, "%u", &flag);
214
215 if (flag) {
216 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
217 } else {
218 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
219 }
220
221 return count;
222}
223
224static ssize_t show_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
225{
226 if (!gpio_evmi)
227 return -ENODEV;
228
229 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS) ? 1 : 0);
230}
231
232static ssize_t store_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
233{
234 unsigned flag;
235
236 if (!gpio_evmi)
237 return -ENODEV;
238
239 sscanf(buf, "%u", &flag);
240
241 if (flag) {
242 gpio_evmi->flags |= GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
243 } else {
244 gpio_evmi->flags &= ~GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
245 }
246
247 return count;
248}
249
250static ssize_t show_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
251{
252 if (!gpio_evmi)
253 return -ENODEV;
254
255 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS) ? 1 : 0);
256}
257
258static ssize_t store_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
259{
260 unsigned flag;
261
262 if (!gpio_evmi)
263 return -ENODEV;
264
265 sscanf(buf, "%u", &flag);
266
267 if (flag) {
268 gpio_evmi->flags |= GPIOKPF_PRINT_UNMAPPED_KEYS;
269 } else {
270 gpio_evmi->flags &= ~GPIOKPF_PRINT_UNMAPPED_KEYS;
271 }
272
273 return count;
274}
275
276static ssize_t show_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
277{
278 if (!gpio_evmi)
279 return -ENODEV;
280
281 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_MAPPED_KEYS) ? 1 : 0);
282}
283
284static ssize_t store_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
285{
286 unsigned flag;
287
288 if (!gpio_evmi)
289 return -ENODEV;
290
291 sscanf(buf, "%u", &flag);
292
293 if (flag) {
294 gpio_evmi->flags |= GPIOKPF_PRINT_MAPPED_KEYS;
295 } else {
296 gpio_evmi->flags &= ~GPIOKPF_PRINT_MAPPED_KEYS;
297 }
298
299 return count;
300}
301
302static ssize_t show_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
303{
304 if (!gpio_evmi)
305 return -ENODEV;
306
307 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_PHANTOM_KEYS) ? 1 : 0);
308}
309
310static ssize_t store_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
311{
312 unsigned flag;
313
314 if (!gpio_evmi)
315 return -ENODEV;
316
317 sscanf(buf, "%u", &flag);
318
319 if (flag) {
320 gpio_evmi->flags |= GPIOKPF_PRINT_PHANTOM_KEYS;
321 } else {
322 gpio_evmi->flags &= ~GPIOKPF_PRINT_PHANTOM_KEYS;
323 }
324
325 return count;
326}
327
a2485674
MG
328static ssize_t show_active_high_flag(struct device *dev, struct device_attribute *attr, char *buf)
329{
330 if (!gpio_evmi)
331 return -ENODEV;
332
333 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_ACTIVE_HIGH) ? 1 : 0);
334}
335
336static ssize_t store_active_high_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
337{
338 unsigned flag;
339
340 if (!gpio_evmi)
341 return -ENODEV;
342
343 sscanf(buf, "%u", &flag);
344
345 if (flag) {
346 gpio_evmi->flags |= GPIOKPF_ACTIVE_HIGH;
347 } else {
348 gpio_evmi->flags &= ~GPIOKPF_ACTIVE_HIGH;
349 }
350
f4286301
MG
351 set_irq_types();
352
353 return count;
354}
355
356static ssize_t show_level_triggered_irq_flag(struct device *dev, struct device_attribute *attr, char *buf)
357{
358 if (!gpio_evmi)
359 return -ENODEV;
360
361 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_LEVEL_TRIGGERED_IRQ) ? 1 : 0);
362}
363
364static ssize_t store_level_triggered_irq_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
365{
366 unsigned flag;
367
368 if (!gpio_evmi)
369 return -ENODEV;
370
371 sscanf(buf, "%u", &flag);
372
373 if (flag) {
374 gpio_evmi->flags |= GPIOKPF_LEVEL_TRIGGERED_IRQ;
375 } else {
376 gpio_evmi->flags &= ~GPIOKPF_LEVEL_TRIGGERED_IRQ;
377 }
378
379 set_irq_types();
380
a2485674
MG
381 return count;
382}
383
384static ssize_t show_drive_inactive_flag(struct device *dev, struct device_attribute *attr, char *buf)
385{
386 if (!gpio_evmi)
387 return -ENODEV;
388
389 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DRIVE_INACTIVE) ? 1 : 0);
390}
391
392static ssize_t store_drive_inactive_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
393{
394 unsigned flag;
395
396 if (!gpio_evmi)
397 return -ENODEV;
398
399 sscanf(buf, "%u", &flag);
400
401 if (flag) {
402 gpio_evmi->flags |= GPIOKPF_DRIVE_INACTIVE;
403 } else {
404 gpio_evmi->flags &= ~GPIOKPF_DRIVE_INACTIVE;
405 }
406
407 return count;
408}
409
29bad272
MG
410static ssize_t show_hw_debounce(struct device *dev, struct device_attribute *attr, char *buf)
411{
412 return snprintf(buf, PAGE_SIZE, "%d\n", hw_debounce);
413}
414
415static ssize_t store_hw_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
416{
417 int enable;
418
419 sscanf(buf, "%d", &enable);
420
421 if (enable) {
422 hw_debounce_set(1, -1);
423 hw_debounce = 1;
424 }
425 else {
c0cd650e 426 hw_debounce_set(-1, 0);
29bad272
MG
427 hw_debounce_set(0, -1);
428 hw_debounce = 0;
c0cd650e 429 hw_debounce_time = 0;
29bad272
MG
430 }
431
432 return count;
433}
434
435static ssize_t show_hw_debounce_time(struct device *dev, struct device_attribute *attr, char *buf)
436{
437 return snprintf(buf, PAGE_SIZE, "%d\n", hw_debounce_time);
438}
439
440static ssize_t store_hw_debounce_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
441{
442 int time;
443
444 sscanf(buf, "%d", &time);
445
446 if ((time < 0) || (time > 0xff))
447 return count;
448
8440ec7c
MG
449 if (!hw_debounce)
450 return count;
451
29bad272
MG
452 hw_debounce_set(-1, time);
453 hw_debounce_time = time;
454
455 return count;
456}
457
fc215caa
MG
458static DEVICE_ATTR(debounce_delay, (S_IRUGO | S_IWUGO), show_debounce_delay, store_debounce_delay);
459static DEVICE_ATTR(settle_time, (S_IRUGO | S_IWUGO), show_settle_time, store_settle_time);
460static DEVICE_ATTR(poll_time, (S_IRUGO | S_IWUGO), show_poll_time, store_poll_time);
461static DEVICE_ATTR(flags, (S_IRUGO), show_flags, store_flags);
462static DEVICE_ATTR(debounce_flag, (S_IRUGO | S_IWUGO), show_debounce_flag, store_debounce_flag);
463static DEVICE_ATTR(remove_some_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_remove_some_phantom_keys_flag, store_remove_some_phantom_keys_flag);
464static DEVICE_ATTR(print_unmapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_unmapped_keys_flag, store_print_unmapped_keys_flag);
465static DEVICE_ATTR(print_mapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_mapped_keys_flag, store_print_mapped_keys_flag);
466static DEVICE_ATTR(print_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_print_phantom_keys_flag, store_print_phantom_keys_flag);
60fe4255 467static DEVICE_ATTR(active_high_flag, (S_IRUGO | S_IWUGO), show_active_high_flag, store_active_high_flag);
f4286301 468static DEVICE_ATTR(level_triggered_irq_flag, (S_IRUGO | S_IWUGO), show_level_triggered_irq_flag, store_level_triggered_irq_flag);
a2485674 469static DEVICE_ATTR(drive_inactive_flag, (S_IRUGO | S_IWUGO), show_drive_inactive_flag, store_drive_inactive_flag);
29bad272
MG
470static DEVICE_ATTR(hw_debounce, (S_IRUGO | S_IWUGO), show_hw_debounce, store_hw_debounce);
471static DEVICE_ATTR(hw_debounce_time, (S_IRUGO | S_IWUGO), show_hw_debounce_time, store_hw_debounce_time);
f7cb07b2 472
e063f9d5
MG
473#if 0
474static int debounce_fixup(int index)
475{
476 int ret;
477
478 printk(KERN_INFO PREFIX "0x%x\n", index);
479
480 ret = old_sw_fixup(index);
481 if (!ret)
482 printk(KERN_INFO PREFIX "IGNORED!\n");
483
484 return ret;
485}
486#endif
487
f7cb07b2
MG
488static void debounce_release(struct device *dev)
489{
490}
491
492static struct device debounce_device = {
493 .init_name = "debounce",
494 .release = debounce_release,
495};
496
b422e333
MG
497static int __init debounce_init(void)
498{
d1ff9643
MG
499 struct device *event_dev = NULL;
500 struct gpio_event_platform_data *gpio_epd;
501 struct gpio_event_info *gpio_ei;
f7cb07b2 502 int err = 0;
d1ff9643 503
ab5ed215 504 printk(KERN_INFO PREFIX "Searching for " GPIO_EVENT_DEV_NAME "...\n");
d1ff9643
MG
505
506 event_dev = device_find_child(&platform_bus, GPIO_EVENT_DEV_NAME, find_ms2_dev);
507 if (event_dev == NULL)
508 return -ENODEV;
509
510 gpio_epd = (struct gpio_event_platform_data*)event_dev->platform_data;
ab5ed215 511 printk(KERN_INFO PREFIX "And there is a %s connected...\n", gpio_epd->name);
d1ff9643
MG
512 if (strcmp(gpio_epd->name, "sholes-keypad"))
513 return -ENODEV;
514
515 gpio_ei = (struct gpio_event_info*)gpio_epd->info[0];
516 gpio_evmi = container_of(gpio_ei, struct gpio_event_matrix_info, info);
517
f7cb07b2
MG
518 err = device_register(&debounce_device);
519 if (err) {
520 return err;
521 }
522
523 err = device_create_file(&debounce_device, &dev_attr_debounce_delay);
524 err = device_create_file(&debounce_device, &dev_attr_settle_time);
525 err = device_create_file(&debounce_device, &dev_attr_poll_time);
526 err = device_create_file(&debounce_device, &dev_attr_flags);
fc215caa
MG
527 err = device_create_file(&debounce_device, &dev_attr_debounce_flag);
528 err = device_create_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
529 err = device_create_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
530 err = device_create_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
531 err = device_create_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
a2485674 532 err = device_create_file(&debounce_device, &dev_attr_active_high_flag);
f4286301 533 err = device_create_file(&debounce_device, &dev_attr_level_triggered_irq_flag);
a2485674 534 err = device_create_file(&debounce_device, &dev_attr_drive_inactive_flag);
29bad272
MG
535 err = device_create_file(&debounce_device, &dev_attr_hw_debounce);
536 err = device_create_file(&debounce_device, &dev_attr_hw_debounce_time);
f7cb07b2 537
ab5ed215
MG
538 printk(KERN_INFO PREFIX "settle_time: %u\n", gpio_evmi->settle_time.tv.nsec);
539 printk(KERN_INFO PREFIX "poll_time: %u\n", gpio_evmi->poll_time.tv.nsec);
540 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
541 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
20bf1c9e 542
bb65757a
MG
543 old_debounce_delay = gpio_evmi->debounce_delay;
544 old_settle_time = gpio_evmi->settle_time;
545 old_poll_time = gpio_evmi->poll_time;
546 old_flags = gpio_evmi->flags;
e063f9d5 547 old_sw_fixup = gpio_evmi->sw_fixup;
1e65c113 548
e063f9d5
MG
549#if 0
550 printk(KERN_INFO PREFIX "Registering fixup handler\n");
551 gpio_evmi->sw_fixup = debounce_fixup;
552#endif
a4838b14 553
b422e333
MG
554 return 0;
555}
556
557static void __exit debounce_exit(void)
558{
1e65c113 559 if (gpio_evmi) {
bb65757a 560 if (gpio_evmi->debounce_delay.tv.nsec != old_debounce_delay.tv.nsec) {
1e65c113 561 printk(KERN_INFO PREFIX "Restoring debounce_delay\n");
bb65757a 562 gpio_evmi->debounce_delay = old_debounce_delay;
1e65c113
MG
563 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
564 }
a4838b14
MG
565 if (gpio_evmi->flags != old_flags) {
566 printk(KERN_INFO PREFIX "Restoring flags\n");
567 gpio_evmi->flags = old_flags;
568 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
f4286301 569 set_irq_types();
a4838b14 570 }
bb65757a
MG
571 gpio_evmi->settle_time = old_settle_time;
572 gpio_evmi->poll_time = old_poll_time;
e063f9d5
MG
573
574 if (gpio_evmi->sw_fixup != old_sw_fixup) {
575 printk(KERN_INFO PREFIX "Restoring fixup handler\n");
576 gpio_evmi->sw_fixup = old_sw_fixup;
577 }
1e65c113 578 }
29bad272 579 hw_debounce_set(0, 0);
f7cb07b2
MG
580 device_remove_file(&debounce_device, &dev_attr_debounce_delay);
581 device_remove_file(&debounce_device, &dev_attr_settle_time);
582 device_remove_file(&debounce_device, &dev_attr_poll_time);
583 device_remove_file(&debounce_device, &dev_attr_flags);
fc215caa
MG
584 device_remove_file(&debounce_device, &dev_attr_debounce_flag);
585 device_remove_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
586 device_remove_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
587 device_remove_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
588 device_remove_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
a2485674 589 device_remove_file(&debounce_device, &dev_attr_active_high_flag);
f4286301 590 device_remove_file(&debounce_device, &dev_attr_level_triggered_irq_flag);
a2485674 591 device_remove_file(&debounce_device, &dev_attr_drive_inactive_flag);
29bad272
MG
592 device_remove_file(&debounce_device, &dev_attr_hw_debounce);
593 device_remove_file(&debounce_device, &dev_attr_hw_debounce_time);
f7cb07b2 594 device_unregister(&debounce_device);
b422e333
MG
595}
596
597module_init(debounce_init);
598module_exit(debounce_exit);
599
600MODULE_LICENSE("GPL");
601MODULE_AUTHOR("Michael Gernoth <michael@gernoth.net>");
Impressum, Datenschutz