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

David Bauer mail at david-bauer.net
Thu Jun 20 14:10:18 EDT 2019


Hello Christian,

On 20.06.19 17:21, Christian Lamparter wrote:
> 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. 

You are right, i will rework this part.

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

Hmm, i have a bit trouble grasping your intention here.

Do you mean we can unify the scheduling for polled and interrupt-based keys?

Best wishes
David

>>  		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