From 8d3788fa8cf7baab001021e9b258b77a586f015d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Jun 2019 08:55:07 +1000 Subject: [PATCH] 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 --- src/evdev.c | 39 ++++++++++++++++++++++++++++++--------- test/test-touchpad.c | 18 ++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 940a2fd..7b18cbe 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -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 diff --git a/test/test-touchpad.c b/test/test-touchpad.c index fca15d0..3b93414 100644 --- a/test/test-touchpad.c +++ b/test/test-touchpad.c @@ -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); } -- 2.7.4