diff options
-rw-r--r-- | src/evdev-lid.c | 22 | ||||
-rw-r--r-- | src/libinput-util.c | 2 | ||||
-rw-r--r-- | src/libinput-util.h | 1 | ||||
-rw-r--r-- | test/Makefile.am | 1 | ||||
-rw-r--r-- | test/litest-device-lid-switch-surface3.c | 71 | ||||
-rw-r--r-- | test/litest.c | 2 | ||||
-rw-r--r-- | test/litest.h | 1 | ||||
-rw-r--r-- | test/test-lid.c | 98 | ||||
-rw-r--r-- | udev/90-libinput-model-quirks.hwdb | 24 | ||||
-rwxr-xr-x | udev/parse_hwdb.py | 4 |
10 files changed, 215 insertions, 11 deletions
diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 9029838..c5af753 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -31,6 +31,7 @@ struct lid_switch_dispatch { struct evdev_dispatch base; struct evdev_device *device; + enum switch_reliability reliability; bool lid_is_closed; @@ -54,6 +55,18 @@ lid_switch_keyboard_event(uint64_t time, if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) return; + if (dispatch->reliability == RELIABILITY_WRITE_OPEN) { + int fd = libevdev_get_fd(dispatch->device->evdev); + struct input_event ev[2] = { + {{ 0, 0 }, EV_SW, SW_LID, 0 }, + {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 }, + }; + + (void)write(fd, ev, sizeof(ev)); + /* In case write() fails, we sync the lid state manually + * regardless. */ + } + dispatch->lid_is_closed = false; switch_notify_toggle(&dispatch->device->base, time, @@ -143,6 +156,10 @@ evdev_read_switch_reliability_prop(struct evdev_device *device) device->devname, prop); r = RELIABILITY_UNKNOWN; + } else if (r == RELIABILITY_WRITE_OPEN) { + log_info(evdev_libinput_context(device), + "%s: will write switch open events\n", + device->devname); } return r; @@ -216,6 +233,8 @@ lid_switch_sync_initial_state(struct evdev_device *device, struct libevdev *evdev = device->evdev; bool is_closed = false; + dispatch->reliability = evdev_read_switch_reliability_prop(device); + /* For the initial state sync, we depend on whether the lid switch * is reliable. If we know it's reliable, we sync as expected. * If we're not sure, we ignore the initial state and only sync on @@ -223,8 +242,9 @@ lid_switch_sync_initial_state(struct evdev_device *device, * that always have the switch in 'on' state thus don't mess up our * touchpad. */ - switch(evdev_read_switch_reliability_prop(device)) { + switch(dispatch->reliability) { case RELIABILITY_UNKNOWN: + case RELIABILITY_WRITE_OPEN: is_closed = false; break; case RELIABILITY_RELIABLE: diff --git a/src/libinput-util.c b/src/libinput-util.c index f5d0aa7..aa69a37 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -289,6 +289,8 @@ parse_switch_reliability_property(const char *prop, if (streq(prop, "reliable")) *reliability = RELIABILITY_RELIABLE; + else if (streq(prop, "write_open")) + *reliability = RELIABILITY_WRITE_OPEN; else return false; diff --git a/src/libinput-util.h b/src/libinput-util.h index ce3a5ac..1d03ce1 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -380,6 +380,7 @@ bool parse_dimension_property(const char *prop, size_t *width, size_t *height); enum switch_reliability { RELIABILITY_UNKNOWN, RELIABILITY_RELIABLE, + RELIABILITY_WRITE_OPEN, }; bool diff --git a/test/Makefile.am b/test/Makefile.am index ce1973f..2e565de 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -33,6 +33,7 @@ liblitest_la_SOURCES = \ litest-device-keyboard-all-codes.c \ litest-device-keyboard-razer-blackwidow.c \ litest-device-lid-switch.c \ + litest-device-lid-switch-surface3.c \ litest-device-logitech-trackball.c \ litest-device-nexus4-touch-screen.c \ litest-device-magic-trackpad.c \ diff --git a/test/litest-device-lid-switch-surface3.c b/test/litest-device-lid-switch-surface3.c new file mode 100644 index 0000000..fde15c2 --- /dev/null +++ b/test/litest-device-lid-switch-surface3.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2017 James Ye <jye836@gmail.com> + * Copyright © 2017 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 void +litest_lid_switch_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_LID_SWITCH_SURFACE3); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x19, + .vendor = 0x0, + .product = 0x5, +}; + +static int events[] = { + EV_SW, SW_LID, + -1, -1, +}; + +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"switch_end\"\n" +"KERNEL!=\"event*\", GOTO=\"switch_end\"\n" +"\n" +"ATTRS{name}==\"litest Lid Switch Surface3*\",\\\n" +" ENV{ID_INPUT_SWITCH}=\"1\",\\\n" +" ENV{LIBINPUT_ATTR_LID_SWITCH_RELIABILITY}=\"write_open\"\n" +"\n" +"LABEL=\"switch_end\""; + +struct litest_test_device litest_lid_switch_surface3_device = { + .type = LITEST_LID_SWITCH_SURFACE3, + .features = LITEST_SWITCH, + .shortname = "lid-switch-surface3", + .setup = litest_lid_switch_setup, + .interface = NULL, + + .name = "Lid Switch Surface3", + .id = &input_id, + .events = events, + .absinfo = NULL, + + .udev_rule = udev_rule, +}; diff --git a/test/litest.c b/test/litest.c index 7a5ec57..1756940 100644 --- a/test/litest.c +++ b/test/litest.c @@ -409,6 +409,7 @@ extern struct litest_test_device litest_acer_hawaii_touchpad_device; extern struct litest_test_device litest_synaptics_rmi4_device; extern struct litest_test_device litest_mouse_wheel_tilt_device; extern struct litest_test_device litest_lid_switch_device; +extern struct litest_test_device litest_lid_switch_surface3_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -472,6 +473,7 @@ struct litest_test_device* devices[] = { &litest_synaptics_rmi4_device, &litest_mouse_wheel_tilt_device, &litest_lid_switch_device, + &litest_lid_switch_surface3_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 0075604..d779f0f 100644 --- a/test/litest.h +++ b/test/litest.h @@ -230,6 +230,7 @@ enum litest_device_type { LITEST_SYNAPTICS_RMI4, LITEST_MOUSE_WHEEL_TILT, LITEST_LID_SWITCH, + LITEST_LID_SWITCH_SURFACE3, }; enum litest_device_feature { diff --git a/test/test-lid.c b/test/test-lid.c index 6577d23..a5f439a 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -87,12 +87,32 @@ START_TEST(lid_switch_double) } END_TEST +static bool +lid_switch_is_reliable(struct litest_device *dev) +{ + struct udev_device *udev_device; + const char *prop; + bool is_reliable = false; + + udev_device = libinput_device_get_udev_device(dev->libinput_device); + prop = udev_device_get_property_value(udev_device, + "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY"); + + is_reliable = prop && streq(prop, "reliable"); + udev_device_unref(udev_device); + + return is_reliable; +} + START_TEST(lid_switch_down_on_init) { struct litest_device *sw = litest_current_device(); struct libinput *li; struct libinput_event *event; + if (!lid_switch_is_reliable(sw)) + return; + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); /* need separate context to test */ @@ -128,6 +148,35 @@ START_TEST(lid_switch_down_on_init) } END_TEST +START_TEST(lid_switch_not_down_on_init) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li; + struct libinput_event *event; + + if (lid_switch_is_reliable(sw)) + return; + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + + /* need separate context to test */ + li = litest_create_context(); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(sw->uinput)); + libinput_dispatch(li); + + while ((event = libinput_get_event(li)) != NULL) { + ck_assert_int_ne(libinput_event_get_type(event), + LIBINPUT_EVENT_SWITCH_TOGGLE); + libinput_event_destroy(event); + } + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + libinput_unref(li); +} +END_TEST + static inline struct litest_device * lid_init_paired_touchpad(struct libinput *li) { @@ -358,12 +407,59 @@ START_TEST(lid_open_on_key_touchpad_enabled) } END_TEST +START_TEST(lid_update_hw_on_key) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput *li2; + struct litest_device *keyboard; + struct libinput_event *event; + + sleep(5); + keyboard = litest_add_device(li, LITEST_KEYBOARD); + + /* separate context to listen to the fake hw event */ + li2 = litest_create_context(); + libinput_path_add_device(li2, + libevdev_uinput_get_devnode(sw->uinput)); + litest_drain_events(li2); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_drain_events(li); + + libinput_dispatch(li2); + event = libinput_get_event(li2); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + litest_event(keyboard, EV_KEY, KEY_A, 1); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_event(keyboard, EV_KEY, KEY_A, 0); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_drain_events(li); + + libinput_dispatch(li2); + event = libinput_get_event(li2); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + litest_assert_empty_queue(li); + + libinput_unref(li2); + litest_delete_device(keyboard); +} +END_TEST + void litest_setup_tests_lid(void) { litest_add("lid:switch", lid_switch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:switch", lid_switch_double, LITEST_SWITCH, LITEST_ANY); litest_add("lid:switch", lid_switch_down_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:switch", lid_switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); @@ -372,4 +468,6 @@ litest_setup_tests_lid(void) litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY); litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); + + litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); } diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index a5102d2..86eea0d 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -17,6 +17,15 @@ # Sort by brand, model ########################################## +# Chassis types 9 (Laptop) and 10 +# (Notebook) are expected to have working +# lid switches +########################################## +libinput:name:*Lid Switch*:dmi:*:ct10:* +libinput:name:*Lid Switch*:dmi:*:ct9:* + LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable + +########################################## # ALPS ########################################## libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:dmi:* @@ -151,6 +160,13 @@ libinput:name:*Logitech M570*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 ########################################## +# Microsoft +########################################## +# Surface3 needs us to write the open lid switch event +libinput:name:*Lid Switch*:dmi:*svnMicrosoftCorporation:pnSurface3:* + LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=write_open + +########################################## # Synaptics ########################################## libinput:touchpad:input:b0011v0002p0007* @@ -188,11 +204,3 @@ libinput:touchpad:input:b0003v056Ap* libinput:name:*Trackball*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 -########################################## -# Chassis types 9 (Laptop) and 10 -# (Notebook) are expected to have working -# lid switches -########################################## -libinput:name:*Lid Switch*:dmi:*:ct10:* -libinput:name:*Lid Switch*:dmi:*:ct9:* - LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py index 102ef6c..d079be2 100755 --- a/udev/parse_hwdb.py +++ b/udev/parse_hwdb.py @@ -102,10 +102,10 @@ def property_grammar(): size_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') for name, val in sz_props] - reliability_tags = (Literal("reliable")) + reliability_tags = Or(('reliable', 'write_open')) reliability = [Literal('LIBINPUT_ATTR_LID_SWITCH_RELIABILITY')('NAME') - Suppress('=') - - Group(OneOrMore(reliability_tags))('VALUE')] + reliability_tags('VALUE')] grammar = Or(model_props + size_props + reliability) |