From: Nelson Castillo <[email protected]>

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 <[email protected]>
---

 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 <[email protected]>
  * 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;
 }
 


Reply via email to