mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 14:48:09 +02:00
quirks: allow tweaking the debounce timeouts
Add `AttrBouncingTimeoutMs` and `AttrBouncingTimeoutSpuriousMs` to allow quirks to change the debounce timeouts. The goal is to allow users to workaround defective hardware by increasing `AttrBouncingTimeoutMs` enough for what they observe.
This commit is contained in:
parent
e68d80b13b
commit
a1710d870c
7 changed files with 89 additions and 8 deletions
|
|
@ -54,3 +54,27 @@ correspond to the buttons 'pressed' and 'released' states, respectively.
|
||||||
Some devices send events in bursts, erroneously triggering the button
|
Some devices send events in bursts, erroneously triggering the button
|
||||||
debouncing detection. Please :ref:`file a bug <reporting_bugs>` if that
|
debouncing detection. Please :ref:`file a bug <reporting_bugs>` if that
|
||||||
occurs for your device.
|
occurs for your device.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Configuration (via Quirks)
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.. warning:: Quirks are an internal API, they come with no
|
||||||
|
backwards-compatibility guarantees or support for configuration.
|
||||||
|
Read the full :ref:`device-quirks` section before using.
|
||||||
|
Do NOT try to upstream your debouncing timeouts!
|
||||||
|
|
||||||
|
It is possible to configure the timeouts used by both debouncing methods with
|
||||||
|
quirks.
|
||||||
|
Use ``libinput record`` to figure out the timing of bounced events.
|
||||||
|
Then increase the "bounce" timeout quirk to be larger than that, but smaller
|
||||||
|
than the fastest double click you can perform manually.
|
||||||
|
|
||||||
|
Example quirk: ::
|
||||||
|
|
||||||
|
[My Borked Mouse]
|
||||||
|
MatchUdevType=mouse
|
||||||
|
MatchBus=usb
|
||||||
|
MatchName=*MyBorkedMouse*
|
||||||
|
ModelBouncingKeys=1
|
||||||
|
AttrBouncingTimeoutMs=100
|
||||||
|
|
|
||||||
|
|
@ -142,9 +142,14 @@ ModelTabletModeSwitchUnreliable
|
||||||
Indicates that this tablet mode switch's state cannot be relied upon.
|
Indicates that this tablet mode switch's state cannot be relied upon.
|
||||||
ModelTrackball
|
ModelTrackball
|
||||||
Reserved for trackballs
|
Reserved for trackballs
|
||||||
|
|
||||||
|
.. _device-quirks-ModelBouncingKeys:
|
||||||
|
|
||||||
ModelBouncingKeys
|
ModelBouncingKeys
|
||||||
Indicates that the device may send fake bouncing key events and
|
Indicates that the device may send fake bouncing key events and
|
||||||
timestamps can not be relied upon.
|
timestamps can not be relied upon.
|
||||||
|
See also :ref:`device-quirks-AttrBouncingTimeoutMs` and
|
||||||
|
:ref:`device-quirks-AttrBouncingTimeoutSpuriousMs`.
|
||||||
ModelSynapticsSerialTouchpad
|
ModelSynapticsSerialTouchpad
|
||||||
Reserved for touchpads made by Synaptics on the serial bus
|
Reserved for touchpads made by Synaptics on the serial bus
|
||||||
ModelPressurePad
|
ModelPressurePad
|
||||||
|
|
@ -202,6 +207,20 @@ AttrTabletSmoothing=1|0
|
||||||
Enables (1) or disables (0) input smoothing for tablet devices. Smoothing is enabled
|
Enables (1) or disables (0) input smoothing for tablet devices. Smoothing is enabled
|
||||||
by default, except on AES devices.
|
by default, except on AES devices.
|
||||||
|
|
||||||
|
.. _device-quirks-AttrBouncingTimeoutMs:
|
||||||
|
|
||||||
|
AttrBouncingTimeoutMs
|
||||||
|
Timeout (in milliseconds) for the "bounce" debouncing method.
|
||||||
|
See :ref:`button_debouncing` for details.
|
||||||
|
Only applies when :ref:`device-quirks-ModelBouncingKeys` is enabled.
|
||||||
|
|
||||||
|
.. _device-quirks-AttrBouncingTimeoutSpuriousMs:
|
||||||
|
|
||||||
|
AttrBouncingTimeoutSpuriousMs
|
||||||
|
Timeout (in milliseconds) for the "spurious" debouncing method.
|
||||||
|
See :ref:`button_debouncing` for details.
|
||||||
|
Only applies when :ref:`device-quirks-ModelBouncingKeys` is enabled.
|
||||||
|
|
||||||
.. _device-quirks-matches:
|
.. _device-quirks-matches:
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -126,20 +126,16 @@ static inline void
|
||||||
debounce_set_timer(struct fallback_dispatch *fallback,
|
debounce_set_timer(struct fallback_dispatch *fallback,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
{
|
{
|
||||||
const int DEBOUNCE_TIMEOUT_BOUNCE = ms2us(25);
|
|
||||||
|
|
||||||
libinput_timer_set(&fallback->debounce.timer,
|
libinput_timer_set(&fallback->debounce.timer,
|
||||||
time + DEBOUNCE_TIMEOUT_BOUNCE);
|
time + fallback->debounce.timeout_bounce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
debounce_set_timer_short(struct fallback_dispatch *fallback,
|
debounce_set_timer_short(struct fallback_dispatch *fallback,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
{
|
{
|
||||||
const int DEBOUNCE_TIMEOUT_SPURIOUS = ms2us(12);
|
|
||||||
|
|
||||||
libinput_timer_set(&fallback->debounce.timer_short,
|
libinput_timer_set(&fallback->debounce.timer_short,
|
||||||
time + DEBOUNCE_TIMEOUT_SPURIOUS);
|
time + fallback->debounce.timeout_spurious);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
@ -573,14 +569,28 @@ void
|
||||||
fallback_init_debounce(struct fallback_dispatch *dispatch)
|
fallback_init_debounce(struct fallback_dispatch *dispatch)
|
||||||
{
|
{
|
||||||
struct evdev_device *device = dispatch->device;
|
struct evdev_device *device = dispatch->device;
|
||||||
|
struct quirks_context *quirks = evdev_libinput_context(device)->quirks;
|
||||||
|
struct quirks *q = quirks_fetch_for_device(quirks, device->udev_device);
|
||||||
|
bool disabled = false;
|
||||||
|
bool has_spurious_quirk = false;
|
||||||
|
uint32_t timeout_ms = 25;
|
||||||
|
uint32_t timeout_spurious_ms = 12;
|
||||||
char timer_name[64];
|
char timer_name[64];
|
||||||
|
|
||||||
if (evdev_device_has_model_quirk(device, QUIRK_MODEL_BOUNCING_KEYS)) {
|
quirks_get_bool(q, QUIRK_MODEL_BOUNCING_KEYS, &disabled);
|
||||||
|
if (disabled) {
|
||||||
dispatch->debounce.state = DEBOUNCE_STATE_DISABLED;
|
dispatch->debounce.state = DEBOUNCE_STATE_DISABLED;
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quirks_get_uint32(q, QUIRK_ATTR_BOUNCING_TIMEOUT_MS, &timeout_ms);
|
||||||
|
has_spurious_quirk = quirks_get_uint32(q,
|
||||||
|
QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS,
|
||||||
|
&timeout_spurious_ms);
|
||||||
|
|
||||||
dispatch->debounce.state = DEBOUNCE_STATE_IS_UP;
|
dispatch->debounce.state = DEBOUNCE_STATE_IS_UP;
|
||||||
|
dispatch->debounce.timeout_bounce = ms2us(timeout_ms);
|
||||||
|
dispatch->debounce.timeout_spurious = ms2us(timeout_spurious_ms);
|
||||||
|
|
||||||
snprintf(timer_name,
|
snprintf(timer_name,
|
||||||
sizeof(timer_name),
|
sizeof(timer_name),
|
||||||
|
|
@ -601,4 +611,10 @@ fallback_init_debounce(struct fallback_dispatch *dispatch)
|
||||||
timer_name,
|
timer_name,
|
||||||
debounce_timeout,
|
debounce_timeout,
|
||||||
device);
|
device);
|
||||||
|
|
||||||
|
if (has_spurious_quirk)
|
||||||
|
debounce_enable_spurious(dispatch);
|
||||||
|
|
||||||
|
end:
|
||||||
|
quirks_unref(q);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,8 @@ struct fallback_dispatch {
|
||||||
uint64_t button_time;
|
uint64_t button_time;
|
||||||
struct libinput_timer timer;
|
struct libinput_timer timer;
|
||||||
struct libinput_timer timer_short;
|
struct libinput_timer timer_short;
|
||||||
|
uint32_t timeout_bounce;
|
||||||
|
uint32_t timeout_spurious;
|
||||||
enum debounce_state state;
|
enum debounce_state state;
|
||||||
bool spurious_enabled;
|
bool spurious_enabled;
|
||||||
} debounce;
|
} debounce;
|
||||||
|
|
|
||||||
16
src/quirks.c
16
src/quirks.c
|
|
@ -292,6 +292,8 @@ quirk_get_name(enum quirk q)
|
||||||
case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp";
|
case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp";
|
||||||
case QUIRK_ATTR_EVENT_CODE: return "AttrEventCode";
|
case QUIRK_ATTR_EVENT_CODE: return "AttrEventCode";
|
||||||
case QUIRK_ATTR_INPUT_PROP: return "AttrInputProp";
|
case QUIRK_ATTR_INPUT_PROP: return "AttrInputProp";
|
||||||
|
case QUIRK_ATTR_BOUNCING_TIMEOUT_MS: return "AttrBouncingTimeoutMs";
|
||||||
|
case QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS: return "AttrBouncingTimeoutSpuriousMs";
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
@ -878,6 +880,20 @@ parse_attr(struct quirks_context *ctx,
|
||||||
p->value.tuples.ntuples = nprops;
|
p->value.tuples.ntuples = nprops;
|
||||||
p->type = PT_TUPLES;
|
p->type = PT_TUPLES;
|
||||||
|
|
||||||
|
rc = true;
|
||||||
|
} else if (streq(key, quirk_get_name(QUIRK_ATTR_BOUNCING_TIMEOUT_MS))) {
|
||||||
|
p->id = QUIRK_ATTR_BOUNCING_TIMEOUT_MS;
|
||||||
|
if (!safe_atou(value, &v))
|
||||||
|
goto out;
|
||||||
|
p->type = PT_UINT;
|
||||||
|
p->value.u = v;
|
||||||
|
rc = true;
|
||||||
|
} else if (streq(key, quirk_get_name(QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS))) {
|
||||||
|
p->id = QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS;
|
||||||
|
if (!safe_atou(value, &v))
|
||||||
|
goto out;
|
||||||
|
p->type = PT_UINT;
|
||||||
|
p->value.u = v;
|
||||||
rc = true;
|
rc = true;
|
||||||
} else {
|
} else {
|
||||||
qlog_error(ctx, "Unknown key %s in %s\n", key, s->name);
|
qlog_error(ctx, "Unknown key %s in %s\n", key, s->name);
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ enum quirk {
|
||||||
QUIRK_ATTR_MSC_TIMESTAMP,
|
QUIRK_ATTR_MSC_TIMESTAMP,
|
||||||
QUIRK_ATTR_EVENT_CODE,
|
QUIRK_ATTR_EVENT_CODE,
|
||||||
QUIRK_ATTR_INPUT_PROP,
|
QUIRK_ATTR_INPUT_PROP,
|
||||||
|
QUIRK_ATTR_BOUNCING_TIMEOUT_MS,
|
||||||
|
QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS,
|
||||||
|
|
||||||
_QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */
|
_QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -899,6 +899,8 @@ tools_list_device_quirks(struct quirks_context *ctx,
|
||||||
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD:
|
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD:
|
||||||
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD:
|
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD:
|
||||||
case QUIRK_ATTR_THUMB_SIZE_THRESHOLD:
|
case QUIRK_ATTR_THUMB_SIZE_THRESHOLD:
|
||||||
|
case QUIRK_ATTR_BOUNCING_TIMEOUT_MS:
|
||||||
|
case QUIRK_ATTR_BOUNCING_TIMEOUT_SPURIOUS_MS:
|
||||||
quirks_get_uint32(quirks, q, &v);
|
quirks_get_uint32(quirks, q, &v);
|
||||||
snprintf(buf, sizeof(buf), "%s=%u", name, v);
|
snprintf(buf, sizeof(buf), "%s=%u", name, v);
|
||||||
callback(userdata, buf);
|
callback(userdata, buf);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue