Commit 8d3788fa authored by Peter Hutterer's avatar Peter Hutterer

evdev: when the kernel fuzz is nonzero, set ours to zero

Our udev callout is supposed to reset the kernel fuzz to 0 and move the value
to the LIBINPUT_FUZZ property. This is to stop the kernel from applying its
own hysteresis-like approach.

Where the kernel fuzz is nonzero, something has gone wrong with that approach.
Complain about it and set our fuzz to zero, we are in the hands of the kernel
now. If we leave our fuzz as nonzero, we'll apply our own hysteresis on top of
the kernel's and that leads to unresponsive behavior.

Fixes #313Signed-off-by: Peter Hutterer's avatarPeter Hutterer <>
parent aa538dc5
Pipeline #45568 passed with stages
in 8 minutes and 55 seconds
......@@ -1616,10 +1616,10 @@ evdev_extract_abs_axes(struct evdev_device *device,
device->abs.is_fake_resolution = true;
if ((fuzz = evdev_read_fuzz_prop(device, ABS_X)))
libevdev_set_abs_fuzz(evdev, ABS_X, fuzz);
if ((fuzz = evdev_read_fuzz_prop(device, ABS_Y)))
libevdev_set_abs_fuzz(evdev, ABS_Y, fuzz);
fuzz = evdev_read_fuzz_prop(device, ABS_X);
libevdev_set_abs_fuzz(evdev, ABS_X, fuzz);
fuzz = evdev_read_fuzz_prop(device, ABS_Y);
libevdev_set_abs_fuzz(evdev, ABS_Y, fuzz);
device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_X);
......@@ -2298,23 +2298,44 @@ evdev_read_fuzz_prop(struct evdev_device *device, unsigned int code)
char name[32];
int rc;
int fuzz = 0;
const struct input_absinfo *abs;
rc = snprintf(name, sizeof(name), "LIBINPUT_FUZZ_%02x", code);
if (rc == -1)
return 0;
prop = udev_device_get_property_value(device->udev_device, name);
if (prop == NULL)
return 0;
if (safe_atoi(prop, &fuzz) == false || fuzz < 0) {
if (prop && (safe_atoi(prop, &fuzz) == false || fuzz < 0)) {
"invalid LIBINPUT_FUZZ property value: %s\n",
return 0;
return fuzz;
/* The udev callout should have set the kernel fuzz to zero.
* If the kernel fuzz is nonzero, something has gone wrong there, so
* let's complain but still use a fuzz of zero for our view of the
* device. Otherwise, the kernel will use the nonzero fuzz, we then
* use the same fuzz on top of the pre-fuzzed data and that leads to
* unresponsive behaviur.
abs = libevdev_get_abs_info(device->evdev, code);
if (!abs || abs->fuzz == 0)
return fuzz;
if (prop) {
"kernel fuzz of %d even with LIBINPUT_FUZZ_%02x present\n",
} else {
"kernel fuzz of %d but LIBINPUT_FUZZ_%02x is missing\n",
return 0;
......@@ -6956,6 +6956,22 @@ START_TEST(touchpad_end_start_touch)
struct litest_device *dev = litest_current_device();
struct libevdev *evdev = dev->evdev;
/* We expect our udev callout to always set this to 0 */
ck_assert_int_eq(libevdev_get_abs_fuzz(evdev, ABS_X), 0);
ck_assert_int_eq(libevdev_get_abs_fuzz(evdev, ABS_Y), 0);
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X))
ck_assert_int_eq(libevdev_get_abs_fuzz(evdev, ABS_MT_POSITION_X), 0);
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
ck_assert_int_eq(libevdev_get_abs_fuzz(evdev, ABS_MT_POSITION_Y), 0);
struct range suspends = { SUSPEND_EXT_MOUSE, SUSPEND_COUNT };
......@@ -7160,4 +7176,6 @@ TEST_COLLECTION(touchpad)
/* Happens on the "Wacom Intuos Pro M Finger" but our test device
* has the same properties */
litest_add_for_device("touchpad:bugs", touchpad_end_start_touch, LITEST_WACOM_FINGER);
litest_add("touchpad:fuzz", touchpad_fuzz, LITEST_TOUCHPAD, LITEST_ANY);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment