linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] gpio-keys debouncing support
@ 2008-03-19 22:13 Dmitry Baryshkov
  2008-04-21 14:40 ` Dmitry Baryshkov
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Baryshkov @ 2008-03-19 22:13 UTC (permalink / raw)
  To: linux-input; +Cc: dtor

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@gmail.com>
---
 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


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] gpio-keys debouncing support
  2008-03-19 22:13 [PATCH] gpio-keys debouncing support Dmitry Baryshkov
@ 2008-04-21 14:40 ` Dmitry Baryshkov
  2008-04-21 15:55   ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Baryshkov @ 2008-04-21 14:40 UTC (permalink / raw)
  To: linux-input; +Cc: dtor

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@gmail.com>
> ---
>  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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] gpio-keys debouncing support
  2008-04-21 14:40 ` Dmitry Baryshkov
@ 2008-04-21 15:55   ` Dmitry Torokhov
  2008-04-22  1:14     ` Dmitry Baryshkov
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Torokhov @ 2008-04-21 15:55 UTC (permalink / raw)
  To: Dmitry Baryshkov; +Cc: linux-input

Hi Dmitry,

On Mon, Apr 21, 2008 at 06:40:19PM +0400, Dmitry Baryshkov wrote:
> Hi,
> 
> What about this patch? I still got no comments.
> 

I thought I CCed you form slightly different thread. I don't think that
this should be a separate Kconfig option, we shoudl make it permanent
in the driver. I also wonder if it would be better to allocate debounce
data once for all buttons instead of nickel-and-dime-ing memory
allocator with tiny requests. Timer shoudl be moved into debounce data
too BTW.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] gpio-keys debouncing support
  2008-04-21 15:55   ` Dmitry Torokhov
@ 2008-04-22  1:14     ` Dmitry Baryshkov
  2008-04-26 19:14       ` Dmitry Baryshkov
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Baryshkov @ 2008-04-22  1:14 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

Hi,

On Mon, Apr 21, 2008 at 11:55:16AM -0400, Dmitry Torokhov wrote:
> Hi Dmitry,
> 
> On Mon, Apr 21, 2008 at 06:40:19PM +0400, Dmitry Baryshkov wrote:
> > Hi,
> > 
> > What about this patch? I still got no comments.
> > 
> 
> I thought I CCed you form slightly different thread. I don't think that
> this should be a separate Kconfig option, we shoudl make it permanent
> in the driver. I also wonder if it would be better to allocate debounce
> data once for all buttons instead of nickel-and-dime-ing memory
> allocator with tiny requests. Timer shoudl be moved into debounce data
> too BTW.

Please review the updated patch:

>From acf6027db75bca502d1baf45e48418ddb7aadcb7 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Tue, 22 Apr 2008 05:12:07 +0400
Subject: [PATCH] gpio-keys debouncing support

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 drivers/input/keyboard/gpio_keys.c |  102 ++++++++++++++++++++++++++++++++---
 include/linux/gpio_keys.h          |    2 +
 2 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 6a9ca4b..33901e4 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -26,23 +26,72 @@
 
 #include <asm/gpio.h>
 
+struct gpio_button_data {
+	struct platform_device *pdev;
+	struct gpio_keys_button *button;
+
+	/* For debounce */
+	int state;
+	int count;
+	struct timer_list	timer;
+};
+
+struct gpio_keys_drvdata {
+	struct input_dev *input;
+	struct gpio_button_data data[0];
+};
+
+static void gpio_debounce_timer(unsigned long _data)
+{
+	struct gpio_button_data *data = (struct gpio_button_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 gpio_keys_drvdata *ddata = platform_get_drvdata(data->pdev);
+	struct input_dev *input = ddata->input;
+
+	if (state != data->state) {
+		data->count = 0;
+		data->state = state;
+		mod_timer(&data->timer, jiffies +
+					msecs_to_jiffies(button->interval));
+	} else if (data->count < button->count) {
+		data->count ++;
+		mod_timer(&data->timer, jiffies +
+					msecs_to_jiffies(button->interval));
+	} else {
+		input_event(input, type, button->code, !!state);
+		input_sync(input);
+	}
+}
+
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
 	int i;
 	struct platform_device *pdev = dev_id;
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-	struct input_dev *input = platform_get_drvdata(pdev);
+	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+	struct input_dev *input = ddata->input;
 
 	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button *button = &pdata->buttons[i];
+		struct gpio_button_data *data = &ddata->data[i];
 		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;
-
-			input_event(input, type, button->code, !!state);
-			input_sync(input);
+			if (button->count) {
+				if (!timer_pending(&data->timer))
+					mod_timer(&data->timer, jiffies +
+							msecs_to_jiffies(
+							button->interval));
+			} else {
+				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);
+			}
 		}
 	}
 
