.gitignore | 1 configure.ac | 17 debian/changelog | 33 debian/control | 1 debian/libinput10.symbols | 52 debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch | 2 debian/patches/touch-point-orientation-size.patch | 58 doc/Makefile.am | 1 doc/absolute-axes.dox | 18 doc/device-configuration-via-udev.dox | 4 doc/gestures.dox | 38 doc/normalization-of-relative-motion.dox | 8 doc/page-hierarchy.dox | 4 doc/pointer-acceleration.dox | 6 doc/svg/gesture-2fg-ambiguity.svg | 496 + doc/svg/pinch-gestures-softbuttons.svg | 365 doc/svg/tablet-axes.svg | 564 + doc/svg/tablet-out-of-bounds.svg | 271 doc/svg/tablet.svg | 199 doc/tablet-support.dox | 211 doc/tapping.dox | 6 doc/touchpad-tap-state-machine.svg | 1467 ++- src/Makefile.am | 4 src/evdev-mt-touchpad-buttons.c | 27 src/evdev-mt-touchpad-edge-scroll.c | 5 src/evdev-mt-touchpad-gestures.c | 395 - src/evdev-mt-touchpad-tap.c | 57 src/evdev-mt-touchpad.c | 237 src/evdev-mt-touchpad.h | 51 src/evdev-tablet.c | 1691 ++++ src/evdev-tablet.h | 204 src/evdev.c | 95 src/evdev.h | 26 src/filter.c | 94 src/filter.h | 3 src/libinput-private.h | 100 src/libinput-util.h | 56 src/libinput.c | 826 ++ src/libinput.h | 1011 ++ src/libinput.sym | 55 test/Makefile.am | 18 test/device.c | 103 test/gestures.c | 892 ++ test/litest-device-anker-mouse-kbd.c | 225 test/litest-device-apple-internal-keyboard.c | 239 test/litest-device-cyborg-rat-5.c | 71 test/litest-device-huion-pentablet.c | 113 test/litest-device-synaptics-hover.c | 2 test/litest-device-synaptics-i2c.c | 102 test/litest-device-wacom-bamboo-tablet.c | 119 test/litest-device-wacom-cintiq-24hd.c | 147 test/litest-device-wacom-cintiq-tablet.c | 158 test/litest-device-wacom-intuos-tablet.c | 163 test/litest-device-wacom-isdv4-tablet.c | 112 test/litest-device-waltop-tablet.c | 241 test/litest-device-yubikey.c | 169 test/litest-int.h | 8 test/litest-selftest.c | 4 test/litest.c | 188 test/litest.h | 597 + test/misc.c | 114 test/path.c | 60 test/pointer.c | 10 test/tablet.c | 3680 ++++++++++ test/touchpad-tap.c | 296 test/touchpad.c | 485 + test/udev.c | 5 test/valgrind.suppressions | 18 tools/event-debug.c | 234 tools/event-gui.c | 236 tools/libinput-list-devices.c | 16 tools/shared.c | 16 tools/shared.h | 1 udev/90-libinput-model-quirks.hwdb | 28 udev/90-libinput-model-quirks.rules.in | 4 udev/libinput-model-quirks.c | 6 76 files changed, 16196 insertions(+), 1443 deletions(-)
New commits: commit f06b99ba73bf0f8d801d0167e0c29f9717a99541 Author: Timo Aaltonen <[email protected]> Date: Thu Mar 17 11:14:12 2016 +0200 refresh patches, release to xenial diff --git a/debian/changelog b/debian/changelog index bb23bdb..a5d26d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +libinput (1.2.2-1ubuntu1) xenial; urgency=medium + + * Merge from debian. + * patches: Refreshed. + + -- Timo Aaltonen <[email protected]> Thu, 17 Mar 2016 11:12:01 +0200 + libinput (1.2.2-1) unstable; urgency=medium * New upstream release. diff --git a/debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch b/debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch index e1fb1d6..0473fdf 100644 --- a/debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch +++ b/debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch @@ -17,7 +17,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> --- a/src/evdev.c +++ b/src/evdev.c -@@ -654,16 +654,16 @@ evdev_process_key(struct evdev_device *d +@@ -665,16 +665,16 @@ evdev_process_key(struct evdev_device *d if (e->value == 2) return; diff --git a/debian/patches/touch-point-orientation-size.patch b/debian/patches/touch-point-orientation-size.patch index 7094de7..298a460 100644 --- a/debian/patches/touch-point-orientation-size.patch +++ b/debian/patches/touch-point-orientation-size.patch @@ -37,7 +37,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> --- a/doc/Makefile.am +++ b/doc/Makefile.am -@@ -26,6 +26,7 @@ header_files = \ +@@ -27,6 +27,7 @@ header_files = \ $(srcdir)/tapping.dox \ $(srcdir)/test-suite.dox \ $(srcdir)/tools.dox \ @@ -45,7 +45,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> $(srcdir)/touchpads.dox diagram_files = \ -@@ -50,6 +51,7 @@ diagram_files = \ +@@ -51,6 +52,7 @@ diagram_files = \ $(srcdir)/svg/thumb-detection.svg \ $(srcdir)/svg/top-software-buttons.svg \ $(srcdir)/svg/touchscreen-gestures.svg \ @@ -471,7 +471,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> enum evdev_key_type { EVDEV_KEY_TYPE_NONE, -@@ -245,6 +249,100 @@ evdev_device_transform_y(struct evdev_de +@@ -258,6 +262,100 @@ evdev_device_transform_y(struct evdev_de return scale_axis(device->abs.absinfo_y, y, height); } @@ -572,7 +572,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> static inline void normalize_delta(struct evdev_device *device, const struct device_coords *delta, -@@ -282,8 +380,15 @@ evdev_flush_pending_event(struct evdev_d +@@ -295,8 +393,15 @@ evdev_flush_pending_event(struct evdev_d struct normalized_coords accel, unaccel; struct device_coords point; struct device_float_coords raw; @@ -588,7 +588,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> switch (device->pending_event) { case EVDEV_NONE: -@@ -324,7 +429,7 @@ evdev_flush_pending_event(struct evdev_d +@@ -337,7 +442,7 @@ evdev_flush_pending_event(struct evdev_d if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) break; @@ -597,7 +597,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> log_bug_kernel(libinput, "%s: Driver sent multiple touch down for the " "same slot", -@@ -333,38 +438,50 @@ evdev_flush_pending_event(struct evdev_d +@@ -346,38 +451,48 @@ evdev_flush_pending_event(struct evdev_d } seat_slot = ffs(~seat->slot_map) - 1; @@ -610,7 +610,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> seat->slot_map |= 1 << seat_slot; - point = device->mt.slots[slot].point; + point = slot_data->point; - transform_absolute(device, &point); + evdev_transform_absolute(device, &point); - touch_notify_touch_down(base, time, slot, seat_slot, - &point); @@ -629,16 +629,14 @@ Signed-off-by: Andreas Pokorny <[email protected]> - seat_slot = device->mt.slots[slot].seat_slot; - point = device->mt.slots[slot].point; + seat_slot = slot_data->seat_slot; -+ + point = slot_data->point; if (seat_slot == -1) break; - transform_absolute(device, &point); + evdev_transform_absolute(device, &point); - touch_notify_touch_motion(base, time, slot, seat_slot, - &point); -+ + touch_notify_touch_motion(base, + time, + slot, @@ -658,9 +656,9 @@ Signed-off-by: Andreas Pokorny <[email protected]> if (seat_slot == -1) break; -@@ -396,7 +513,13 @@ evdev_flush_pending_event(struct evdev_d +@@ -409,7 +524,13 @@ evdev_flush_pending_event(struct evdev_d point = device->abs.point; - transform_absolute(device, &point); + evdev_transform_absolute(device, &point); - touch_notify_touch_down(base, time, -1, seat_slot, &point); + touch_notify_touch_down(base, @@ -673,7 +671,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> break; case EVDEV_ABSOLUTE_MOTION: point = device->abs.point; -@@ -408,8 +531,13 @@ evdev_flush_pending_event(struct evdev_d +@@ -421,8 +542,13 @@ evdev_flush_pending_event(struct evdev_d if (seat_slot == -1) break; @@ -689,7 +687,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> } else if (device->seat_caps & EVDEV_DEVICE_POINTER) { pointer_notify_motion_absolute(base, time, &point); } -@@ -583,8 +711,9 @@ evdev_process_touch(struct evdev_device +@@ -596,8 +722,9 @@ evdev_process_touch(struct evdev_device struct input_event *e, uint64_t time) { @@ -701,7 +699,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> if ((size_t)e->value >= device->mt.slots_len) { log_bug_libinput(device->base.seat->libinput, "%s exceeds slots (%d of %zd)\n", -@@ -595,8 +724,7 @@ evdev_process_touch(struct evdev_device +@@ -608,8 +735,7 @@ evdev_process_touch(struct evdev_device } evdev_flush_pending_event(device, time); device->mt.slot = e->value; @@ -711,7 +709,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> if (device->pending_event != EVDEV_NONE && device->pending_event != EVDEV_ABSOLUTE_MT_MOTION) evdev_flush_pending_event(device, time); -@@ -604,17 +732,34 @@ evdev_process_touch(struct evdev_device +@@ -617,17 +743,34 @@ evdev_process_touch(struct evdev_device device->pending_event = EVDEV_ABSOLUTE_MT_DOWN; else device->pending_event = EVDEV_ABSOLUTE_MT_UP; @@ -756,7 +754,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> } } -@@ -1969,6 +2114,20 @@ evdev_configure_mt_device(struct evdev_d +@@ -1989,6 +2132,20 @@ evdev_configure_mt_device(struct evdev_d slots[slot].point.y = libevdev_get_slot_value(evdev, slot, ABS_MT_POSITION_Y); @@ -777,7 +775,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> } device->mt.slots = slots; device->mt.slots_len = num_slots; -@@ -2039,6 +2198,15 @@ evdev_configure_device(struct evdev_devi +@@ -2060,6 +2217,15 @@ evdev_configure_device(struct evdev_devi return -1; } @@ -795,7 +793,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> --- a/src/evdev.h +++ b/src/evdev.h -@@ -113,6 +113,8 @@ enum evdev_device_model { +@@ -119,6 +119,8 @@ enum evdev_device_model { struct mt_slot { int32_t seat_slot; struct device_coords point; @@ -804,7 +802,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> }; struct evdev_device { -@@ -129,6 +131,8 @@ struct evdev_device { +@@ -135,6 +137,8 @@ struct evdev_device { int fd; struct { const struct input_absinfo *absinfo_x, *absinfo_y; @@ -813,7 +811,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> int fake_resolution; struct device_coords point; -@@ -350,6 +354,26 @@ double +@@ -376,6 +380,26 @@ double evdev_device_transform_y(struct evdev_device *device, double y, uint32_t height); @@ -854,7 +852,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> /* * A coordinate pair in device coordinates, capable of holding non discrete * values, this is necessary e.g. when device coordinates get averaged. -@@ -396,14 +401,18 @@ touch_notify_touch_down(struct libinput_ +@@ -461,14 +466,18 @@ touch_notify_touch_down(struct libinput_ uint64_t time, int32_t slot, int32_t seat_slot, @@ -877,7 +875,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> touch_notify_touch_up(struct libinput_device *device, --- a/src/libinput-util.h +++ b/src/libinput-util.h -@@ -118,6 +118,12 @@ msleep(unsigned int ms) +@@ -145,6 +145,12 @@ msleep(unsigned int ms) usleep(ms * 1000); } @@ -901,7 +899,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> }; struct libinput_event_gesture { -@@ -732,6 +734,204 @@ libinput_event_touch_get_y(struct libinp +@@ -758,6 +760,204 @@ libinput_event_touch_get_y(struct libinp return evdev_convert_to_mm(device->abs.absinfo_y, event->point.y); } @@ -1106,7 +1104,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> LIBINPUT_EXPORT uint32_t libinput_event_gesture_get_time(struct libinput_event_gesture *event) { -@@ -1512,7 +1712,9 @@ touch_notify_touch_down(struct libinput_ +@@ -2113,7 +2313,9 @@ touch_notify_touch_down(struct libinput_ uint64_t time, int32_t slot, int32_t seat_slot, @@ -1117,7 +1115,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> { struct libinput_event_touch *touch_event; -@@ -1528,6 +1730,8 @@ touch_notify_touch_down(struct libinput_ +@@ -2129,6 +2331,8 @@ touch_notify_touch_down(struct libinput_ .slot = slot, .seat_slot = seat_slot, .point = *point, @@ -1126,7 +1124,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> }; post_device_event(device, time, -@@ -1540,7 +1744,9 @@ touch_notify_touch_motion(struct libinpu +@@ -2141,7 +2345,9 @@ touch_notify_touch_motion(struct libinpu uint64_t time, int32_t slot, int32_t seat_slot, @@ -1137,7 +1135,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> { struct libinput_event_touch *touch_event; -@@ -1556,6 +1762,8 @@ touch_notify_touch_motion(struct libinpu +@@ -2157,6 +2363,8 @@ touch_notify_touch_motion(struct libinpu .slot = slot, .seat_slot = seat_slot, .point = *point, @@ -1148,7 +1146,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> post_device_event(device, time, --- a/src/libinput.h +++ b/src/libinput.h -@@ -968,6 +968,228 @@ libinput_event_touch_get_y_transformed(s +@@ -1151,6 +1151,228 @@ libinput_event_touch_get_y_transformed(s /** * @ingroup event_touch * @@ -1379,7 +1377,7 @@ Signed-off-by: Andreas Pokorny <[email protected]> struct libinput_event * --- a/src/libinput.sym +++ b/src/libinput.sym -@@ -173,6 +173,19 @@ LIBINPUT_0.21.0 { +@@ -174,6 +174,19 @@ LIBINPUT_0.21.0 { libinput_event_touch_get_time_usec; } LIBINPUT_0.20.0; commit 371db78d35361ec5b0f5b2c1d3b4c6862c317bd6 Author: Timo Aaltonen <[email protected]> Date: Thu Mar 17 10:55:12 2016 +0200 release to unstable diff --git a/debian/changelog b/debian/changelog index f092320..f32c177 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libinput (1.2.2-1) unstable; urgency=medium + + * New upstream release. + + -- Timo Aaltonen <[email protected]> Thu, 17 Mar 2016 10:49:19 +0200 + libinput (1.2.0-1) unstable; urgency=medium * New upstream release. commit ae7b2f77720f19ce3b6924bb3ecf706cabd17587 Author: Peter Hutterer <[email protected]> Date: Tue Mar 15 10:23:42 2016 +1000 configure.ac: libinput 1.2.2 Signed-off-by: Peter Hutterer <[email protected]> diff --git a/configure.ac b/configure.ac index 71255ed..7d73183 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.64]) m4_define([libinput_major_version], [1]) m4_define([libinput_minor_version], [2]) -m4_define([libinput_micro_version], [1]) +m4_define([libinput_micro_version], [2]) m4_define([libinput_version], [libinput_major_version.libinput_minor_version.libinput_micro_version]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) # b) If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # c) If the interface is the same as the previous version, change to C:R+1:A -LIBINPUT_LT_VERSION=17:3:7 +LIBINPUT_LT_VERSION=17:4:7 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes]) commit a608d9dc2c70c7915fc94466ed27c1684f65409e Author: Peter Hutterer <[email protected]> Date: Mon Mar 7 16:05:25 2016 +1000 touchpad: add quirk for the T450 and T460 generation hardware The touchpad's sensors are too far apart (or the firmware interferes), causing in a jerky movement visible especially on slow motion. We get a bunch of normal motion events, then only ABS_MT_PRESSURE updates without x/y updates. After about one mm of movement x/y updates resume, with the first event covering the distance between the last motion event. That event is usually accelerated and thus causes a large jump. Subsequent events are sufficiently fine-grained again. This patch counts the number of non-motion events. Once we hit 10 in a row, we mark the first motion update as non-dirty, effectively discarding the motion and thus stopping the pointer jumps. https://bugs.freedesktop.org/show_bug.cgi?id=94379 Signed-off-by: Peter Hutterer <[email protected]> Tested-by: Benjamin Tissoires <[email protected]> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 00d6539..d0a8e27 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -337,7 +337,7 @@ tp_process_absolute(struct tp_dispatch *tp, case ABS_MT_PRESSURE: t->pressure = e->value; t->dirty = true; - tp->queued |= TOUCHPAD_EVENT_MOTION; + tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; break; } } @@ -880,8 +880,10 @@ tp_position_fake_touches(struct tp_dispatch *tp) } static inline bool -tp_need_motion_history_reset(struct tp_dispatch *tp) +tp_need_motion_history_reset(struct tp_dispatch *tp, uint64_t time) { + bool rc = false; + /* semi-mt finger postions may "jump" when nfingers changes */ if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down) return true; @@ -894,7 +896,29 @@ tp_need_motion_history_reset(struct tp_dispatch *tp) tp->old_nfingers_down > tp->num_slots)) return true; - return false; + /* Quirk: if we had multiple events without x/y axis + information, the next x/y event is going to be a jump. So we + reset that touch to non-dirty effectively swallowing that event + and restarting with the next event again. + */ + if (tp->device->model_flags & EVDEV_MODEL_LENOVO_T450_TOUCHPAD) { + if (tp->queued & TOUCHPAD_EVENT_MOTION) { + if (tp->quirks.nonmotion_event_count > 10) { + struct tp_touch *t; + + tp_for_each_touch(tp, t) + t->dirty = false; + rc = true; + } + tp->quirks.nonmotion_event_count = 0; + } + + if ((tp->queued & (TOUCHPAD_EVENT_OTHERAXIS|TOUCHPAD_EVENT_MOTION)) == + TOUCHPAD_EVENT_OTHERAXIS) + tp->quirks.nonmotion_event_count++; + } + + return rc; } static void @@ -909,7 +933,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) tp_unhover_touches(tp, time); tp_position_fake_touches(tp); - want_motion_reset = tp_need_motion_history_reset(tp); + want_motion_reset = tp_need_motion_history_reset(tp, time); for (i = 0; i < tp->ntouches; i++) { t = tp_get_touch(tp, i); diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index eae327b..1f05a03 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -41,6 +41,7 @@ enum touchpad_event { TOUCHPAD_EVENT_MOTION = (1 << 0), TOUCHPAD_EVENT_BUTTON_PRESS = (1 << 1), TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2), + TOUCHPAD_EVENT_OTHERAXIS = (1 << 3), }; enum touchpad_model { @@ -353,6 +354,17 @@ struct tp_dispatch { int upper_thumb_line; int lower_thumb_line; } thumb; + + struct { + /* A quirk used on the T450 series Synaptics hardware. + * Slowly moving the finger causes multiple events with only + * ABS_MT_PRESSURE but no x/y information. When the x/y + * event comes, it will be a jump of ~20 units. We use the + * below to count non-motion events to discard that first + * event with the jump. + */ + unsigned int nonmotion_event_count; + } quirks; }; #define tp_for_each_touch(_tp, _t) \ diff --git a/src/evdev.c b/src/evdev.c index 51768fe..a5c965d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1680,6 +1680,7 @@ evdev_read_model_flags(struct evdev_device *device) { "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT }, { "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA }, { "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE }, + { "LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD", EVDEV_MODEL_LENOVO_T450_TOUCHPAD }, { NULL, EVDEV_MODEL_DEFAULT }, }; const struct model_map *m = model_map; diff --git a/src/evdev.h b/src/evdev.h index 482712b..4a5d807 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -113,6 +113,7 @@ enum evdev_device_model { EVDEV_MODEL_CYBORG_RAT = (1 << 14), EVDEV_MODEL_CYAPA = (1 << 15), EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16), + EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17), }; struct mt_slot { diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index eb2859e..d5978f7 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -100,6 +100,13 @@ libinput:name:Cypress APA Trackpad (cyapa):dmi:* libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230* LIBINPUT_MODEL_LENOVO_X230=1 +# Lenovo T450/T460 and all other Lenovos of the *50 and *60 generation, +# including the X1 Carbon 3rd gen +libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??50*: +libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??60*: +libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd:* + LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD=1 + ########################################## # Synaptics ########################################## commit 5d904b63191538b46d7fe8443990b55c42de0205 Author: Peter Hutterer <[email protected]> Date: Mon Mar 7 10:12:13 2016 +1000 tablet: reject mislabelled tablet devices The HUION 580 has a "consumer control" event node that has an ABS_VOLUME, keys and a REL_HWHEEL. It has the same VID/PID as the pen tablet and libwacom labels it as ID_INPUT_TABLET. This causes a crash later when we try to init pointer acceleration for a device that doesn't have axes. https://bugzilla.redhat.com/show_bug.cgi?id=1314955 Signed-off-by: Peter Hutterer <[email protected]> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 0f6fa2c..7359881 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1613,6 +1613,31 @@ tablet_init_left_handed(struct evdev_device *device) } static int +tablet_reject_device(struct evdev_device *device) +{ + struct libevdev *evdev = device->evdev; + int rc = -1; + + if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) || + !libevdev_has_event_code(evdev, EV_ABS, ABS_Y)) + goto out; + + if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN)) + goto out; + + rc = 0; + +out: + if (rc) { + log_bug_libinput(device->base.seat->libinput, + "Device '%s' does not meet tablet criteria. " + "Ignoring this device.\n", + device->devname); + } + return rc; +} + +static int tablet_init(struct tablet_dispatch *tablet, struct evdev_device *device) { @@ -1625,6 +1650,9 @@ tablet_init(struct tablet_dispatch *tablet, tablet->current_tool_type = LIBINPUT_TOOL_NONE; list_init(&tablet->tool_list); + if (tablet_reject_device(device)) + return -1; + tablet_init_calibration(tablet, device); tablet_init_proximity_threshold(tablet, device); rc = tablet_init_accel(tablet, device); commit b4a74bcebc8f1d37b2ed78db3440435ead03299a Author: Peter Hutterer <[email protected]> Date: Fri Mar 4 07:50:49 2016 +1000 Assert that the interface is actually filled in. Had this in a private bug report recently. Missing hooks for open/close just segfault with little information to debug. Add an assert, this is definitely a bug in the caller and we don't need to recover from that. Signed-off-by: Peter Hutterer <[email protected]> diff --git a/src/libinput.c b/src/libinput.c index 3c78905..1480878 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1517,6 +1517,9 @@ libinput_init(struct libinput *libinput, const struct libinput_interface_backend *interface_backend, void *user_data) { + assert(interface->open_restricted != NULL); + assert(interface->close_restricted != NULL); + libinput->epoll_fd = epoll_create1(EPOLL_CLOEXEC);; if (libinput->epoll_fd < 0) return -1; diff --git a/test/udev.c b/test/udev.c index 30ae118..9296e94 100644 --- a/test/udev.c +++ b/test/udev.c @@ -52,7 +52,6 @@ const struct libinput_interface simple_interface = { START_TEST(udev_create_NULL) { struct libinput *li; - const struct libinput_interface interface; struct udev *udev; udev = udev_new(); @@ -60,13 +59,13 @@ START_TEST(udev_create_NULL) li = libinput_udev_create_context(NULL, NULL, NULL); ck_assert(li == NULL); - li = libinput_udev_create_context(&interface, NULL, NULL); + li = libinput_udev_create_context(&simple_interface, NULL, NULL); ck_assert(li == NULL); li = libinput_udev_create_context(NULL, NULL, udev); ck_assert(li == NULL); - li = libinput_udev_create_context(&interface, NULL, udev); + li = libinput_udev_create_context(&simple_interface, NULL, udev); ck_assert(li != NULL); ck_assert_int_eq(libinput_udev_assign_seat(li, NULL), -1); commit 00a9b05da71c9071cc910a1c5975165f2a8db9c6 Author: Peter Hutterer <[email protected]> Date: Thu Mar 3 08:33:22 2016 +1000 test: add two path tests for invalid devices One test for an actual file (so far we only tested /tmp, the directory) and one for a kernel dev that returns a udev device and thus gets one step further in the error handling code. Plus, I saw test code doing this (opening /dev/uinput) and it crashed (for other reasons), so we might as well test it. Signed-off-by: Peter Hutterer <[email protected]> diff --git a/test/path.c b/test/path.c index 0b04b19..7d7c445 100644 --- a/test/path.c +++ b/test/path.c @@ -27,6 +27,7 @@ #include <errno.h> #include <fcntl.h> #include <libinput.h> +#include <stdio.h> #include <unistd.h> #include "litest.h" @@ -98,6 +99,63 @@ START_TEST(path_create_invalid) } END_TEST +START_TEST(path_create_invalid_kerneldev) +{ + struct libinput *li; + struct libinput_device *device; + const char *path = "/dev/uinput"; + + open_func_count = 0; + close_func_count = 0; + + li = libinput_path_create_context(&simple_interface, NULL); + ck_assert(li != NULL); + device = libinput_path_add_device(li, path); + ck_assert(device == NULL); + + ck_assert_int_eq(open_func_count, 1); + ck_assert_int_eq(close_func_count, 1); + + libinput_unref(li); + ck_assert_int_eq(close_func_count, 1); + + open_func_count = 0; + close_func_count = 0; +} +END_TEST + +START_TEST(path_create_invalid_file) +{ + struct libinput *li; + struct libinput_device *device; + char path[] = "/tmp/litest_path_XXXXXX"; + int fd; + + fd = mkstemp(path); + ck_assert_int_ge(fd, 0); + close(fd); + + open_func_count = 0; + close_func_count = 0; + + li = libinput_path_create_context(&simple_interface, NULL); + unlink(path); + + ck_assert(li != NULL); + device = libinput_path_add_device(li, path); + ck_assert(device == NULL); + + ck_assert_int_eq(open_func_count, 0); + ck_assert_int_eq(close_func_count, 0); + + libinput_unref(li); + ck_assert_int_eq(close_func_count, 0); + + open_func_count = 0; + close_func_count = 0; +} +END_TEST + START_TEST(path_create_destroy) { struct libinput *li; @@ -882,6 +940,8 @@ litest_setup_tests(void) { litest_add_no_device("path:create", path_create_NULL); litest_add_no_device("path:create", path_create_invalid); + litest_add_no_device("path:create", path_create_invalid_file); + litest_add_no_device("path:create", path_create_invalid_kerneldev); litest_add_no_device("path:create", path_create_destroy); litest_add_no_device("path:create", path_set_user_data); litest_add_no_device("path:suspend", path_suspend); commit a60afbeec39f7de4a03103dab26701b506dc93d0 Author: Peter Hutterer <[email protected]> Date: Wed Mar 2 11:48:59 2016 +1000 touchpad: use the udev property over a compile-time vendor ID check Signed-off-by: Peter Hutterer <[email protected]> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 95d650a..00d6539 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1299,7 +1299,7 @@ tp_dwt_device_is_blacklisted(struct evdev_device *device) return true; /* Wacom makes touchpads, but not internal ones */ - if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM) + if (device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD) return true; return false; commit 2bb0678a00f9c089dc865d6ecd20be36446d1c06 Author: Peter Hutterer <[email protected]> Date: Wed Feb 10 09:24:51 2016 +1000 tablet: sanitize button mask passing We have a struct, use it. Better than passing arrays and array lengths around. Signed-off-by: Peter Hutterer <[email protected]> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 22ea1eb..0f6fa2c 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -38,34 +38,27 @@ static inline void tablet_get_pressed_buttons(struct tablet_dispatch *tablet, - unsigned char *buttons, - unsigned int buttons_len) + struct button_state *buttons) { size_t i; const struct button_state *state = &tablet->button_state, *prev_state = &tablet->prev_button_state; - assert(buttons_len <= ARRAY_LENGTH(state->stylus_buttons)); - - for (i = 0; i < buttons_len; i++) - buttons[i] = state->stylus_buttons[i] & - ~(prev_state->stylus_buttons[i]); + for (i = 0; i < sizeof(buttons->bits); i++) + buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]); } static inline void tablet_get_released_buttons(struct tablet_dispatch *tablet, - unsigned char *buttons, - unsigned int buttons_len) + struct button_state *buttons) { size_t i; const struct button_state *state = &tablet->button_state, *prev_state = &tablet->prev_button_state; - assert(buttons_len <= ARRAY_LENGTH(state->stylus_buttons)); - - for (i = 0; i < buttons_len; i++) - buttons[i] = prev_state->stylus_buttons[i] & - ~(state->stylus_buttons[i]); + for (i = 0; i < sizeof(buttons->bits); i++) + buttons->bits[i] = prev_state->bits[i] & + ~(state->bits[i]); } /* Merge the previous state with the current one so all buttons look like @@ -77,10 +70,9 @@ tablet_force_button_presses(struct tablet_dispatch *tablet) *prev_state = &tablet->prev_button_state; size_t i; - for (i = 0; i < sizeof(state->stylus_buttons); i++) { - state->stylus_buttons[i] = state->stylus_buttons[i] | - prev_state->stylus_buttons[i]; - prev_state->stylus_buttons[i] = 0; + for (i = 0; i < sizeof(state->bits); i++) { + state->bits[i] = state->bits[i] | prev_state->bits[i]; + prev_state->bits[i] = 0; } } @@ -566,10 +558,10 @@ tablet_update_button(struct tablet_dispatch *tablet, } if (enable) { - set_bit(tablet->button_state.stylus_buttons, evcode); + set_bit(tablet->button_state.bits, evcode); tablet_set_status(tablet, TABLET_BUTTONS_PRESSED); } else { - clear_bit(tablet->button_state.stylus_buttons, evcode); + clear_bit(tablet->button_state.bits, evcode); tablet_set_status(tablet, TABLET_BUTTONS_RELEASED); } } @@ -936,20 +928,19 @@ tablet_notify_button_mask(struct tablet_dispatch *tablet, struct evdev_device *device, uint64_t time, struct libinput_tablet_tool *tool, - const unsigned char *buttons, - unsigned int buttons_len, + const struct button_state *buttons, enum libinput_button_state state) { struct libinput_device *base = &device->base; size_t i; - size_t nbits = 8 * sizeof(buttons[0]) * buttons_len; + size_t nbits = 8 * sizeof(buttons->bits); enum libinput_tablet_tool_tip_state tip_state; tip_state = tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ? LIBINPUT_TABLET_TOOL_TIP_DOWN : LIBINPUT_TABLET_TOOL_TIP_UP; for (i = 0; i < nbits; i++) { - if (!bit_is_set(buttons, i)) + if (!bit_is_set(buttons->bits, i)) continue; tablet_notify_button(base, @@ -969,21 +960,18 @@ tablet_notify_buttons(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, enum libinput_button_state state) { - unsigned char buttons[ARRAY_LENGTH(tablet->button_state.stylus_buttons)]; + struct button_state buttons; if (state == LIBINPUT_BUTTON_STATE_PRESSED) - tablet_get_pressed_buttons(tablet, buttons, sizeof(buttons)); + tablet_get_pressed_buttons(tablet, &buttons); else - tablet_get_released_buttons(tablet, - buttons, - sizeof(buttons)); + tablet_get_released_buttons(tablet, &buttons); tablet_notify_button_mask(tablet, device, time, tool, - buttons, - sizeof(buttons), + &buttons, state); } @@ -1332,9 +1320,9 @@ tablet_flush(struct tablet_dispatch *tablet, if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { /* Release all stylus buttons */ - memset(tablet->button_state.stylus_buttons, + memset(tablet->button_state.bits, 0, - sizeof(tablet->button_state.stylus_buttons)); + sizeof(tablet->button_state.bits)); tablet_set_status(tablet, TABLET_BUTTONS_RELEASED); if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT); diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 1d6fc93..880d523 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -45,7 +45,7 @@ enum tablet_status { }; struct button_state { - unsigned char stylus_buttons[NCHARS(KEY_CNT)]; + unsigned char bits[NCHARS(KEY_CNT)]; }; struct tablet_dispatch { commit 21fe11fb11a4d79aabb208f5839679a52a74678b Author: Peter Hutterer <[email protected]> Date: Fri Feb 26 15:19:57 2016 +1000 configure.ac: libinput 1.2.1 Signed-off-by: Peter Hutterer <[email protected]> diff --git a/configure.ac b/configure.ac index d400f21..71255ed 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.64]) m4_define([libinput_major_version], [1])

