diff --git a/meson.build b/meson.build index d32b1ea35..a866217bf 100644 --- a/meson.build +++ b/meson.build @@ -767,6 +767,7 @@ if get_option('tests') litest_sources = [ 'test/litest.h', 'test/litest-int.h', + 'test/litest-device-absinfo-override.c', 'test/litest-device-acer-hawaii-keyboard.c', 'test/litest-device-acer-hawaii-touchpad.c', 'test/litest-device-aiptek-tablet.c', diff --git a/test/litest-device-absinfo-override.c b/test/litest-device-absinfo-override.c new file mode 100644 index 000000000..ce8586e46 --- /dev/null +++ b/test/litest-device-absinfo-override.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2020 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. + */ + +#include "config.h" + +#include "litest.h" +#include "litest-int.h" + +static struct input_id input_id = { + .bustype = 0x11, + .vendor = 0x1234, + .product = 0x4567, +}; + +static int events[] = { + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_TOOL_DOUBLETAP, + EV_KEY, BTN_TOOL_TRIPLETAP, + EV_KEY, BTN_TOOL_QUADTAP, + INPUT_PROP_MAX, INPUT_PROP_POINTER, + -1 , -1, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, 0, 2000, 0, 0, 0 }, + { ABS_Y, 0, 1400, 0, 0, 0 }, + { ABS_PRESSURE, 0, 127, 0, 0, 0 }, + { ABS_MT_SLOT, 0, 1, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 2000, 0, 0, 0 }, + { ABS_MT_POSITION_Y, 0, 1400, 0, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 }, + { .value = -1 } +}; + +/* This device only exists to verify that the EVDEV_ABS override bits work + * correctly */ +TEST_DEVICE("absinfo-override", + .type = LITEST_ABSINFO_OVERRIDE, + .features = LITEST_IGNORED, + .interface = NULL, + + .name = "absinfo override", + .id = &input_id, + .absinfo = absinfo, + .events = events, + .udev_properties = { + { "EVDEV_ABS_00", "1:1000:100:10" }, + { "EVDEV_ABS_01", "2:2000:200:20" }, + { "EVDEV_ABS_35", "3:3000:300:30" }, + { "EVDEV_ABS_36", "4:4000:400:40" }, + { NULL }, + }, +) diff --git a/test/litest.c b/test/litest.c index 8d7875c2f..783c13800 100644 --- a/test/litest.c +++ b/test/litest.c @@ -692,6 +692,7 @@ litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f) { const struct key_value_str *kv; static int count; + bool need_keyboard_builtin = false; if (dev->udev_properties[0].key == NULL) return; @@ -707,10 +708,27 @@ litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f) kv = dev->udev_properties; while (kv->key) { fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value); + if (strneq(kv->key, "EVDEV_ABS_", 10)) + need_keyboard_builtin = true; kv++; } - fprintf(f, "\n"); + + /* Special case: the udev keyboard builtin is only run for hwdb + * matches but we don't set any up in litest. So instead scan the + * device's udev properties for any EVDEV_ABS properties and where + * they exist, force a (re-)run of the keyboard builtin to set up + * the evdev device correctly. + * This needs to be done as separate rule apparently, otherwise the + * ENV variables aren't set yet by the time the builtin runs. + */ + if (need_keyboard_builtin) { + fprintf(f, "" + "ATTRS{name}==\"litest %s*\"," + " IMPORT{builtin}+=\"keyboard\"\n", + dev->name); + } + fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);; } diff --git a/test/litest.h b/test/litest.h index e145f3a84..20a3c9219 100644 --- a/test/litest.h +++ b/test/litest.h @@ -302,6 +302,7 @@ enum litest_device_type { LITEST_WACOM_ISDV4_4200_PEN, LITEST_ALPS_3FG, LITEST_ELAN_TABLET, + LITEST_ABSINFO_OVERRIDE, }; #define LITEST_DEVICELESS -2 diff --git a/test/test-misc.c b/test/test-misc.c index b131cde97..901b6d4e2 100644 --- a/test/test-misc.c +++ b/test/test-misc.c @@ -760,6 +760,84 @@ START_TEST(timer_flush) } END_TEST +START_TEST(udev_absinfo_override) +{ + struct litest_device *dev = litest_current_device(); + struct libevdev *evdev = dev->evdev; + const struct input_absinfo *abs; + struct udev_device *ud; + struct udev_list_entry *entry; + bool found_x = false, found_y = false, + found_mt_x = false, found_mt_y = false; + + ud = libinput_device_get_udev_device(dev->libinput_device); + ck_assert_notnull(ud); + + /* Custom checks for this special litest device only */ + + entry = udev_device_get_properties_list_entry(ud); + while (entry) { + const char *key, *value; + + key = udev_list_entry_get_name(entry); + value = udev_list_entry_get_value(entry); + + if (streq(key, "EVDEV_ABS_00")) { + found_x = true; + ck_assert(streq(value, "1:1000:100:10")); + } + if (streq(key, "EVDEV_ABS_01")) { + found_y = true; + ck_assert(streq(value, "2:2000:200:20")); + } + if (streq(key, "EVDEV_ABS_35")) { + found_mt_x = true; + ck_assert(streq(value, "3:3000:300:30")); + } + if (streq(key, "EVDEV_ABS_36")) { + found_mt_y = true; + ck_assert(streq(value, "4:4000:400:40")); + } + + entry = udev_list_entry_get_next(entry); + } + udev_device_unref(ud); + + ck_assert(found_x); + ck_assert(found_y); + ck_assert(found_mt_x); + ck_assert(found_mt_y); + + abs = libevdev_get_abs_info(evdev, ABS_X); + ck_assert_int_eq(abs->minimum, 1); + ck_assert_int_eq(abs->maximum, 1000); + ck_assert_int_eq(abs->resolution, 100); + /* if everything goes well, we override the fuzz to 0 */ + ck_assert_int_eq(abs->fuzz, 0); + + abs = libevdev_get_abs_info(evdev, ABS_Y); + ck_assert_int_eq(abs->minimum, 2); + ck_assert_int_eq(abs->maximum, 2000); + ck_assert_int_eq(abs->resolution, 200); + /* if everything goes well, we override the fuzz to 0 */ + ck_assert_int_eq(abs->fuzz, 0); + + abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); + ck_assert_int_eq(abs->minimum, 3); + ck_assert_int_eq(abs->maximum, 3000); + ck_assert_int_eq(abs->resolution, 300); + /* if everything goes well, we override the fuzz to 0 */ + ck_assert_int_eq(abs->fuzz, 0); + + abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); + ck_assert_int_eq(abs->minimum, 4); + ck_assert_int_eq(abs->maximum, 4000); + ck_assert_int_eq(abs->resolution, 400); + /* if everything goes well, we override the fuzz to 0 */ + ck_assert_int_eq(abs->fuzz, 0); +} +END_TEST + TEST_COLLECTION(misc) { litest_add_no_device("events:conversion", event_conversion_device_notify); @@ -780,4 +858,6 @@ TEST_COLLECTION(misc) litest_add_no_device("timer:flush", timer_flush); litest_add_no_device("misc:fd", fd_no_event_leak); + + litest_add_for_device("misc:system", udev_absinfo_override, LITEST_ABSINFO_OVERRIDE); }