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 <m...@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@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to