Hi, What about this patch? I still got no comments. On Thu, Mar 20, 2008 at 01:13:23AM +0300, Dmitry Baryshkov wrote: > Sometimes the gpio line can generates jitter while transitioning > from one state to another. Implement a way to filter such noise during > transitions. > > Signed-off-by: Dmitry Baryshkov <dbaryshkov@xxxxxxxxx> > --- > drivers/input/keyboard/Kconfig | 7 +++ > drivers/input/keyboard/gpio_keys.c | 96 ++++++++++++++++++++++++++++++++++-- > include/linux/gpio_keys.h | 6 ++ > 3 files changed, 104 insertions(+), 5 deletions(-) > > diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig > index 8ea709b..0fb4592 100644 > --- a/drivers/input/keyboard/Kconfig > +++ b/drivers/input/keyboard/Kconfig > @@ -295,6 +295,13 @@ config KEYBOARD_GPIO > To compile this driver as a module, choose M here: the > module will be called gpio-keys. > > +config KEYBOARD_GPIO_DEBOUNCE > + bool "GPIO Buttons debouncer" > + depends on KEYBOARD_GPIO > + help > + This driver will enable the debouncer in the gpio-keys > + driver for pins that take some time to come to stable state. > + > config KEYBOARD_MAPLE > tristate "Maple bus keyboard" > depends on SH_DREAMCAST && MAPLE > diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c > index 6a9ca4b..577dfea 100644 > --- a/drivers/input/keyboard/gpio_keys.c > +++ b/drivers/input/keyboard/gpio_keys.c > @@ -26,6 +26,39 @@ > > #include <asm/gpio.h> > > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > +struct gpio_debounce_data { > + struct platform_device *pdev; > + struct gpio_keys_button *button; > + int state; > + int count; > +}; > + > +static void gpio_debounce_timer(unsigned long _data) > +{ > + struct gpio_debounce_data *data = (struct gpio_debounce_data *)_data; > + struct gpio_keys_button *button = data->button; > + int gpio = button->gpio; > + unsigned int type = button->type ?: EV_KEY; > + int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; > + struct input_dev *input = platform_get_drvdata(data->pdev); > + > + if (state != data->state) { > + data->count = 0; > + data->state = state; > + mod_timer(&button->timer, jiffies + > + msecs_to_jiffies(button->interval)); > + } else if (data->count < button->count) { > + data->count ++; > + mod_timer(&button->timer, jiffies + > + msecs_to_jiffies(button->interval)); > + } else { > + input_event(input, type, button->code, !!state); > + input_sync(input); > + } > +} > +#endif > + > static irqreturn_t gpio_keys_isr(int irq, void *dev_id) > { > int i; > @@ -38,11 +71,21 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) > int gpio = button->gpio; > > if (irq == gpio_to_irq(gpio)) { > - unsigned int type = button->type ?: EV_KEY; > - int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + if (button->count) { > + if (!timer_pending(&button->timer)) > + mod_timer(&button->timer, jiffies + > + msecs_to_jiffies( > + button->interval)); > + } else > +#endif > + { > + unsigned int type = button->type ?: EV_KEY; > + int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; > > - input_event(input, type, button->code, !!state); > - input_sync(input); > + input_event(input, type, button->code, !!state); > + input_sync(input); > + } > } > } > > @@ -103,6 +146,31 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) > gpio_free(button->gpio); > goto fail; > } > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + if (button->count && button->interval) { > + struct gpio_debounce_data *data; > + data = kzalloc(sizeof(struct gpio_debounce_data), GFP_KERNEL); > + if (!data) { > + error = -ENOMEM; > + pr_err("gpio-keys: Unable to allocate debounce data" > + " for GPIO %d, error %d\n", > + button->gpio, error); > + gpio_free(button->gpio); > + goto fail; > + } > + > + data->pdev = pdev; > + data->button = button; > + data->state = -1; > + > + init_timer(&button->timer); > + button->timer.function = gpio_debounce_timer; > + button->timer.data = (unsigned long)data; > + > + mod_timer(&button->timer, jiffies + > + msecs_to_jiffies(button->interval)); > + } > +#endif > > error = request_irq(irq, gpio_keys_isr, > IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | > @@ -112,6 +180,12 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) > if (error) { > pr_err("gpio-keys: Unable to claim irq %d; error %d\n", > irq, error); > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + if (button->count) { > + del_timer_sync(&button->timer); > + kfree((void*)button->timer.data); > + } > +#endif > gpio_free(button->gpio); > goto fail; > } > @@ -136,6 +210,12 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) > fail: > while (--i >= 0) { > free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + if (pdata->buttons[i].count) { > + del_timer_sync(&pdata->buttons[i].timer); > + kfree((void*)pdata->buttons[i].timer.data); > + } > +#endif > gpio_free(pdata->buttons[i].gpio); > } > > @@ -156,6 +236,12 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) > for (i = 0; i < pdata->nbuttons; i++) { > int irq = gpio_to_irq(pdata->buttons[i].gpio); > free_irq(irq, pdev); > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + if (pdata->buttons[i].count) { > + del_timer_sync(&pdata->buttons[i].timer); > + kfree((void*)pdata->buttons[i].timer.data); > + } > +#endif > gpio_free(pdata->buttons[i].gpio); > } > > diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h > index c6d3a9d..2432e62 100644 > --- a/include/linux/gpio_keys.h > +++ b/include/linux/gpio_keys.h > @@ -9,6 +9,12 @@ struct gpio_keys_button { > char *desc; > int type; /* input event type (EV_KEY, EV_SW) */ > int wakeup; /* configure the button as a wake-up source */ > +#ifdef CONFIG_KEYBOARD_GPIO_DEBOUNCE > + int count; > + int interval; /* in msecs */ > + /* private: */ > + struct timer_list timer; > +#endif > }; > > struct gpio_keys_platform_data { > -- > 1.5.4.3 > > > -- > With best wishes > Dmitry > -- With best wishes Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html