From 30df66d0a6dfd36f760a32394d5ddb8a45a92403 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 16 Dec 2015 10:48:39 +1000 Subject: [PATCH 01/11] evdev: drain any pending evdev events on a device open_restricted() doesn't always mean 'open the fd'. When the X server uses systemd-logind, the fd is opened once before PreInit and then kept open across devices being disabled and enabled through the protocol. When the device is re-enabled and libinput_path_add_device is called for the device, we may have events pending on the fd, leaking information that we should just ignore. There's also the potential of inconsistent state. The kernel updates the device state whenever it processes an event, the evdev ioctls return that state. If events are pending, the state we see is newer than the events we process immediately after initialization. That can lead to confusion. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 15 ++++++++++ test/misc.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 9fecdc4c..37080725 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2202,6 +2202,17 @@ evdev_set_device_group(struct evdev_device *device, return 0; } +static inline void +evdev_drain_fd(int fd) +{ + struct input_event ev[24]; + size_t sz = sizeof ev; + + while (read(fd, &ev, sz) == (int)sz) { + /* discard all pending events */ + } +} + struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *udev_device) @@ -2235,6 +2246,8 @@ evdev_device_create(struct libinput_seat *seat, libinput_device_init(&device->base, seat); libinput_seat_ref(seat); + evdev_drain_fd(fd); + rc = libevdev_new_from_fd(fd, &device->evdev); if (rc != 0) goto err; @@ -2682,6 +2695,8 @@ evdev_device_resume(struct evdev_device *device) return -ENODEV; } + evdev_drain_fd(fd); + device->fd = fd; if (evdev_need_mtdev(device)) { diff --git a/test/misc.c b/test/misc.c index 89edb145..b962cc5a 100644 --- a/test/misc.c +++ b/test/misc.c @@ -693,6 +693,87 @@ START_TEST(time_conversion) } END_TEST +static int open_restricted_leak(const char *path, int flags, void *data) +{ + return *(int*)data; +} + +static void close_restricted_leak(int fd, void *data) +{ + /* noop */ +} + +const struct libinput_interface leak_interface = { + .open_restricted = open_restricted_leak, + .close_restricted = close_restricted_leak, +}; + +static void +simple_log_handler(struct libinput *libinput, + enum libinput_log_priority priority, + const char *format, + va_list args) +{ + vfprintf(stderr, format, args); +} + +START_TEST(fd_no_event_leak) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + int fd = -1; + const char *path; + struct libinput_event *event; + + uinput = create_simple_test_device("litest test device", + EV_REL, REL_X, + EV_REL, REL_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_LEFT, + -1, -1); + path = libevdev_uinput_get_devnode(uinput); + + fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC); + ck_assert_int_gt(fd, -1); + + li = libinput_path_create_context(&leak_interface, &fd); + libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG); + libinput_log_set_handler(li, simple_log_handler); + + /* Add the device, trigger an event, then remove it again. + * Without it, we get a SYN_DROPPED immediately and no events. + */ + device = libinput_path_add_device(li, path); + libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_path_remove_device(device); + libinput_dispatch(li); + litest_drain_events(li); + + /* Device is removed, but fd is still open. Queue an event, add a + * new device with the same fd, the queued event must be discarded + * by libinput */ + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, 1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + libinput_path_add_device(li, path); + libinput_dispatch(li); + event = libinput_get_event(li); + ck_assert_int_eq(libinput_event_get_type(event), + LIBINPUT_EVENT_DEVICE_ADDED); + libinput_event_destroy(event); + + litest_assert_empty_queue(li); + + close(fd); + libinput_unref(li); + libevdev_uinput_destroy(uinput); +} +END_TEST + void litest_setup_tests(void) { @@ -714,4 +795,6 @@ litest_setup_tests(void) litest_add_no_device("misc:parser", trackpoint_accel_parser); litest_add_no_device("misc:parser", dimension_prop_parser); litest_add_no_device("misc:time", time_conversion); + + litest_add_no_device("misc:fd", fd_no_event_leak); } From 7ca6a7b13cf92776846bef866e5d73beac43fc99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 22 Dec 2015 11:03:55 +1000 Subject: [PATCH 02/11] doc: add missing @config tag to libinput_config_send_event_modes Signed-off-by: Peter Hutterer --- src/libinput.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libinput.h b/src/libinput.h index 90574463..79d6e90b 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -2371,6 +2371,8 @@ libinput_device_config_calibration_get_default_matrix(struct libinput_device *de float matrix[6]); /** + * @ingroup config + * * The send-event mode of a device defines when a device may generate events * and pass those events to the caller. */ From a340736e9b9399f630ff4b436930c1dee26cb803 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 22 Dec 2015 11:18:07 +1000 Subject: [PATCH 03/11] configure.ac: libinput 1.1.4 Signed-off-by: Peter Hutterer --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 92f3e226..711aa42a 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], [1]) -m4_define([libinput_micro_version], [3]) +m4_define([libinput_micro_version], [4]) 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=16:3:6 +LIBINPUT_LT_VERSION=16:4:6 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes]) From b3f11180e337d6cd7fd997685b65e5ed48acc661 Mon Sep 17 00:00:00 2001 From: Caibin Chen Date: Sun, 13 Dec 2015 22:27:55 -0800 Subject: [PATCH 04/11] touchpad: fix DWT pairing for Macbook Pro 2015 Label internal keyboards through the udev hwdb and only pair the internal (usb) Apple touchpads with those keyboards labelled as such. https://bugs.freedesktop.org/show_bug.cgi?id=93367 Co-authored-by: Peter Hutterer Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 9 + src/evdev.c | 1 + src/evdev.h | 1 + src/libinput-util.h | 1 + test/Makefile.am | 1 + test/litest-device-apple-internal-keyboard.c | 239 +++++++++++++++++++ test/litest.c | 2 + test/litest.h | 1 + test/touchpad.c | 87 +++++-- udev/90-libinput-model-quirks.hwdb | 3 + 10 files changed, 328 insertions(+), 17 deletions(-) create mode 100644 test/litest-device-apple-internal-keyboard.c diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d78a54b0..aa123cd4 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1285,6 +1285,8 @@ tp_want_dwt(struct evdev_device *touchpad, { unsigned int bus_tp = libevdev_get_id_bustype(touchpad->evdev), bus_kbd = libevdev_get_id_bustype(keyboard->evdev); + unsigned int vendor_tp = evdev_device_get_id_vendor(touchpad); + unsigned int vendor_kbd = evdev_device_get_id_vendor(keyboard); if (tp_dwt_device_is_blacklisted(touchpad) || tp_dwt_device_is_blacklisted(keyboard)) @@ -1295,6 +1297,13 @@ tp_want_dwt(struct evdev_device *touchpad, if (bus_tp == BUS_I8042 && bus_kbd != bus_tp) return false; + /* For Apple touchpads, always use its internal keyboard */ + if (vendor_tp == VENDOR_ID_APPLE) { + return vendor_kbd == vendor_tp && + keyboard->model_flags & + EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD; + } + /* everything else we don't really know, so we have to assume they go together */ diff --git a/src/evdev.c b/src/evdev.c index 37080725..a6d8a604 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1662,6 +1662,7 @@ evdev_read_model_flags(struct evdev_device *device) { "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD }, { "LIBINPUT_MODEL_JUMPING_SEMI_MT", EVDEV_MODEL_JUMPING_SEMI_MT }, { "LIBINPUT_MODEL_ELANTECH_TOUCHPAD", EVDEV_MODEL_ELANTECH_TOUCHPAD }, + { "LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD", EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD }, { NULL, EVDEV_MODEL_DEFAULT }, }; const struct model_map *m = model_map; diff --git a/src/evdev.h b/src/evdev.h index 36bf7b42..97177ec2 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -108,6 +108,7 @@ enum evdev_device_model { EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10), EVDEV_MODEL_ELANTECH_TOUCHPAD = (1 << 11), EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12), + EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13), }; struct mt_slot { diff --git a/src/libinput-util.h b/src/libinput-util.h index a627e5d4..25de8e5d 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -38,6 +38,7 @@ #define VENDOR_ID_APPLE 0x5ac #define VENDOR_ID_WACOM 0x56a #define VENDOR_ID_SYNAPTICS_SERIAL 0x002 +#define PRODUCT_ID_APPLE_KBD_TOUCHPAD 0x273 #define PRODUCT_ID_SYNAPTICS_SERIAL 0x007 /* The HW DPI rate we normalize to before calculating pointer acceleration */ diff --git a/test/Makefile.am b/test/Makefile.am index e4ed8e5d..3b18cf46 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -15,6 +15,7 @@ liblitest_la_SOURCES = \ litest-int.h \ litest-device-alps-semi-mt.c \ litest-device-alps-dualpoint.c \ + litest-device-apple-internal-keyboard.c \ litest-device-asus-rog-gladius.c \ litest-device-atmel-hover.c \ litest-device-bcm5974.c \ diff --git a/test/litest-device-apple-internal-keyboard.c b/test/litest-device-apple-internal-keyboard.c new file mode 100644 index 00000000..c24403da --- /dev/null +++ b/test/litest-device-apple-internal-keyboard.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "litest.h" +#include "litest-int.h" + +static void litest_apple_keyboard_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_APPLE_KEYBOARD); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x3, + .vendor = 0x5ac, + .product = 0x273, +}; + +static int events[] = { + EV_KEY, KEY_ESC, + EV_KEY, KEY_1, + EV_KEY, KEY_2, + EV_KEY, KEY_3, + EV_KEY, KEY_4, + EV_KEY, KEY_5, + EV_KEY, KEY_6, + EV_KEY, KEY_7, + EV_KEY, KEY_8, + EV_KEY, KEY_9, + EV_KEY, KEY_0, + EV_KEY, KEY_MINUS, + EV_KEY, KEY_EQUAL, + EV_KEY, KEY_BACKSPACE, + EV_KEY, KEY_TAB, + EV_KEY, KEY_Q, + EV_KEY, KEY_W, + EV_KEY, KEY_E, + EV_KEY, KEY_R, + EV_KEY, KEY_T, + EV_KEY, KEY_Y, + EV_KEY, KEY_U, + EV_KEY, KEY_I, + EV_KEY, KEY_O, + EV_KEY, KEY_P, + EV_KEY, KEY_LEFTBRACE, + EV_KEY, KEY_RIGHTBRACE, + EV_KEY, KEY_ENTER, + EV_KEY, KEY_LEFTCTRL, + EV_KEY, KEY_A, + EV_KEY, KEY_S, + EV_KEY, KEY_D, + EV_KEY, KEY_F, + EV_KEY, KEY_G, + EV_KEY, KEY_H, + EV_KEY, KEY_J, + EV_KEY, KEY_K, + EV_KEY, KEY_L, + EV_KEY, KEY_SEMICOLON, + EV_KEY, KEY_APOSTROPHE, + EV_KEY, KEY_GRAVE, + EV_KEY, KEY_LEFTSHIFT, + EV_KEY, KEY_BACKSLASH, + EV_KEY, KEY_Z, + EV_KEY, KEY_X, + EV_KEY, KEY_C, + EV_KEY, KEY_V, + EV_KEY, KEY_B, + EV_KEY, KEY_N, + EV_KEY, KEY_M, + EV_KEY, KEY_COMMA, + EV_KEY, KEY_DOT, + EV_KEY, KEY_SLASH, + EV_KEY, KEY_RIGHTSHIFT, + EV_KEY, KEY_KPASTERISK, + EV_KEY, KEY_LEFTALT, + EV_KEY, KEY_SPACE, + EV_KEY, KEY_CAPSLOCK, + EV_KEY, KEY_F1, + EV_KEY, KEY_F2, + EV_KEY, KEY_F3, + EV_KEY, KEY_F4, + EV_KEY, KEY_F5, + EV_KEY, KEY_F6, + EV_KEY, KEY_F7, + EV_KEY, KEY_F8, + EV_KEY, KEY_F9, + EV_KEY, KEY_F10, + EV_KEY, KEY_NUMLOCK, + EV_KEY, KEY_SCROLLLOCK, + EV_KEY, KEY_KP7, + EV_KEY, KEY_KP8, + EV_KEY, KEY_KP9, + EV_KEY, KEY_KPMINUS, + EV_KEY, KEY_KP4, + EV_KEY, KEY_KP5, + EV_KEY, KEY_KP6, + EV_KEY, KEY_KPPLUS, + EV_KEY, KEY_KP1, + EV_KEY, KEY_KP2, + EV_KEY, KEY_KP3, + EV_KEY, KEY_KP0, + EV_KEY, KEY_KPDOT, + EV_KEY, KEY_ZENKAKUHANKAKU, + EV_KEY, KEY_102ND, + EV_KEY, KEY_F11, + EV_KEY, KEY_F12, + EV_KEY, KEY_RO, + EV_KEY, KEY_KATAKANA, + EV_KEY, KEY_HIRAGANA, + EV_KEY, KEY_HENKAN, + EV_KEY, KEY_KATAKANAHIRAGANA, + EV_KEY, KEY_MUHENKAN, + EV_KEY, KEY_KPJPCOMMA, + EV_KEY, KEY_KPENTER, + EV_KEY, KEY_RIGHTCTRL, + EV_KEY, KEY_KPSLASH, + EV_KEY, KEY_SYSRQ, + EV_KEY, KEY_RIGHTALT, + EV_KEY, KEY_HOME, + EV_KEY, KEY_UP, + EV_KEY, KEY_PAGEUP, + EV_KEY, KEY_LEFT, + EV_KEY, KEY_RIGHT, + EV_KEY, KEY_END, + EV_KEY, KEY_DOWN, + EV_KEY, KEY_PAGEDOWN, + EV_KEY, KEY_INSERT, + EV_KEY, KEY_DELETE, + EV_KEY, KEY_MUTE, + EV_KEY, KEY_VOLUMEDOWN, + EV_KEY, KEY_VOLUMEUP, + EV_KEY, KEY_POWER, + EV_KEY, KEY_KPEQUAL, + EV_KEY, KEY_PAUSE, + EV_KEY, KEY_SCALE, + EV_KEY, KEY_KPCOMMA, + EV_KEY, KEY_HANGEUL, + EV_KEY, KEY_HANJA, + EV_KEY, KEY_YEN, + EV_KEY, KEY_LEFTMETA, + EV_KEY, KEY_RIGHTMETA, + EV_KEY, KEY_COMPOSE, + EV_KEY, KEY_STOP, + EV_KEY, KEY_AGAIN, + EV_KEY, KEY_PROPS, + EV_KEY, KEY_UNDO, + EV_KEY, KEY_FRONT, + EV_KEY, KEY_COPY, + EV_KEY, KEY_OPEN, + EV_KEY, KEY_PASTE, + EV_KEY, KEY_FIND, + EV_KEY, KEY_CUT, + EV_KEY, KEY_HELP, + EV_KEY, KEY_CALC, + EV_KEY, KEY_SLEEP, + EV_KEY, KEY_WWW, + EV_KEY, KEY_COFFEE, + EV_KEY, KEY_BACK, + EV_KEY, KEY_FORWARD, + EV_KEY, KEY_EJECTCD, + EV_KEY, KEY_NEXTSONG, + EV_KEY, KEY_PLAYPAUSE, + EV_KEY, KEY_PREVIOUSSONG, + EV_KEY, KEY_STOPCD, + EV_KEY, KEY_REWIND, + EV_KEY, KEY_REFRESH, + EV_KEY, KEY_EDIT, + EV_KEY, KEY_SCROLLUP, + EV_KEY, KEY_SCROLLDOWN, + EV_KEY, KEY_KPLEFTPAREN, + EV_KEY, KEY_KPRIGHTPAREN, + EV_KEY, KEY_F13, + EV_KEY, KEY_F14, + EV_KEY, KEY_F15, + EV_KEY, KEY_F16, + EV_KEY, KEY_F17, + EV_KEY, KEY_F18, + EV_KEY, KEY_F19, + EV_KEY, KEY_F20, + EV_KEY, KEY_F21, + EV_KEY, KEY_F22, + EV_KEY, KEY_F23, + EV_KEY, KEY_F24, + EV_KEY, KEY_DASHBOARD, + EV_KEY, KEY_FASTFORWARD, + EV_KEY, KEY_BRIGHTNESSDOWN, + EV_KEY, KEY_BRIGHTNESSUP, + EV_KEY, KEY_SWITCHVIDEOMODE, + EV_KEY, KEY_KBDILLUMTOGGLE, + EV_KEY, KEY_KBDILLUMDOWN, + EV_KEY, KEY_KBDILLUMUP, + EV_KEY, KEY_UNKNOWN, + EV_KEY, KEY_FN, + EV_MSC, MSC_SCAN, + + EV_LED, LED_NUML, + EV_LED, LED_CAPSL, + EV_LED, LED_SCROLLL, + EV_LED, LED_COMPOSE, + EV_LED, LED_KANA, + -1, -1 +}; + +struct litest_test_device litest_apple_keyboard_device = { + .type = LITEST_APPLE_KEYBOARD, + .features = LITEST_KEYS, + .shortname = "apple_keyboard", + .setup = litest_apple_keyboard_setup, + .interface = NULL, + + .name = "Apple Inc. Apple Internal Keyboard / Trackpad", + .id = &input_id, + .events = events, + .absinfo = NULL, +}; diff --git a/test/litest.c b/test/litest.c index fc188b6a..0e3a815c 100644 --- a/test/litest.c +++ b/test/litest.c @@ -367,6 +367,7 @@ extern struct litest_test_device litest_magicpad_device; extern struct litest_test_device litest_elantech_touchpad_device; extern struct litest_test_device litest_mouse_gladius_device; extern struct litest_test_device litest_mouse_wheel_click_angle_device; +extern struct litest_test_device litest_apple_keyboard_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -400,6 +401,7 @@ struct litest_test_device* devices[] = { &litest_elantech_touchpad_device, &litest_mouse_gladius_device, &litest_mouse_wheel_click_angle_device, + &litest_apple_keyboard_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 1268e104..7cd550e2 100644 --- a/test/litest.h +++ b/test/litest.h @@ -144,6 +144,7 @@ enum litest_device_type { LITEST_ELANTECH_TOUCHPAD = -30, LITEST_MOUSE_GLADIUS = -31, LITEST_MOUSE_WHEEL_CLICK_ANGLE = -32, + LITEST_APPLE_KEYBOARD = -33, }; enum litest_device_feature { diff --git a/test/touchpad.c b/test/touchpad.c index dab2781e..4eb94187 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -2282,6 +2282,18 @@ has_disable_while_typing(struct litest_device *device) return libinput_device_config_dwt_is_available(device->libinput_device); } +static inline struct litest_device * +dwt_init_paired_keyboard(struct libinput *li, + struct litest_device *touchpad) +{ + enum litest_device_type which = LITEST_KEYBOARD; + + if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_APPLE) + which = LITEST_APPLE_KEYBOARD; + + return litest_add_device(li, which); +} + START_TEST(touchpad_dwt) { struct litest_device *touchpad = litest_current_device(); @@ -2291,7 +2303,7 @@ START_TEST(touchpad_dwt) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2333,7 +2345,7 @@ START_TEST(touchpad_dwt_enable_touch) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2371,7 +2383,7 @@ START_TEST(touchpad_dwt_touch_hold) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2408,7 +2420,7 @@ START_TEST(touchpad_dwt_key_hold) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2436,7 +2448,7 @@ START_TEST(touchpad_dwt_type) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2474,7 +2486,7 @@ START_TEST(touchpad_dwt_type_short_timeout) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2511,7 +2523,7 @@ START_TEST(touchpad_dwt_tap) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_enable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2541,7 +2553,7 @@ START_TEST(touchpad_dwt_tap_drag) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_enable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2575,7 +2587,7 @@ START_TEST(touchpad_dwt_click) if (!has_disable_while_typing(touchpad)) return; - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2608,7 +2620,7 @@ START_TEST(touchpad_dwt_edge_scroll) litest_enable_edge_scroll(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -2655,7 +2667,7 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt) litest_enable_edge_scroll(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_drain_events(li); litest_touch_down(touchpad, 0, 99, 20); @@ -2779,7 +2791,7 @@ START_TEST(touchpad_dwt_disabled) disable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2808,7 +2820,7 @@ START_TEST(touchpad_dwt_disable_during_touch) enable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2843,7 +2855,7 @@ START_TEST(touchpad_dwt_disable_before_touch) enable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2874,7 +2886,7 @@ START_TEST(touchpad_dwt_enable_during_touch) disable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2908,7 +2920,7 @@ START_TEST(touchpad_dwt_enable_before_touch) disable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); @@ -2939,7 +2951,7 @@ START_TEST(touchpad_dwt_enable_during_tap) litest_enable_tap(touchpad->libinput_device); disable_dwt(touchpad); - keyboard = litest_add_device(li, LITEST_KEYBOARD); + keyboard = dwt_init_paired_keyboard(li, touchpad); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -2964,6 +2976,46 @@ START_TEST(touchpad_dwt_enable_during_tap) litest_delete_device(keyboard); } END_TEST + +START_TEST(touchpad_dwt_apple) +{ + struct litest_device *touchpad = litest_current_device(); + struct litest_device *keyboard, *apple_keyboard; + struct libinput *li = touchpad->libinput; + + ck_assert(has_disable_while_typing(touchpad)); + + /* Only the apple keyboard can trigger DWT */ + keyboard = litest_add_device(li, LITEST_KEYBOARD); + litest_drain_events(li); + + litest_keyboard_key(keyboard, KEY_A, true); + litest_keyboard_key(keyboard, KEY_A, false); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + apple_keyboard = litest_add_device(li, LITEST_APPLE_KEYBOARD); + litest_drain_events(li); + + litest_keyboard_key(apple_keyboard, KEY_A, true); + litest_keyboard_key(apple_keyboard, KEY_A, false); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_delete_device(keyboard); + litest_delete_device(apple_keyboard); +} +END_TEST + static int has_thumb_detect(struct litest_device *dev) { @@ -3632,6 +3684,7 @@ litest_setup_tests(void) litest_add("touchpad:dwt", touchpad_dwt_enable_during_touch, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:dwt", touchpad_dwt_enable_before_touch, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:dwt", touchpad_dwt_enable_during_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_for_device("touchpad:dwt", touchpad_dwt_apple, LITEST_BCM5974); litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_CLICKPAD, LITEST_ANY); diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 814ec401..baebcb3d 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -34,6 +34,9 @@ libinput:touchpad:input:b0005v05ACp* LIBINPUT_MODEL_APPLE_TOUCHPAD=1 LIBINPUT_ATTR_SIZE_HINT=104x75 +libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:* + LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD=1 + ########################################## # Elantech ########################################## From fec99a28e3c93d2eafa7a5164f381e7230b9e897 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 5 Jan 2016 16:11:09 +1000 Subject: [PATCH 05/11] tools: print the button name too, not just the code new output: event4 POINTER_BUTTON +0.84s BTN_RIGHT (273) released, seat count: 0 Signed-off-by: Peter Hutterer --- tools/event-debug.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/event-debug.c b/tools/event-debug.c index 23e6cf92..ece58888 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -255,12 +255,18 @@ print_button_event(struct libinput_event *ev) { struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); enum libinput_button_state state; + const char *buttonname; + int button; print_event_time(libinput_event_pointer_get_time(p)); + button = libinput_event_pointer_get_button(p); + buttonname = libevdev_event_code_get_name(EV_KEY, button); + state = libinput_event_pointer_get_button_state(p); - printf("%3d %s, seat count: %u\n", - libinput_event_pointer_get_button(p), + printf("%s (%d) %s, seat count: %u\n", + buttonname ? buttonname : "???", + button, state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released", libinput_event_pointer_get_seat_button_count(p)); } From 988cfda42c5613edb871d0ee7a2332fc9668c84c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 23 Dec 2015 15:15:29 +1000 Subject: [PATCH 06/11] evdev: only reject devices with missing MT x/y if they're MT devices A fake MT device may have ABS_MT_POSITION_X but not Y. In this case we don't care, because we don't handle those axes anyway. http://bugs.freedesktop.org/show_bug.cgi?id=93474 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 3 +- test/Makefile.am | 1 + test/device.c | 31 ++++ test/litest-device-anker-mouse-kbd.c | 225 +++++++++++++++++++++++++++ test/litest.c | 2 + test/litest.h | 1 + 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 test/litest-device-anker-mouse-kbd.c diff --git a/src/evdev.c b/src/evdev.c index a6d8a604..430d7de2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1869,7 +1869,8 @@ evdev_reject_device(struct evdev_device *device) libevdev_has_event_code(evdev, EV_REL, REL_Y)) return -1; - if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ^ + if (!evdev_is_fake_mt_device(device) && + libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ^ libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) return -1; diff --git a/test/Makefile.am b/test/Makefile.am index 3b18cf46..4c394bf9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -15,6 +15,7 @@ liblitest_la_SOURCES = \ litest-int.h \ litest-device-alps-semi-mt.c \ litest-device-alps-dualpoint.c \ + litest-device-anker-mouse-kbd.c \ litest-device-apple-internal-keyboard.c \ litest-device-asus-rog-gladius.c \ litest-device-atmel-hover.c \ diff --git a/test/device.c b/test/device.c index b7fa0e07..03659ace 100644 --- a/test/device.c +++ b/test/device.c @@ -1254,6 +1254,35 @@ START_TEST(device_abs_rel) } END_TEST +START_TEST(device_quirks_no_abs_mt_y) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *pev; + int code; + + litest_drain_events(li); + + litest_event(dev, EV_REL, REL_HWHEEL, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + event = libinput_get_event(li); + pev = litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + LIBINPUT_POINTER_AXIS_SOURCE_WHEEL); + libinput_event_destroy(libinput_event_pointer_get_base_event(pev)); + + for (code = ABS_MISC + 1; code < ABS_MAX; code++) { + litest_event(dev, EV_ABS, code, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_assert_empty_queue(li); + } + +} +END_TEST + void litest_setup_tests(void) { @@ -1308,4 +1337,6 @@ litest_setup_tests(void) litest_add_no_device("device:invalid rel events", device_touchpad_rel); litest_add_no_device("device:invalid rel events", device_touch_rel); litest_add_no_device("device:invalid rel events", device_abs_rel); + + litest_add_for_device("device:quirks", device_quirks_no_abs_mt_y, LITEST_ANKER_MOUSE_KBD); } diff --git a/test/litest-device-anker-mouse-kbd.c b/test/litest-device-anker-mouse-kbd.c new file mode 100644 index 00000000..5f399289 --- /dev/null +++ b/test/litest-device-anker-mouse-kbd.c @@ -0,0 +1,225 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "litest.h" +#include "litest-int.h" + +/* Recording from https://bugs.freedesktop.org/show_bug.cgi?id=93474 + * This is the keyboard device for this mouse. + */ + +static void litest_anker_mouse_kbd_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_ANKER_MOUSE_KBD); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x3, + .vendor = 0x4d9, + .product = 0xfa50, +}; + +static int events[] = { + EV_REL, REL_HWHEEL, + EV_KEY, KEY_ESC, + EV_KEY, KEY_KPMINUS, + EV_KEY, KEY_KPPLUS, + EV_KEY, KEY_UP, + EV_KEY, KEY_PAGEUP, + EV_KEY, KEY_LEFT, + EV_KEY, KEY_RIGHT, + EV_KEY, KEY_END, + EV_KEY, KEY_DOWN, + EV_KEY, KEY_PAGEDOWN, + EV_KEY, KEY_INSERT, + EV_KEY, KEY_DELETE, + EV_KEY, KEY_MUTE, + EV_KEY, KEY_VOLUMEDOWN, + EV_KEY, KEY_VOLUMEUP, + EV_KEY, KEY_POWER, + EV_KEY, KEY_PAUSE, + EV_KEY, KEY_STOP, + EV_KEY, KEY_PROPS, + EV_KEY, KEY_UNDO, + EV_KEY, KEY_COPY, + EV_KEY, KEY_OPEN, + EV_KEY, KEY_PASTE, + EV_KEY, KEY_FIND, + EV_KEY, KEY_CUT, + EV_KEY, KEY_HELP, + EV_KEY, KEY_MENU, + EV_KEY, KEY_CALC, + EV_KEY, KEY_SLEEP, + EV_KEY, KEY_WAKEUP, + EV_KEY, KEY_FILE, + EV_KEY, KEY_WWW, + EV_KEY, KEY_COFFEE, + EV_KEY, KEY_MAIL, + EV_KEY, KEY_BOOKMARKS, + EV_KEY, KEY_BACK, + EV_KEY, KEY_FORWARD, + EV_KEY, KEY_EJECTCD, + EV_KEY, KEY_NEXTSONG, + EV_KEY, KEY_PLAYPAUSE, + EV_KEY, KEY_PREVIOUSSONG, + EV_KEY, KEY_STOPCD, + EV_KEY, KEY_RECORD, + EV_KEY, KEY_REWIND, + EV_KEY, KEY_PHONE, + EV_KEY, KEY_CONFIG, + EV_KEY, KEY_HOMEPAGE, + EV_KEY, KEY_REFRESH, + EV_KEY, KEY_EXIT, + EV_KEY, KEY_EDIT, + EV_KEY, KEY_SCROLLUP, + EV_KEY, KEY_SCROLLDOWN, + EV_KEY, KEY_NEW, + EV_KEY, KEY_REDO, + EV_KEY, KEY_CLOSE, + EV_KEY, KEY_PLAY, + EV_KEY, KEY_FASTFORWARD, + EV_KEY, KEY_BASSBOOST, + EV_KEY, KEY_PRINT, + EV_KEY, KEY_CAMERA, + EV_KEY, KEY_CHAT, + EV_KEY, KEY_SEARCH, + EV_KEY, KEY_FINANCE, + EV_KEY, KEY_BRIGHTNESSDOWN, + EV_KEY, KEY_BRIGHTNESSUP, + EV_KEY, KEY_KBDILLUMTOGGLE, + EV_KEY, KEY_SAVE, + EV_KEY, KEY_DOCUMENTS, + EV_KEY, KEY_UNKNOWN, + EV_KEY, KEY_VIDEO_NEXT, + EV_KEY, KEY_BRIGHTNESS_AUTO, + EV_KEY, BTN_0, + EV_KEY, KEY_SELECT, + EV_KEY, KEY_GOTO, + EV_KEY, KEY_INFO, + EV_KEY, KEY_PROGRAM, + EV_KEY, KEY_PVR, + EV_KEY, KEY_SUBTITLE, + EV_KEY, KEY_ZOOM, + EV_KEY, KEY_KEYBOARD, + EV_KEY, KEY_PC, + EV_KEY, KEY_TV, + EV_KEY, KEY_TV2, + EV_KEY, KEY_VCR, + EV_KEY, KEY_VCR2, + EV_KEY, KEY_SAT, + EV_KEY, KEY_CD, + EV_KEY, KEY_TAPE, + EV_KEY, KEY_TUNER, + EV_KEY, KEY_PLAYER, + EV_KEY, KEY_DVD, + EV_KEY, KEY_AUDIO, + EV_KEY, KEY_VIDEO, + EV_KEY, KEY_MEMO, + EV_KEY, KEY_CALENDAR, + EV_KEY, KEY_RED, + EV_KEY, KEY_GREEN, + EV_KEY, KEY_YELLOW, + EV_KEY, KEY_BLUE, + EV_KEY, KEY_CHANNELUP, + EV_KEY, KEY_CHANNELDOWN, + EV_KEY, KEY_LAST, + EV_KEY, KEY_NEXT, + EV_KEY, KEY_RESTART, + EV_KEY, KEY_SLOW, + EV_KEY, KEY_SHUFFLE, + EV_KEY, KEY_PREVIOUS, + EV_KEY, KEY_VIDEOPHONE, + EV_KEY, KEY_GAMES, + EV_KEY, KEY_ZOOMIN, + EV_KEY, KEY_ZOOMOUT, + EV_KEY, KEY_ZOOMRESET, + EV_KEY, KEY_WORDPROCESSOR, + EV_KEY, KEY_EDITOR, + EV_KEY, KEY_SPREADSHEET, + EV_KEY, KEY_GRAPHICSEDITOR, + EV_KEY, KEY_PRESENTATION, + EV_KEY, KEY_DATABASE, + EV_KEY, KEY_NEWS, + EV_KEY, KEY_VOICEMAIL, + EV_KEY, KEY_ADDRESSBOOK, + EV_KEY, KEY_MESSENGER, + EV_KEY, KEY_DISPLAYTOGGLE, + EV_KEY, KEY_SPELLCHECK, + EV_KEY, KEY_LOGOFF, + EV_KEY, KEY_MEDIA_REPEAT, + EV_KEY, KEY_IMAGES, + EV_KEY, KEY_BUTTONCONFIG, + EV_KEY, KEY_TASKMANAGER, + EV_KEY, KEY_JOURNAL, + EV_KEY, KEY_CONTROLPANEL, + EV_KEY, KEY_APPSELECT, + EV_KEY, KEY_SCREENSAVER, + EV_KEY, KEY_VOICECOMMAND, + EV_KEY, KEY_BRIGHTNESS_MIN, + EV_KEY, KEY_BRIGHTNESS_MAX, + EV_KEY, KEY_KBDINPUTASSIST_PREV, + EV_KEY, KEY_KBDINPUTASSIST_NEXT, + EV_KEY, KEY_KBDINPUTASSIST_PREVGROUP, + EV_KEY, KEY_KBDINPUTASSIST_NEXTGROUP, + EV_KEY, KEY_KBDINPUTASSIST_ACCEPT, + EV_KEY, KEY_KBDINPUTASSIST_CANCEL, + EV_MSC, MSC_SCAN, + -1 , -1, +}; + +static struct input_absinfo absinfo[] = { + { ABS_VOLUME, 0, 4096, 0, 0, 0 }, + { ABS_MISC, 0, 255, 0, 0, 0 }, + { 0x29, 0, 255, 0, 0, 0 }, + { 0x2a, 0, 255, 0, 0, 0 }, + { 0x2b, 0, 255, 0, 0, 0 }, + { 0x2c, 0, 255, 0, 0, 0 }, + { 0x2d, 0, 255, 0, 0, 0 }, + { 0x2e, 0, 255, 0, 0, 0 }, + { ABS_MT_SLOT, 0, 255, 0, 0, 0 }, + { ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0, 0 }, + { ABS_MT_TOUCH_MINOR, 0, 255, 0, 0, 0 }, + { ABS_MT_WIDTH_MINOR, 0, 255, 0, 0, 0 }, + { ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0, 0 }, + { ABS_MT_ORIENTATION, 0, 255, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 255, 0, 0, 0 }, + { .value = -1 }, +}; + +struct litest_test_device litest_anker_mouse_kbd_device = { + .type = LITEST_ANKER_MOUSE_KBD, + .features = LITEST_KEYS | LITEST_WHEEL, + .shortname = "anker_kbd", + .setup = litest_anker_mouse_kbd_setup, + .interface = NULL, + + .name = "USB Laser Game Mouse", + .id = &input_id, + .absinfo = absinfo, + .events = events, +}; diff --git a/test/litest.c b/test/litest.c index 0e3a815c..cc348e9e 100644 --- a/test/litest.c +++ b/test/litest.c @@ -368,6 +368,7 @@ extern struct litest_test_device litest_elantech_touchpad_device; extern struct litest_test_device litest_mouse_gladius_device; extern struct litest_test_device litest_mouse_wheel_click_angle_device; extern struct litest_test_device litest_apple_keyboard_device; +extern struct litest_test_device litest_anker_mouse_kbd_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -402,6 +403,7 @@ struct litest_test_device* devices[] = { &litest_mouse_gladius_device, &litest_mouse_wheel_click_angle_device, &litest_apple_keyboard_device, + &litest_anker_mouse_kbd_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 7cd550e2..e74e923b 100644 --- a/test/litest.h +++ b/test/litest.h @@ -145,6 +145,7 @@ enum litest_device_type { LITEST_MOUSE_GLADIUS = -31, LITEST_MOUSE_WHEEL_CLICK_ANGLE = -32, LITEST_APPLE_KEYBOARD = -33, + LITEST_ANKER_MOUSE_KBD = -34, }; enum litest_device_feature { From 52b8874ecc78a60239aa7df2c0f1885af91fd5d5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 12 Jan 2016 12:16:25 +1000 Subject: [PATCH 07/11] touchpad: drop outdated comment Obsolete comment since 4ca70c813f750721592d1a68aced385560705256, we rely on the udev hwdb to set the resolution for us. Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index aa123cd4..2de2539f 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1780,8 +1780,7 @@ tp_init_palmdetect(struct tp_dispatch *tp, width = device->abs.dimensions.x; height = device->abs.dimensions.y; - /* Wacom doesn't have internal touchpads, - * Apple touchpads are always big enough to warrant palm detection */ + /* Wacom doesn't have internal touchpads */ if (device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD) return 0; From ea8fff291b3bc75ad1934e234a327e22ccd1de7e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 13 Jan 2016 08:48:12 +1000 Subject: [PATCH 08/11] touchpad: whitespace fix Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index f42fb02d..b5e0e8ec 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -396,6 +396,7 @@ struct normalized_coords tp_filter_motion(struct tp_dispatch *tp, const struct normalized_coords *unaccelerated, uint64_t time); + struct normalized_coords tp_filter_motion_unaccelerated(struct tp_dispatch *tp, const struct normalized_coords *unaccelerated, From 41cc9053dd87e8b2be89187b73312d85a010c4ef Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 13 Jan 2016 11:50:21 +1000 Subject: [PATCH 09/11] doc: add section names to motion normalization subheaders Otherwise the first word is used as section header and discarded from the output. Signed-off-by: Peter Hutterer --- doc/normalization-of-relative-motion.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/normalization-of-relative-motion.dox b/doc/normalization-of-relative-motion.dox index 31596a93..d0a42e03 100644 --- a/doc/normalization-of-relative-motion.dox +++ b/doc/normalization-of-relative-motion.dox @@ -28,7 +28,7 @@ This normalization only applies to accelerated coordinates, unaccelerated coordinates are left in device-units. It is up to the caller to interpret those coordinates correctly. -@section Normalization of touchpad coordinates +@section motion_normalization_touchpad Normalization of touchpad coordinates Touchpads may have a different resolution for the horizontal and vertical axis. Interpreting coordinates from the touchpad without taking resolution @@ -38,7 +38,7 @@ libinput scales unaccelerated touchpad motion to the resolution of the touchpad's x axis, i.e. the unaccelerated value for the y axis is: y = (x / resolution_x) * resolution_y -@section Setting custom DPI settings +@section motion_normalization_customization Setting custom DPI settings Devices usually do not advertise their resolution and libinput relies on the udev property MOUSE_DPI for this information. This property is usually From 556aac04b5d56f015d5da8b96e24fd78ad231760 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 12 Jan 2016 12:24:18 +1000 Subject: [PATCH 10/11] touchpad: disable MT for elantech semi-mt touchpads When three fingers are set down on the touchpad, one finger tends to get a 0/0 coordinate, triggering palm detection in the upper left corner. Handle this like the jumping semi-mt touchpads and disable MT handling and instead just rely on the x/y axis and the BTN_TOOL_* events. https://bugs.freedesktop.org/show_bug.cgi?id=93583 This kernel patch is required: https://lkml.org/lkml/2016/1/11/171 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 2de2539f..f91f8392 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1496,7 +1496,8 @@ tp_init_slots(struct tp_dispatch *tp, * explanation. */ if (tp->semi_mt && - (device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT)) { + (device->model_flags & + (EVDEV_MODEL_JUMPING_SEMI_MT|EVDEV_MODEL_ELANTECH_TOUCHPAD))) { tp->num_slots = 1; tp->slot = 0; tp->has_mt = false; From 999cbc8933c6b01d5045afed8203aeba7dfdcb6f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 18 Jan 2016 16:44:28 +1000 Subject: [PATCH 11/11] touchpad: drop the model detection - write-only value Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 36 ------------------------------------ src/evdev-mt-touchpad.h | 1 - 2 files changed, 37 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index f91f8392..6f834fb1 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -2094,40 +2094,6 @@ tp_change_to_left_handed(struct evdev_device *device) device->left_handed.enabled = device->left_handed.want_enabled; } -struct model_lookup_t { - uint16_t vendor; - uint16_t product_start; - uint16_t product_end; - enum touchpad_model model; -}; - -static struct model_lookup_t model_lookup_table[] = { - { 0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS }, - { 0x0002, 0x0008, 0x0008, MODEL_ALPS }, - { 0x0002, 0x000e, 0x000e, MODEL_ELANTECH }, - { 0x05ac, 0, 0x0222, MODEL_APPLETOUCH }, - { 0x05ac, 0x0223, 0x0228, MODEL_UNIBODY_MACBOOK }, - { 0x05ac, 0x0229, 0x022b, MODEL_APPLETOUCH }, - { 0x05ac, 0x022c, 0xffff, MODEL_UNIBODY_MACBOOK }, - { 0, 0, 0, 0 } -}; - -static enum touchpad_model -tp_get_model(struct evdev_device *device) -{ - struct model_lookup_t *lookup; - uint16_t vendor = libevdev_get_id_vendor(device->evdev); - uint16_t product = libevdev_get_id_product(device->evdev); - - for (lookup = model_lookup_table; lookup->vendor; lookup++) { - if (lookup->vendor == vendor && - lookup->product_start <= product && - product <= lookup->product_end) - return lookup->model; - } - return MODEL_UNKNOWN; -} - struct evdev_dispatch * evdev_mt_touchpad_create(struct evdev_device *device) { @@ -2137,8 +2103,6 @@ evdev_mt_touchpad_create(struct evdev_device *device) if (!tp) return NULL; - tp->model = tp_get_model(device); - if (tp_init(tp, device) != 0) { tp_interface_destroy(&tp->base); return NULL; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index b5e0e8ec..eb6702d3 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -227,7 +227,6 @@ struct tp_dispatch { bool has_mt; bool semi_mt; bool reports_distance; /* does the device support true hovering */ - enum touchpad_model model; unsigned int num_slots; /* number of slots */ unsigned int ntouches; /* no slots inc. fakes */