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