[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