[PATCH] Filter key bouncing for more keys
Nelson
arhuaco at freaks-unidos.net
Tue Dec 30 08:22:21 CET 2008
From: Nelson Castillo <arhuaco at freaks-unidos.net>
This patch filters key bouncing. We store the state of
the buttons and only change it when we notice that at
least AUX_TIMER_CONSECUTIVE_EVENTS consecutive equal GPIO
reads occur.
This patch removes the function neo1973kbd_aux_irq and now
we use the default handler for the AUX button also.
Tested with : GTA02. We need to test with GTA01/GTA03.
Signed-off-by: Nelson Castillo <arhuaco at freaks-unidos.net>
---
drivers/input/keyboard/neo1973kbd.c | 130 ++++++++++++++++++-----------------
1 files changed, 68 insertions(+), 62 deletions(-)
diff --git a/drivers/input/keyboard/neo1973kbd.c b/drivers/input/keyboard/neo1973kbd.c
index 20f0a34..2c3595c 100644
--- a/drivers/input/keyboard/neo1973kbd.c
+++ b/drivers/input/keyboard/neo1973kbd.c
@@ -1,7 +1,7 @@
/*
* Keyboard driver for FIC Neo1973 GSM phone
*
- * (C) 2006-2007 by Openmoko, Inc.
+ * (C) 2006-2009 by Openmoko, Inc.
* Author: Harald Welte <laforge at openmoko.org>
* All rights reserved.
*
@@ -33,7 +33,6 @@ struct neo1973kbd {
struct input_dev *input;
struct device *cdev;
struct work_struct work;
- int aux_state;
int work_in_progress;
int hp_irq_count_in_work;
int hp_irq_count;
@@ -55,9 +54,15 @@ struct neo1973kbd_key {
irqreturn_t (*isr)(int irq, void *dev_id);
int irq;
int input_key;
+
+ /* the following are used to filter bouncing */
+ int last;
+ int last_count;
+ int state;
+ int noop_counter;
+ int active;
};
-static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev_id);
static irqreturn_t neo1973kbd_headphone_irq(int irq, void *dev_id);
static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id);
@@ -65,7 +70,7 @@ static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id);
static struct neo1973kbd_key keys[] = {
[NEO1973_KEY_AUX] = {
.name = "Neo1973 AUX button",
- .isr = neo1973kbd_aux_irq,
+ .isr = neo1973kbd_default_key_irq,
.input_key = KEY_PHONE,
},
[NEO1973_KEY_HOLD] = {
@@ -89,86 +94,87 @@ static struct neo1973kbd_key keys[] = {
},
};
-/* This timer section filters AUX button IRQ bouncing */
+/* This timer section filters button IRQ bouncing */
-static void aux_key_timer_f(unsigned long data);
+static void kbd_key_timer_f(unsigned long data);
-static struct timer_list aux_key_timer =
- TIMER_INITIALIZER(aux_key_timer_f, 0, 0);
+static struct timer_list kbd_key_timer =
+ TIMER_INITIALIZER(kbd_key_timer_f, 0, 0);
-#define AUX_TIMER_TIMEOUT (HZ >> 7)
-#define AUX_TIMER_ALLOWED_NOOP 2
-#define AUX_TIMER_CONSECUTIVE_EVENTS 5
+#define KBD_TIMER_TIMEOUT (HZ >> 7)
+#define KBD_TIMER_ALLOWED_NOOP 2
+#define KBD_TIMER_CONSECUTIVE_EVENTS 5
struct neo1973kbd *timer_kbd;
-static void aux_key_timer_f(unsigned long data)
+static void kbd_key_timer_f(unsigned long data)
{
- static int noop_counter;
- static int last_key = -1;
- static int last_count;
- int key_pressed;
-
- key_pressed =
- !gpio_get_value(timer_kbd->pdev->resource[NEO1973_KEY_AUX].start);
- if (machine_is_neo1973_gta02())
- key_pressed = !key_pressed;
-
- if (likely(key_pressed == last_key))
- last_count++;
- else {
- last_count = 1;
- last_key = key_pressed;
- }
-
- if (unlikely(last_count >= AUX_TIMER_CONSECUTIVE_EVENTS)) {
- if (timer_kbd->aux_state != last_key) {
- input_report_key(timer_kbd->input, KEY_PHONE, last_key);
- input_sync(timer_kbd->input);
+ int n;
+ int nactive = 0;
- timer_kbd->aux_state = last_key;
- noop_counter = 0;
- }
- last_count = 0;
- if (unlikely(++noop_counter > AUX_TIMER_ALLOWED_NOOP)) {
- noop_counter = 0;
- return;
- }
- }
+ for (n = 0; n < ARRAY_SIZE(keys); n++) {
+ int key_pressed;
- mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
-}
+ if (!keys[n].active)
+ continue;
+ nactive++;
-static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev)
-{
- int *p = NULL;
+ key_pressed =
+ gpio_get_value(timer_kbd->pdev->resource[n].start);
- /* if you stall inside resume then AUX will force a panic,
- which in turn forces a dump of the pending syslog */
+ /* the only exception */
+ if (machine_is_neo1973_gta01() && n == NEO1973_KEY_AUX)
+ key_pressed = !key_pressed;
- if (global_inside_suspend)
- printk(KERN_ERR "death %d\n", *p);
+ if (likely(key_pressed == keys[n].last)) {
+ keys[n].last_count++;
+ } else {
+ keys[n].last_count = 1;
+ keys[n].last = key_pressed;
+ }
- mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
+ if (unlikely(keys[n].last_count >=
+ KBD_TIMER_CONSECUTIVE_EVENTS)) {
+ if (keys[n].state != keys[n].last) {
+ input_report_key(timer_kbd->input,
+ keys[n].input_key,
+ key_pressed);
+ input_sync(timer_kbd->input);
+ keys[n].state = keys[n].last;
+ keys[n].noop_counter = 0;
+ }
+ keys[n].last_count = 0;
+ if (unlikely(++keys[n].noop_counter >
+ KBD_TIMER_ALLOWED_NOOP)) {
+ keys[n].noop_counter = 0;
+ keys[n].active = 0;
+ }
+ }
+ }
- return IRQ_HANDLED;
+ if (nactive)
+ mod_timer(&kbd_key_timer, jiffies + KBD_TIMER_TIMEOUT);
}
static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id)
{
- struct neo1973kbd *kbd = dev_id;
int n;
-
for (n = 0; n < ARRAY_SIZE(keys); n++) {
+ if (irq == keys[n].irq) {
+ if (machine_is_neo1973_gta01() && global_inside_suspend
+ && NEO1973_KEY_AUX == n) {
+ /* if you stall inside resume then AUX will
+ * force a panic, which in turn forces a dump
+ * of the pending syslog */
+ int *p = NULL;
+ printk(KERN_ERR "death %d\n", *p);
+ }
- if (irq != keys[n].irq)
- continue;
-
- input_report_key(kbd->input, keys[n].input_key,
- gpio_get_value(kbd->pdev->resource[n].start));
- input_sync(kbd->input);
+ keys[n].active = 1;
+ mod_timer(&kbd_key_timer, jiffies + KBD_TIMER_TIMEOUT);
+ break;
+ }
}
-
return IRQ_HANDLED;
}
More information about the openmoko-kernel
mailing list