[PATCH libinput 0/1] Fix debouncing algorithm
Vicente Bergas
vicencb at gmail.com
Wed Nov 1 23:34:01 UTC 2017
Hi Peter,
>Hi Vicente
>
>sorry about the delay, too many things on right now.
Thank you for taking the time to review the patch.
>...
>Note: the current algorithm does ignore spurious actions, at least after the
>very first one. AIUI it's not that uncommon either when the contacts are
>wobbly. So removing it means we re-introduce bugs, you'll have to modify
>your patch to fit in addition to the current one.
For this reason I suggested (below) making the DEBOUNCE_AFTER macro a
configurable parameter. When it is set to true then it also filters out
spurious events, as explained in the next paragraph.
In any case, this new patch enables the debounce_after mode dynamically, so,
feature wise, will be equivalent to the current version.
>> There is a macro named DEBOUNCE_AFTER that changes the algorithm in a way
>> that events are committed after noise suppression. In that mode it is
>> well suited for both misbehaviours of the button. The drawback is that
>> there is a delay in that mode, so, it is not enabled by default.
>> ...
>> src/evdev-fallback.c | 158 +++++++++++++++------------------------------------
>> src/evdev.h | 19 -------
>> 2 files changed, 45 insertions(+), 132 deletions(-)
>
>I generally worry when I see significant changes to src but nothing in
>test :) and indeed, most (all?) button debouncing tests fail now. and there
>are no new tests for the various new behaviours. we definitely need those
>before we can merge it.
I hope it is fixed, but not been able to run the test-suite.
Please, can you confirm if the new test-suite passes?
>> ...
>> +/* Commit an event before or after DEBOUNCE_TIME
>> + * before: events are notified without any delay
>> + * spurious events are also notified
>> + * after: events are notified after a delay
>> + * spurious events are filtered out
>> + */
>> +#define DEBOUNCE_AFTER false
>
>definitive no to this bit. Use an enum, it makes the code a lot more
>readable, especially because you're mixing the boolean value and the
>human-readable DEBOUNCE_AFTER. I recommend using an enum with the first enum
>value not being 0, it avoids the fake boolean temptation.
Fixed.
>> ...
>> struct {
>> - enum evdev_debounce_state state;
>> + bool cancel_noise;
>> + bool first_value;
>> + bool last_value;
>> unsigned int button_code;
>> - uint64_t button_up_time;
>> + uint64_t button_time;
>> struct libinput_timer timer;
>> } debounce;
>>
>> @@ -639,22 +650,24 @@ static inline void
>> fallback_flush_debounce(struct fallback_dispatch *dispatch,
>> struct evdev_device *device)
>> {
>
>this function needs to check for cancel_noise == true and return early if
>that's not the case. we can't guarantee that the timer won't be called after
>an event has already cancelled it.
Fixed.
>> ...
>> + bool last_value = dispatch->debounce.last_value;
>
>whoah,
please, be more respectful, what you claim is going on here is not a reason
for that exclamation.
>you're secretly changing int to bool here. this needs to be more
>expressive like e.g.
> bool is_down = !!dispatch->debounce.last_value;
>
>you can't just change the type, herein lays mayhem.
your claim is incorrect, the local variable last_value is of type bool and
the variable dispatch->debounce.last_value is of the same type.
That applied further below, but not here.
Does that also apply when an int is used as a boolean condition in an if
statement or the ternary operator?
>> ...
>> + if (DEBOUNCE_AFTER !=
>> + (dispatch->debounce.first_value != last_value)
>
>the DEBOUNCE_AFTER is a #define, so you're effectively just checking if the
>first value != last value or something here (a double negation like this
>makes my brain go fuzzy). I actually had to write this out, it reads as:
> if (false != (first_value != last_value))
>which may be the most confusing way to write this condition :)
>and again, you have a #define but then use the readable name of it. Either
>you use a boolean and make the code so that it's self-explanatory or you use
>an enum.
Re-written in a more understandable way.
>> ...
>> + int code = dispatch->debounce.button_code;
>
>empty line after declarations please, and watch out for alignments and
>function arguments (one per line where multiple lines are needed). See
>CODING_STYLE.
Fixed.
>> ...
>> + evdev_log_debug(device, "debounce ignore %u\n", last_value);
>
>In regards to debug messages: these need to be prefixed so we can grep for
>it (the touchpad code e.g. uses things like "pressure:", "thumb state",
>etc.) But I'd say for the debouncing code only ever log when anything kicks
>in and we're filtering or otherwise modifying an event. Drop the rest so it
>doesn't get too confusing and it stands out more when something actually
>happens.
>
>Also note that the debug messages will be seen by users searching for a bug
>so they need to be good readable. 'debounce commit 1' doesn't explain much.
Dropped all messages that were not there before.
>Finally here: value is a signed integer in the event and should be kept at
>that, even if we only ever expect 0/1 as values.
Fixed. That removes the "int to bool mayhem"
>> ...
>> + if (dispatch->debounce.cancel_noise) {
>> + /* Flush if a button is pressed while holding back another one */
>
>indentation, one tab in please.
Fixed.
>> ...
>> - evdev_log_info(device,
>> - "Enabling button debouncing, "
>> - "see %sbutton_debouncing.html for details\n",
>> - HTTP_DOC_LINK);
>
>you should really log this the first time the debouncing kicks in so there's
>some reference in the logs that we're messing with button events now.
This algorithm was intended to be user configurable once the DEBOUNCE_AFTER
macro was converted to a parameter, so, there was no need to enable it
dynamically and printing this message.
Personally I would prefer it as a configuration parameter, but not a
deal-breaker. Because you prefer it automagically enabled, the new version
restores the dynamic behaviour and this message.
>> ...
>> + evdev_log_debug(device, "debounce noise %u %8lu\n",
>> + e->value, time - dispatch->debounce.button_time);
>
>use us2ms() here, no-one cares about microseconds granularity here. That
>also means you don't have to use PRIu64, %lu isn't reliably a uint64.
Fixed. (removed)
>> ...
>> + libinput_timer_set(&dispatch->debounce.timer, time + DEBOUNCE_TIME);
>> + return DEBOUNCE_AFTER;
>
>empty line before return, goes for all of the hunks in this patch.
>same with an empty line after a } to close the block.
Fixed.
>Cheers,
> Peter
Thanks for the review!
Regards,
Vicente.
More information about the wayland-devel
mailing list