1 #include <linux/module.h>
2 #include <linux/device.h>
3 #include <linux/platform_device.h>
4 #include <linux/gpio_event.h>
6 #define PREFIX "debounce: "
8 static int debounce_delay
= 15;
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
;
16 module_param(debounce_delay
, int, S_IRUSR
| S_IRGRP
| S_IROTH
);
17 MODULE_PARM_DESC(debounce_delay
, "debouncing delay (ms), default: 15");
19 static int find_ms2_dev(struct device
*dev
, void *data
)
21 if (!strncmp((char*)data
, dev_name(dev
), strlen((char*)data
))) {
22 printk(KERN_INFO PREFIX
"Found it\n");
28 static ssize_t
show_debounce_delay(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
33 return snprintf(buf
, PAGE_SIZE
, "%ld\n", (gpio_evmi
->debounce_delay
.tv
.nsec
/ NSEC_PER_MSEC
));
36 static void set_debounce_delay(long delay
)
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
);
45 if (gpio_evmi
->debounce_delay
.tv
.nsec
!= 0) {
46 if (!(gpio_evmi
->flags
& GPIOKPF_DEBOUNCE
)) {
47 printk(KERN_INFO PREFIX
"Activating debounce\n");
48 gpio_evmi
->flags
|= GPIOKPF_DEBOUNCE
;
51 if (gpio_evmi
->flags
& GPIOKPF_DEBOUNCE
) {
52 printk(KERN_INFO PREFIX
"Deactivating debounce\n");
53 gpio_evmi
->flags
&= ~GPIOKPF_DEBOUNCE
;
58 static ssize_t
store_debounce_delay(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
65 sscanf(buf
, "%ld", &delay
);
66 set_debounce_delay(delay
);
68 return strnlen(buf
, PAGE_SIZE
);
71 static ssize_t
show_settle_time(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
76 return snprintf(buf
, PAGE_SIZE
, "%ld\n", (gpio_evmi
->settle_time
.tv
.nsec
/ NSEC_PER_USEC
));
79 static ssize_t
store_settle_time(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
86 sscanf(buf
, "%ld", &delay
);
87 gpio_evmi
->settle_time
.tv
.nsec
= delay
* NSEC_PER_USEC
;
89 return strnlen(buf
, PAGE_SIZE
);
92 static ssize_t
show_poll_time(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
97 return snprintf(buf
, PAGE_SIZE
, "%ld\n", (gpio_evmi
->poll_time
.tv
.nsec
/ NSEC_PER_MSEC
));
100 static ssize_t
store_poll_time(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
107 sscanf(buf
, "%ld", &delay
);
108 gpio_evmi
->poll_time
.tv
.nsec
= delay
* NSEC_PER_MSEC
;
110 return strnlen(buf
, PAGE_SIZE
);
113 static ssize_t
show_flags(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
118 return snprintf(buf
, PAGE_SIZE
, "0x%x\n", gpio_evmi
->flags
);
121 static ssize_t
store_flags(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
128 sscanf(buf
, "0x%x", &flags
);
129 gpio_evmi
->flags
= flags
;
131 return strnlen(buf
, PAGE_SIZE
);
134 static DEVICE_ATTR(debounce_delay
, (S_IRUGO
| S_IWUGO
), &show_debounce_delay
, store_debounce_delay
);
135 static DEVICE_ATTR(settle_time
, (S_IRUGO
| S_IWUGO
), &show_settle_time
, store_settle_time
);
136 static DEVICE_ATTR(poll_time
, (S_IRUGO
| S_IWUGO
), &show_poll_time
, store_poll_time
);
137 static DEVICE_ATTR(flags
, (S_IRUGO
| S_IWUGO
), &show_flags
, store_flags
);
139 static void debounce_release(struct device
*dev
)
143 static struct device debounce_device
= {
144 .init_name
= "debounce",
145 .release
= debounce_release
,
148 static int __init
debounce_init(void)
150 struct device
*event_dev
= NULL
;
151 struct gpio_event_platform_data
*gpio_epd
;
152 struct gpio_event_info
*gpio_ei
;
155 printk(KERN_INFO PREFIX
"Searching for " GPIO_EVENT_DEV_NAME
"...\n");
157 event_dev
= device_find_child(&platform_bus
, GPIO_EVENT_DEV_NAME
, find_ms2_dev
);
158 if (event_dev
== NULL
)
161 gpio_epd
= (struct gpio_event_platform_data
*)event_dev
->platform_data
;
162 printk(KERN_INFO PREFIX
"And there is a %s connected...\n", gpio_epd
->name
);
163 if (strcmp(gpio_epd
->name
, "sholes-keypad"))
166 gpio_ei
= (struct gpio_event_info
*)gpio_epd
->info
[0];
167 gpio_evmi
= container_of(gpio_ei
, struct gpio_event_matrix_info
, info
);
169 err
= device_register(&debounce_device
);
174 err
= device_create_file(&debounce_device
, &dev_attr_debounce_delay
);
175 err
= device_create_file(&debounce_device
, &dev_attr_settle_time
);
176 err
= device_create_file(&debounce_device
, &dev_attr_poll_time
);
177 err
= device_create_file(&debounce_device
, &dev_attr_flags
);
179 printk(KERN_INFO PREFIX
"settle_time: %u\n", gpio_evmi
->settle_time
.tv
.nsec
);
180 printk(KERN_INFO PREFIX
"poll_time: %u\n", gpio_evmi
->poll_time
.tv
.nsec
);
181 printk(KERN_INFO PREFIX
"debounce_delay: %u\n", gpio_evmi
->debounce_delay
.tv
.nsec
);
182 printk(KERN_INFO PREFIX
"flags: 0x%x\n", gpio_evmi
->flags
);
184 old_debounce_delay
= gpio_evmi
->debounce_delay
;
185 old_settle_time
= gpio_evmi
->settle_time
;
186 old_poll_time
= gpio_evmi
->poll_time
;
187 old_flags
= gpio_evmi
->flags
;
189 set_debounce_delay(debounce_delay
);
191 gpio_evmi
->flags
&= ~GPIOKPF_REMOVE_SOME_PHANTOM_KEYS
;
193 printk(KERN_INFO PREFIX
"flags: 0x%x\n", gpio_evmi
->flags
);
198 static void __exit
debounce_exit(void)
201 if (gpio_evmi
->debounce_delay
.tv
.nsec
!= old_debounce_delay
.tv
.nsec
) {
202 printk(KERN_INFO PREFIX
"Restoring debounce_delay\n");
203 gpio_evmi
->debounce_delay
= old_debounce_delay
;
204 printk(KERN_INFO PREFIX
"debounce_delay: %u\n", gpio_evmi
->debounce_delay
.tv
.nsec
);
206 if (gpio_evmi
->flags
!= old_flags
) {
207 printk(KERN_INFO PREFIX
"Restoring flags\n");
208 gpio_evmi
->flags
= old_flags
;
209 printk(KERN_INFO PREFIX
"flags: 0x%x\n", gpio_evmi
->flags
);
211 gpio_evmi
->settle_time
= old_settle_time
;
212 gpio_evmi
->poll_time
= old_poll_time
;
214 device_remove_file(&debounce_device
, &dev_attr_debounce_delay
);
215 device_remove_file(&debounce_device
, &dev_attr_settle_time
);
216 device_remove_file(&debounce_device
, &dev_attr_poll_time
);
217 device_remove_file(&debounce_device
, &dev_attr_flags
);
218 device_unregister(&debounce_device
);
221 module_init(debounce_init
);
222 module_exit(debounce_exit
);
224 MODULE_LICENSE("GPL");
225 MODULE_AUTHOR("Michael Gernoth <michael@gernoth.net>");