From 33981394aa5d49ed55a48efd6bbfe71628ac2e9a Mon Sep 17 00:00:00 2001 From: Stephen Chandler Paul Date: Wed, 11 Jun 2014 20:16:04 -0400 Subject: [PATCH 1/6] test: Add litest_assert_double_*() macros Converts two doubles to 24.8 fixed-width integers so assertions can be made with doubles in tests Signed-off-by: Stephen Chandler Paul Reviewed-by: Peter Hutterer (cherry picked from commit 9d96286a44f90091638fc7f1242530da60849188) --- test/litest.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/litest.h b/test/litest.h index ed23c8a2..1268e104 100644 --- a/test/litest.h +++ b/test/litest.h @@ -404,6 +404,23 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name, struct input_id *id, const struct input_absinfo *abs, ...); +#define litest_assert_double_eq(a_, b_)\ + ck_assert_int_eq((int)(a_ * 256), (int)(b_ * 256)) + +#define litest_assert_double_ne(a_, b_)\ + ck_assert_int_ne((int)(a_ * 256), (int)(b_ * 256)) + +#define litest_assert_double_lt(a_, b_)\ + ck_assert_int_lt((int)(a_ * 256), (int)(b_ * 256)) + +#define litest_assert_double_le(a_, b_)\ + ck_assert_int_le((int)(a_ * 256), (int)(b_ * 256)) + +#define litest_assert_double_gt(a_, b_)\ + ck_assert_int_gt((int)(a_ * 256), (int)(b_ * 256)) + +#define litest_assert_double_ge(a_, b_)\ + ck_assert_int_ge((int)(a_ * 256), (int)(b_ * 256)) void litest_timeout_tap(void); void litest_timeout_tapndrag(void); From 6e614e7bee9fea9e9f9530f4d0d1c5ae602fc559 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 1 Dec 2015 15:26:48 +1000 Subject: [PATCH 2/6] test: use the double comparison macros Signed-off-by: Peter Hutterer (cherry picked from commit d070463a72c5c1fe6c8ece7a1cec23df68bed25d) --- test/litest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/litest.c b/test/litest.c index cf9b534e..35b85517 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1675,8 +1675,8 @@ int litest_scale(const struct litest_device *d, unsigned int axis, double val) { int min, max; - litest_assert_int_ge((int)val, 0); - litest_assert_int_le((int)val, 100); + litest_assert_double_ge(val, 0.0); + litest_assert_double_le(val, 100.0); litest_assert_int_le(axis, (unsigned int)ABS_Y); min = d->interface->min[axis]; From 8d76734fb6b91429602bc48e10ae2c5a8b7bf2b8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 10 Dec 2015 16:05:37 +1000 Subject: [PATCH 3/6] test: change extra axes to take a percentage as well More flexible than having values that are device-specific. Signed-off-by: Peter Hutterer --- test/litest.c | 34 +++++++++++++++++++++++++++------- test/touchpad.c | 22 +++++++++++----------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/test/litest.c b/test/litest.c index 35b85517..52679df4 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1255,7 +1255,8 @@ litest_event(struct litest_device *d, unsigned int type, } static bool -axis_replacement_value(struct axis_replacement *axes, +axis_replacement_value(struct litest_device *d, + struct axis_replacement *axes, int32_t evcode, int32_t *value) { @@ -1266,7 +1267,7 @@ axis_replacement_value(struct axis_replacement *axes, while (axis->evcode != -1) { if (axis->evcode == evcode) { - *value = axis->value; + *value = litest_scale(d, evcode, axis->value); return true; } axis++; @@ -1307,7 +1308,7 @@ litest_auto_assign_value(struct litest_device *d, value = touching ? 0 : 1; break; default: - if (!axis_replacement_value(axes, ev->code, &value) && + if (!axis_replacement_value(d, axes, ev->code, &value) && d->interface->get_axis_default) d->interface->get_axis_default(d, ev->code, &value); break; @@ -1671,17 +1672,36 @@ litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press) litest_button_click(d, key, is_press); } +static int +litest_scale_axis(const struct litest_device *d, + unsigned int axis, + double val) +{ + const struct input_absinfo *abs; + + litest_assert_double_ge(val, 0.0); + litest_assert_double_le(val, 100.0); + + abs = libevdev_get_abs_info(d->evdev, axis); + litest_assert_notnull(abs); + + return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum; +} + int litest_scale(const struct litest_device *d, unsigned int axis, double val) { int min, max; litest_assert_double_ge(val, 0.0); litest_assert_double_le(val, 100.0); - litest_assert_int_le(axis, (unsigned int)ABS_Y); - min = d->interface->min[axis]; - max = d->interface->max[axis]; - return (max - min) * val/100.0 + min; + if (axis <= ABS_Y) { + min = d->interface->min[axis]; + max = d->interface->max[axis]; + return (max - min) * val/100.0 + min; + } else { + return litest_scale_axis(d, axis, val); + } } void diff --git a/test/touchpad.c b/test/touchpad.c index 7bc99e98..dab2781e 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -2983,7 +2983,7 @@ START_TEST(touchpad_thumb_begin_no_motion) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3007,7 +3007,7 @@ START_TEST(touchpad_thumb_update_no_motion) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3033,7 +3033,7 @@ START_TEST(touchpad_thumb_moving) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3062,7 +3062,7 @@ START_TEST(touchpad_thumb_clickfinger) struct libinput_event *event; struct libinput_event_pointer *ptrev; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3119,7 +3119,7 @@ START_TEST(touchpad_thumb_btnarea) struct libinput_event *event; struct libinput_event_pointer *ptrev; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3155,7 +3155,7 @@ START_TEST(touchpad_thumb_edgescroll) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3186,7 +3186,7 @@ START_TEST(touchpad_thumb_tap_begin) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3219,7 +3219,7 @@ START_TEST(touchpad_thumb_tap_touch) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3252,7 +3252,7 @@ START_TEST(touchpad_thumb_tap_hold) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3286,7 +3286,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; @@ -3337,7 +3337,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap) struct libinput_event *event; struct libinput_event_pointer *ptrev; struct axis_replacement axes[] = { - { ABS_MT_PRESSURE, 190 }, + { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; From a4ac2bebb310ded75707860f942aea73a9a7cc5f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Dec 2015 15:34:50 +1000 Subject: [PATCH 4/6] test: extend sendfile from 4kB to 40kB The file is already larger than 4k, so we ended up truncating the file for the tests. This went unnoticed until recent additions that ended up truncating it halfway through an assignment. Signed-off-by: Peter Hutterer --- test/litest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/litest.c b/test/litest.c index 52679df4..fc188b6a 100644 --- a/test/litest.c +++ b/test/litest.c @@ -956,7 +956,7 @@ litest_copy_file(const char *dest, const char *src, const char *header) in = open(src, O_RDONLY); litest_assert_int_gt(in, -1); /* lazy, just check for error and empty file copy */ - litest_assert_int_gt(sendfile(out, in, NULL, 4096), 0); + litest_assert_int_gt(sendfile(out, in, NULL, 40960), 0); close(out); close(in); } From 874a9153b932fbc525bf11012ac2155fff084d82 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 14 Dec 2015 07:33:31 +1000 Subject: [PATCH 5/6] util: drop trailing semicolon from CASE_RETURN_STRING macro Avoid empty statements and force the caller to terminate the macro. Signed-off-by: Peter Hutterer --- src/libinput-util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libinput-util.h b/src/libinput-util.h index ba253b57..a627e5d4 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -43,7 +43,7 @@ /* The HW DPI rate we normalize to before calculating pointer acceleration */ #define DEFAULT_MOUSE_DPI 1000 -#define CASE_RETURN_STRING(a) case a: return #a; +#define CASE_RETURN_STRING(a) case a: return #a /* * This list data structure is a verbatim copy from wayland-util.h from the From 53c28a7d75a0a22bc96d780b9082fd6d8d3ed741 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Dec 2015 11:10:25 +1000 Subject: [PATCH 6/6] touchpad: add a special quirk for the Lenovo x220 with updated firmware If an x220 is updated to the touchpad firmware version 8.1, the touchpad suffers from the same issues as the x230 and needs custom acceleration code. Unfortunately we cannot detect this otherwise, so it is left to the user as a custom hwdb setting. https://bugzilla.redhat.com/show_bug.cgi?id=1264453 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/device-configuration-via-udev.dox | 18 ++++++++++++++++++ src/evdev-mt-touchpad.c | 3 ++- src/evdev.c | 1 + src/evdev.h | 1 + udev/90-libinput-model-quirks.hwdb | 12 ++++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index 85c5c9c9..6e9a3dc0 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -117,4 +117,22 @@ defaults or any other reason. The effects of setting these properties, the format of the property and the value of the property are subject to change at any time. +@subsection model_specific_configuration_x220fw81 Lenovo x220 with touchpad firmware v8.1 + +The property LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81 may be set by a +user in a local hwdb file. This property designates the touchpad on a Lenovo +x220 with a touchpad firmware version 8.1. When this firmware version is +installed, the touchpad is imprecise. The touchpad device does not send +continuos x/y axis position updates, a behavior also observed on its +successor model, the Lenovo x230 which has the same firmware version. If the +above property is set, libinput adjusts its behavior to better suit this +particular model. + +The touchpad firmware version cannot be detected automatically by libinput, +local configuration is required to set this property. Refer to the libinput +model quirks hwdb for instructions. + +This property must not be used for any other purpose, no specific behavior +is guaranteed. + */ diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 4fba147d..d78a54b0 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1565,7 +1565,8 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; - if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230) + if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230 || + tp->device->model_flags & EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81) filter = create_pointer_accelerator_filter_lenovo_x230(tp->device->dpi); else filter = create_pointer_accelerator_filter_touchpad(tp->device->dpi); diff --git a/src/evdev.c b/src/evdev.c index 55641c5e..9fecdc4c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1650,6 +1650,7 @@ evdev_read_model_flags(struct evdev_device *device) enum evdev_device_model model; } model_map[] = { { "LIBINPUT_MODEL_LENOVO_X230", EVDEV_MODEL_LENOVO_X230 }, + { "LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81", EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 }, { "LIBINPUT_MODEL_CHROMEBOOK", EVDEV_MODEL_CHROMEBOOK }, { "LIBINPUT_MODEL_SYSTEM76_BONOBO", EVDEV_MODEL_SYSTEM76_BONOBO }, { "LIBINPUT_MODEL_SYSTEM76_GALAGO", EVDEV_MODEL_SYSTEM76_GALAGO }, diff --git a/src/evdev.h b/src/evdev.h index e44a65de..36bf7b42 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -107,6 +107,7 @@ enum evdev_device_model { EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9), EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10), EVDEV_MODEL_ELANTECH_TOUCHPAD = (1 << 11), + EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12), }; struct mt_slot { diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index cf4fbfaa..814ec401 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -67,6 +67,18 @@ libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus* # LENOVO ########################################## +# X220 after a bios update updating the touchpad firmware version to 8.1 +# See https://bugzilla.redhat.com/show_bug.cgi?id=1264453 for details +# If the touchpad is unresponsive and dmesg includes this line +# psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1 [...] +# then copy the two lines below into a new file +# /etc/udev/hwdb.d/90-libinput-x220-touchpad-fw81.hwdb, then run +# sudo udevadm hwdb --update and reboot. +# +# Copy the two lines below: +#libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX220* +# LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81=1 + # X230 (Tablet) libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230* LIBINPUT_MODEL_LENOVO_X230=1