]> git.zerfleddert.de Git - ms2-fixes/blob - debounce.c
a5138c3ec99ba1b1129e72b43d817d63d3e06d46
[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
6 #define PREFIX "debounce: "
7
8 static int debounce_delay = 15;
9
10 static unsigned old_flags = 0;
11 ktime_t old_debounce_delay;
12 ktime_t old_settle_time;
13 ktime_t old_poll_time;
14 static struct gpio_event_matrix_info *gpio_evmi = NULL;
15
16 module_param(debounce_delay, int, S_IRUSR | S_IRGRP | S_IROTH);
17 MODULE_PARM_DESC(debounce_delay, "debouncing delay (ms), default: 15");
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 static 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
36 static 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
45 #if 0
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 }
57 #endif
58 }
59
60 static 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
70 return count;
71 }
72
73 static 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
81 static 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
91 return count;
92 }
93
94 static 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
102 static 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
112 return count;
113 }
114
115 static 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
123 static 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);
131
132 printk(KERN_INFO PREFIX "flags: 0x%x\n", flags);
133
134 if (flags & GPIOKPF_DRIVE_INACTIVE)
135 return count;
136
137 gpio_evmi->flags = flags;
138
139 return count;
140 }
141
142 static 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);
148 }
149
150 static 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
168 static 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
176 static 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
194 static 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
202 static 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
220 static 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
228 static 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
246 static 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
254 static 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
272 static DEVICE_ATTR(debounce_delay, (S_IRUGO | S_IWUGO), show_debounce_delay, store_debounce_delay);
273 static DEVICE_ATTR(settle_time, (S_IRUGO | S_IWUGO), show_settle_time, store_settle_time);
274 static DEVICE_ATTR(poll_time, (S_IRUGO | S_IWUGO), show_poll_time, store_poll_time);
275 static DEVICE_ATTR(flags, (S_IRUGO), show_flags, store_flags);
276 static DEVICE_ATTR(debounce_flag, (S_IRUGO | S_IWUGO), show_debounce_flag, store_debounce_flag);
277 static DEVICE_ATTR(remove_some_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_remove_some_phantom_keys_flag, store_remove_some_phantom_keys_flag);
278 static DEVICE_ATTR(print_unmapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_unmapped_keys_flag, store_print_unmapped_keys_flag);
279 static DEVICE_ATTR(print_mapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_mapped_keys_flag, store_print_mapped_keys_flag);
280 static DEVICE_ATTR(print_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_print_phantom_keys_flag, store_print_phantom_keys_flag);
281
282 static void debounce_release(struct device *dev)
283 {
284 }
285
286 static struct device debounce_device = {
287 .init_name = "debounce",
288 .release = debounce_release,
289 };
290
291 static int __init debounce_init(void)
292 {
293 struct device *event_dev = NULL;
294 struct gpio_event_platform_data *gpio_epd;
295 struct gpio_event_info *gpio_ei;
296 int err = 0;
297
298 printk(KERN_INFO PREFIX "Searching for " GPIO_EVENT_DEV_NAME "...\n");
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;
305 printk(KERN_INFO PREFIX "And there is a %s connected...\n", gpio_epd->name);
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
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);
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);
326
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);
331
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;
336
337 set_debounce_delay(debounce_delay);
338
339 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
340
341 return 0;
342 }
343
344 static void __exit debounce_exit(void)
345 {
346 if (gpio_evmi) {
347 if (gpio_evmi->debounce_delay.tv.nsec != old_debounce_delay.tv.nsec) {
348 printk(KERN_INFO PREFIX "Restoring debounce_delay\n");
349 gpio_evmi->debounce_delay = old_debounce_delay;
350 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
351 }
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 }
357 gpio_evmi->settle_time = old_settle_time;
358 gpio_evmi->poll_time = old_poll_time;
359 }
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);
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);
369 device_unregister(&debounce_device);
370 }
371
372 module_init(debounce_init);
373 module_exit(debounce_exit);
374
375 MODULE_LICENSE("GPL");
376 MODULE_AUTHOR("Michael Gernoth <michael@gernoth.net>");
Impressum, Datenschutz