[OpenWrt-Devel] [PATCH v2] gpio-button-hotplug: mind debounce interval consistently

Christian Lamparter chunkeey at gmail.com
Thu Jun 20 11:21:54 EDT 2019


On Tuesday, June 18, 2019 1:06:12 PM CEST David Bauer wrote:
> This patch implements consistent handling of the debounce interval set
> for the GPIO buttons. Hotplug events will only be fired if
> 
> 1. It's the initial stable state (no state-change for duration of the
> debounce interval) for a switch. Buttons will not trigger an event for
> the initial stable state.
> 
> 2. The input changes it's state and remains stable for the debounce
> interval.
> 
> Prior to this patch, this was handled inconsistently for interrupt-based
> an polled gpio-keys. We unify the shared logic in button_hotplug_event
> and modify both implementations to read the initial state.
> 
> Run-tested for 'gpio-keys' and 'gpio-keys-polled' on
> 
>  - devolo WiFi pro 1200e
>  - devolo WiFi pro 1750c
>  - devolo WiFi pro 1750x
> 
> Signed-off-by: David Bauer <mail at david-bauer.net>
> ---
>  .../src/gpio-button-hotplug.c                 | 42 +++++++++----------
>  1 file changed, 20 insertions(+), 22 deletions(-)
> 
> diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
> index e63d414284..25150344e0 100644
> --- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
> +++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
> @@ -241,6 +241,7 @@ static int button_get_index(unsigned int code)
>  static void button_hotplug_event(struct gpio_keys_button_data *data,
>  			   unsigned int type, int value)
>  {
> +	int last_state = data->last_state;
>  	struct bh_priv *priv = &data->bh;
>  	unsigned long seen = jiffies;
>  	int btn;
> @@ -250,6 +251,14 @@ static void button_hotplug_event(struct gpio_keys_button_data *data,
>  	if ((type != EV_KEY) && (type != EV_SW))
>  		return;
>  
> +	if (value == last_state)
> +		return;
> +
> +	data->last_state = value;
> +
> +	if (last_state == -1 && type != EV_SW)
> +		return;
> +
>  	btn = button_get_index(data->b->code);
>  	if (btn < 0)
>  		return;
> @@ -285,22 +294,14 @@ static int gpio_button_get_value(struct gpio_keys_button_data *bdata)
>  
>  static void gpio_keys_polled_check_state(struct gpio_keys_button_data *bdata)
>  {
> -	int state = gpio_button_get_value(bdata);
> -
> -	if (state != bdata->last_state) {
> -		unsigned int type = bdata->b->type ?: EV_KEY;
> -
> -		if (bdata->count < bdata->threshold) {
> -			bdata->count++;
> -			return;
> -		}
> -
> -		if (bdata->last_state != -1 || type == EV_SW)
> -			button_hotplug_event(bdata, type, state);
> -
> -		bdata->last_state = state;
> +	if (bdata->count < bdata->threshold) {
> +		bdata->count++;
> +		return;
>  	}
>  
> +	button_hotplug_event(bdata, bdata->b->type ?: EV_KEY,
> +				gpio_button_get_value(bdata));
> +
>  	bdata->count = 0;
>  }
Doesn't this change the logic of the gpio-key-polled software-debounce
a bit too aggressivly?

Previously, for the button event to happen the button new state had to
be stable for bdata->threshold counts.

Whereas now, bdata->count is counted upwards on every "tick" and once
bdata->count == bdata->threshold matches the "current state" gets passed
on. This seems that it would interfere with the debounce since a signal
doesn't have to be asserted stable for the whole duration now, instead
it now just has to show up "just before" the
bdata->count == bdata->threshold tick in order to be noticed. 

> @@ -351,8 +352,8 @@ static irqreturn_t button_handle_irq(int irq, void *_bdata)
>  	struct gpio_keys_button_data *bdata =
>  		(struct gpio_keys_button_data *) _bdata;
>  
> -	schedule_delayed_work(&bdata->work,
> -			      msecs_to_jiffies(bdata->software_debounce));
> +	mod_delayed_work(system_wq, &bdata->work,
> +			 msecs_to_jiffies(bdata->software_debounce));
>  
>  	return IRQ_HANDLED;
>  }
> @@ -608,6 +609,9 @@ static int gpio_keys_probe(struct platform_device *pdev)
>  
>  		INIT_DELAYED_WORK(&bdata->work, gpio_keys_irq_work_func);
>  
> +		schedule_delayed_work(&bdata->work,
> +				      msecs_to_jiffies(bdata->software_debounce));
> +
Hm, well since the first state is -1 we could just as well schedule the work
immediately here... 

>  		ret = devm_request_threaded_irq(&pdev->dev,
>  			bdata->irq, NULL, button_handle_irq,
>  			irqflags, dev_name(&pdev->dev), bdata);
> @@ -621,9 +625,6 @@ static int gpio_keys_probe(struct platform_device *pdev)
>  			dev_dbg(&pdev->dev, "gpio:%d has irq:%d\n",
>  				button->gpio, bdata->irq);
>  		}
> -
> -		if (bdata->b->type == EV_SW)
> -			button_hotplug_event(bdata, EV_SW, gpio_button_get_value(bdata));
>  	}
>  
>  	return 0;
> @@ -648,9 +649,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
>  	if (pdata->enable)
>  		pdata->enable(bdev->dev);
>  
> -	for (i = 0; i < pdata->nbuttons; i++)
> -		gpio_keys_polled_check_state(&bdev->data[i]);
> -

...and leave this as is.
>  	gpio_keys_polled_queue_work(bdev);
>  
>  	return ret;
> 





_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list