@@ -52,15 +101,26 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_keys_drvdata *ddata;
 	struct input_dev *input;
 	int i, error;
 	int wakeup = 0;
 
+	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
+			sizeof(struct gpio_button_data) * pdata->nbuttons,
+			GFP_KERNEL);
+
+	if (!ddata)
+		return -ENOMEM;
+
 	input = input_allocate_device();
-	if (!input)
+	if (!input) {
+		kfree(ddata);
 		return -ENOMEM;
+	}
+	ddata->input = input;
 
-	platform_set_drvdata(pdev, input);
+	platform_set_drvdata(pdev, ddata);
 
 	input->evbit[0] = BIT_MASK(EV_KEY);
 
@@ -77,6 +137,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 		struct gpio_keys_button *button = &pdata->buttons[i];
 		int irq;
 		unsigned int type = button->type ?: EV_KEY;
+		struct gpio_button_data *data = &ddata->data[i];
+
+		data->pdev = pdev;
+		data->button = button;
 
 		error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
 		if (error < 0) {
@@ -103,6 +167,16 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 			gpio_free(button->gpio);
 			goto fail;
 		}
+		if (button->count && button->interval) {
+			data->state = -1;
+
+			init_timer(&data->timer);
+			data->timer.function = gpio_debounce_timer;
+			data->timer.data = (unsigned long)data;
+
+			mod_timer(&data->timer, jiffies +
+					msecs_to_jiffies(button->interval));
+		}
 
 		error = request_irq(irq, gpio_keys_isr,
 				    IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
@@ -112,7 +186,10 @@ 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);
+			if (button->count)
+				del_timer_sync(&data->timer);
 			gpio_free(button->gpio);
+
 			goto fail;
 		}
 
@@ -136,11 +213,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail:
 	while (--i >= 0) {
 		free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+		if (pdata->buttons[i].count) {
+			del_timer_sync(&ddata->data[i].timer);
+		}
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
 	platform_set_drvdata(pdev, NULL);
 	input_free_device(input);
+	kfree(ddata);
 
 	return error;
 }
@@ -148,7 +229,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-	struct input_dev *input = platform_get_drvdata(pdev);
+	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+	struct input_dev *input = ddata->input;
 	int i;
 
 	device_init_wakeup(&pdev->dev, 0);
@@ -156,6 +238,8 @@ 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);
+		if (pdata->buttons[i].count)
+			del_timer_sync(&ddata->data[i].timer);
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index c6d3a9d..5d09862 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -9,6 +9,8 @@ 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 */
+	int count;		/* debounce ticks count */
+	int interval;		/* debounce ticks interval in msecs */
 };
 
 struct gpio_keys_platform_data {
-- 
1.5.5


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] gpio-keys debouncing support
  2008-04-22  1:14     ` Dmitry Baryshkov
@ 2008-04-26 19:14       ` Dmitry Baryshkov
  0 siblings, 0 replies; 5+ messages in thread
From: Dmitry Baryshkov @ 2008-04-26 19:14 UTC (permalink / raw)
  To: linux-input

Hi,

Dmitry Baryshkov wrote:

> Hi,
> 
> On Mon, Apr 21, 2008 at 11:55:16AM -0400, Dmitry Torokhov wrote:
>> Hi Dmitry,
>> 
>> On Mon, Apr 21, 2008 at 06:40:19PM +0400, Dmitry Baryshkov wrote:
>> > Hi,
>> > 
>> > What about this patch? I still got no comments.
>> > 
>> > 
>> I thought I CCed you form slightly different thread. I don't think that
>> this should be a separate Kconfig option, we shoudl make it permanent
>> in the driver. I also wonder if it would be better to allocate debounce
>> data once for all buttons instead of nickel-and-dime-ing memory
>> allocator with tiny requests. Timer shoudl be moved into debounce data
>> too BTW.
> 
> Please review the updated patch:
> 
> From acf6027db75bca502d1baf45e48418ddb7aadcb7 Mon Sep 17 00:00:00 2001
> From: Dmitry Baryshkov <dbaryshkov@gmail.com>
> Date: Tue, 22 Apr 2008 05:12:07 +0400
> Subject: [PATCH] gpio-keys debouncing support
> 

So, what about this patch?

-- 
With best wishes
Dmitry



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-04-26 19:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-19 22:13 [PATCH] gpio-keys debouncing support Dmitry Baryshkov
2008-04-21 14:40 ` Dmitry Baryshkov
2008-04-21 15:55   ` Dmitry Torokhov
2008-04-22  1:14     ` Dmitry Baryshkov
2008-04-26 19:14       ` Dmitry Baryshkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).