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

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2019-06-26 08:55:07 +10:00
parent aa538dc5c8
commit 8d3788fa8c
2 changed files with 48 additions and 9 deletions

View file

@ -1616,10 +1616,10 @@ evdev_extract_abs_axes(struct evdev_device *device,
device->abs.is_fake_resolution = true;
if (udev_tags & (EVDEV_UDEV_TAG_TOUCHPAD|EVDEV_UDEV_TAG_TOUCHSCREEN)) {
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)) {
evdev_log_bug_libinput(device,
"invalid LIBINPUT_FUZZ property value: %s\n",
prop);
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) {
evdev_log_bug_libinput(device,
"kernel fuzz of %d even with LIBINPUT_FUZZ_%02x present\n",
abs->fuzz,
code);
} else {
evdev_log_bug_libinput(device,
"kernel fuzz of %d but LIBINPUT_FUZZ_%02x is missing\n",
abs->fuzz,
code);
}
return 0;
}
bool

View file

@ -6956,6 +6956,22 @@ START_TEST(touchpad_end_start_touch)
}
END_TEST
START_TEST(touchpad_fuzz)
{
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);
}
END_TEST
TEST_COLLECTION(touchpad)
{
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);
}