From 782a0661d110bf1cb348a4acf5858e385f0dc0f2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 22 May 2017 14:28:31 +1000 Subject: [PATCH 1/7] lid: add a comment for why we post the switch state there Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 9e694ba1..9815b8fa 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -74,6 +74,10 @@ lid_switch_keyboard_event(uint64_t time, * regardless. */ } + /* Posting the event here means we preempt the keyboard events that + * caused us to wake up, so the lid event is always passed on before + * the key event. + */ dispatch->lid_is_closed = false; switch_notify_toggle(&dispatch->device->base, time, From 1cfa1f64cfd610d97643be32e92c67c0ecee23c8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 22 May 2017 13:34:10 +1000 Subject: [PATCH 2/7] evdev: read LIBINPUT_ATTR_KEYBOARD_INTEGRATION property We have heuristics for detecting whether a keyboard is internal or external, but in some cases (e.g. Surface 3) these heuristics fail. Add a udev property that we can apply to these cases so we have something that's reliable. This will likely eventually become ID_INPUT_KEYBOARD_INTEGRATION as shipped by systemd, similar to the touchpad property. https://bugs.freedesktop.org/show_bug.cgi?id=101101 Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 3 +-- src/evdev.c | 31 +++++++++++++++++++++++++- src/evdev.h | 3 ++- udev/90-libinput-model-quirks.hwdb | 12 +++++++++- udev/90-libinput-model-quirks.rules.in | 4 ++++ udev/parse_hwdb.py | 9 ++++++-- 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 17b14bc8..e5f2a5ce 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1601,8 +1601,7 @@ tp_want_dwt(struct evdev_device *touchpad, /* 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; + keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD; } /* everything else we don't really know, so we have to assume diff --git a/src/evdev.c b/src/evdev.c index f7a019c6..02ed4f1a 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1089,10 +1089,25 @@ evdev_tag_trackpoint(struct evdev_device *device, device->tags |= EVDEV_TAG_TRACKPOINT; } +static inline void +evdev_tag_keyboard_internal(struct evdev_device *device) +{ + device->tags |= EVDEV_TAG_INTERNAL_KEYBOARD; + device->tags &= ~EVDEV_TAG_EXTERNAL_KEYBOARD; +} + +static inline void +evdev_tag_keyboard_external(struct evdev_device *device) +{ + device->tags |= EVDEV_TAG_EXTERNAL_KEYBOARD; + device->tags &= ~EVDEV_TAG_INTERNAL_KEYBOARD; +} + static void evdev_tag_keyboard(struct evdev_device *device, struct udev_device *udev_device) { + const char *prop; int code; if (!libevdev_has_event_type(device->evdev, EV_KEY)) @@ -1105,6 +1120,21 @@ evdev_tag_keyboard(struct evdev_device *device, return; } + /* This should eventually become ID_INPUT_KEYBOARD_INTEGRATION */ + prop = udev_device_get_property_value(udev_device, + "LIBINPUT_ATTR_KEYBOARD_INTEGRATION"); + if (prop) { + if (streq(prop, "internal")) { + evdev_tag_keyboard_internal(device); + } else if (streq(prop, "external")) { + evdev_tag_keyboard_external(device); + } else { + evdev_log_info(device, + "tagged with unknown value %s\n", + prop); + } + } + device->tags |= EVDEV_TAG_KEYBOARD; } @@ -2251,7 +2281,6 @@ evdev_read_model_flags(struct evdev_device *device) MODEL(ALPS_TOUCHPAD), MODEL(SYNAPTICS_SERIAL_TOUCHPAD), MODEL(JUMPING_SEMI_MT), - MODEL(APPLE_INTERNAL_KEYBOARD), MODEL(CYBORG_RAT), MODEL(HP_STREAM11_TOUCHPAD), MODEL(LENOVO_T450_TOUCHPAD), diff --git a/src/evdev.h b/src/evdev.h index a5c11fc3..b891f906 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -73,6 +73,8 @@ enum evdev_device_tags { EVDEV_TAG_TRACKPOINT = (1 << 3), EVDEV_TAG_KEYBOARD = (1 << 4), EVDEV_TAG_LID_SWITCH = (1 << 5), + EVDEV_TAG_INTERNAL_KEYBOARD = (1 << 6), + EVDEV_TAG_EXTERNAL_KEYBOARD = (1 << 7), }; enum evdev_middlebutton_state { @@ -112,7 +114,6 @@ enum evdev_device_model { EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9), EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10), EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12), - EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13), EVDEV_MODEL_CYBORG_RAT = (1 << 14), EVDEV_MODEL_HP_STREAM11_TOUCHPAD = (1 << 16), EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17), diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 3f048092..229fb1de 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -25,6 +25,12 @@ libinput:name:*Lid Switch*:dmi:*:ct10:* libinput:name:*Lid Switch*:dmi:*:ct9:* LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable +########################################## +# Serial keyboards are internal +########################################## +libinput:keyboard:input:b0011v* + LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal + ########################################## # ALPS ########################################## @@ -45,7 +51,7 @@ libinput:touchpad:input:b0005v05ACp* LIBINPUT_ATTR_SIZE_HINT=104x75 libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:* - LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD=1 + LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal libinput:mouse:input:b0005v05ACp030D* LIBINPUT_MODEL_APPLE_MAGICMOUSE=1 @@ -186,6 +192,10 @@ libinput:mouse:input:b0003v046DpC408* libinput:name:*Lid Switch*:dmi:*svnMicrosoftCorporation:pnSurface3:* LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=write_open +# Surface 3 Type Cover keyboard +libinput:name:*Microsoft Surface Type Cover Keyboard*:dmi:*svnMicrosoftCorporation:pnSurface3:* + LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal + ########################################## # Synaptics ########################################## diff --git a/udev/90-libinput-model-quirks.rules.in b/udev/90-libinput-model-quirks.rules.in index 8bff192d..ace2bf07 100644 --- a/udev/90-libinput-model-quirks.rules.in +++ b/udev/90-libinput-model-quirks.rules.in @@ -33,6 +33,10 @@ ENV{ID_INPUT_TOUCHPAD}=="1", \ ENV{ID_INPUT_MOUSE}=="1", \ IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:mouse:" +# libinput:touchpad: +ENV{ID_INPUT_KEYBOARD}=="1", \ + IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:keyboard:" + # libinput:name::dmi: KERNELS=="input*", \ IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'" diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py index b4f0b1bf..8ac64010 100755 --- a/udev/parse_hwdb.py +++ b/udev/parse_hwdb.py @@ -60,7 +60,7 @@ REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER)) UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_') TYPES = { - 'libinput': ('name', 'touchpad', 'mouse'), + 'libinput': ('name', 'touchpad', 'mouse', 'keyboard'), } @functools.lru_cache() @@ -117,8 +117,13 @@ def property_grammar(): Suppress('=') - Group(pressure_range('SETTINGS*')) ] + kbintegration_tags = Or(('internal', 'external')) + kbintegration = [Literal('LIBINPUT_ATTR_KEYBOARD_INTEGRATION')('NAME') - + Suppress('=') - + kbintegration_tags('VALUE')] + grammar = Or(model_props + size_props + reliability + tpkbcombo + - pressure_prop) + pressure_prop + kbintegration) return grammar From 1671c7f4adcf0873c55b21dc3e0578e91c360837 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 22 May 2017 13:51:11 +1000 Subject: [PATCH 3/7] lid: tighten the lid-keyboard pairing Only pair if the keyboard is either tagged as internal device. This has another (unlikely) behaviour change: previously we would override the paired keyboards with ones that look more accurate (e.g. a usb keyboard paired before a serial would be unpaired and the serial keyboard takes its place). Now we assume there can only be one internal keyboard, once we have it we ignore all others. This shouldn't matter in real life provided the tagging is correct. Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 9815b8fa..80907801 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -202,29 +202,23 @@ lid_switch_pair_keyboard(struct evdev_device *lid_switch, { struct lid_switch_dispatch *dispatch = lid_dispatch(lid_switch->dispatch); - unsigned int bus_kbd = libevdev_get_id_bustype(keyboard->evdev); if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0) return; - /* If we already have a keyboard paired, override it if the new one - * is a serio device. Otherwise keep the current one */ - if (dispatch->keyboard.keyboard) { - if (bus_kbd != BUS_I8042) - return; + if (dispatch->keyboard.keyboard) + return; - libinput_device_remove_event_listener(&dispatch->keyboard.listener); - libinput_device_init_event_listener(&dispatch->keyboard.listener); + if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) { + dispatch->keyboard.keyboard = keyboard; + evdev_log_debug(lid_switch, + "lid: keyboard paired with %s<->%s\n", + lid_switch->devname, + keyboard->devname); + + /* We don't init the event listener yet - we don't care + * about keyboard events until the lid is closed */ } - - dispatch->keyboard.keyboard = keyboard; - evdev_log_debug(lid_switch, - "lid: keyboard paired with %s<->%s\n", - lid_switch->devname, - keyboard->devname); - - /* We don't init the event listener yet - we don't care about - * keyboard events until the lid is closed */ } static void From 28fcd2c6d41e972f606c60f56c6f0a94d73455ae Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 19 May 2017 12:55:54 +0200 Subject: [PATCH 4/7] lid: track the notifier initial state internally, but not externally What we do not want is libinput to believe the LID is closed while it's not. But the internal notifier state need to be in sync with the evdev node, or it's going to be a pain setting the keyboard listener. But since we don't know if the state is reliable, we track the internal state separately from the external state so that we can set up the keyboard listener when the lid is closed, without having libinput actually send lid closed events for unreliable devices. https://bugs.freedesktop.org/show_bug.cgi?id=101099 Signed-off-by: Benjamin Tissoires Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 80907801..010cb42d 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -34,6 +34,7 @@ struct lid_switch_dispatch { enum switch_reliability reliability; bool lid_is_closed; + bool lid_is_closed_client_state; struct { struct evdev_device *keyboard; @@ -49,6 +50,20 @@ lid_dispatch(struct evdev_dispatch *dispatch) return container_of(dispatch, struct lid_switch_dispatch, base); } +static void +lid_switch_notify_toggle(struct lid_switch_dispatch *dispatch, + struct evdev_device *device, + uint64_t time) +{ + if (dispatch->lid_is_closed ^ dispatch->lid_is_closed_client_state) { + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + dispatch->lid_is_closed); + dispatch->lid_is_closed_client_state = dispatch->lid_is_closed; + } +} + static void lid_switch_keyboard_event(uint64_t time, struct libinput_event *event, @@ -79,10 +94,7 @@ lid_switch_keyboard_event(uint64_t time, * the key event. */ dispatch->lid_is_closed = false; - switch_notify_toggle(&dispatch->device->base, - time, - LIBINPUT_SWITCH_LID, - dispatch->lid_is_closed); + lid_switch_notify_toggle(dispatch, dispatch->device, time); } static void @@ -120,16 +132,12 @@ lid_switch_process_switch(struct lid_switch_dispatch *dispatch, if (dispatch->lid_is_closed == is_closed) return; - lid_switch_toggle_keyboard_listener(dispatch, is_closed); dispatch->lid_is_closed = is_closed; - switch_notify_toggle(&device->base, - time, - LIBINPUT_SWITCH_LID, - dispatch->lid_is_closed); + lid_switch_notify_toggle(dispatch, device, time); break; } } @@ -249,10 +257,12 @@ lid_switch_sync_initial_state(struct evdev_device *device, { struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch); struct libevdev *evdev = device->evdev; - bool is_closed = false; dispatch->reliability = evdev_read_switch_reliability_prop(device); + dispatch->lid_is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID); + dispatch->lid_is_closed_client_state = false; + /* 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 @@ -260,24 +270,11 @@ 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(dispatch->reliability) { - case RELIABILITY_UNKNOWN: - case RELIABILITY_WRITE_OPEN: - is_closed = false; - break; - case RELIABILITY_RELIABLE: - is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID); - break; - } - - dispatch->lid_is_closed = is_closed; - if (dispatch->lid_is_closed) { + if (dispatch->lid_is_closed && + dispatch->reliability == RELIABILITY_RELIABLE) { uint64_t time; time = libinput_now(evdev_libinput_context(device)); - switch_notify_toggle(&device->base, - time, - LIBINPUT_SWITCH_LID, - LIBINPUT_SWITCH_STATE_ON); + lid_switch_notify_toggle(dispatch, device, time); } } From 8fbdef3aadfaa09dfaec50b0f67ec43ad0b55e96 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 19 May 2017 12:57:23 +0200 Subject: [PATCH 5/7] lid: setup the keyboard notifier when pairing it On unreliable LID switches, we might have the LID declared as closed while it is actually not. We can not wait for the first switch event to setup the keyboard listener: it will never occur. https://bugs.freedesktop.org/show_bug.cgi?id=101099 Signed-off-by: Benjamin Tissoires Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 7 +++++-- test/test-lid.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 010cb42d..fe98e6e1 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -224,8 +224,11 @@ lid_switch_pair_keyboard(struct evdev_device *lid_switch, lid_switch->devname, keyboard->devname); - /* We don't init the event listener yet - we don't care - * about keyboard events until the lid is closed */ + /* We need to init the event listener now only if the reported state + * is closed. */ + if (dispatch->lid_is_closed) + lid_switch_toggle_keyboard_listener(dispatch, + dispatch->lid_is_closed); } } diff --git a/test/test-lid.c b/test/test-lid.c index 1bd75cb6..4bf4c059 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -505,6 +505,56 @@ START_TEST(lid_update_hw_on_key) } END_TEST +START_TEST(lid_update_hw_on_key_closed_on_init) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li; + struct litest_device *keyboard; + struct libevdev *evdev = sw->evdev; + struct input_event ev; + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + + /* Make sure kernel state is right */ + libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); + while (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_SYNC, &ev) >= 0) + ; + ck_assert(libevdev_get_event_value(evdev, EV_SW, SW_LID)); + + keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD); + + /* separate context for the right state on init */ + li = litest_create_context(); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(sw->uinput)); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(keyboard->uinput)); + + /* don't expect a switch waiting for us */ + while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { + ck_assert_int_ne(libinput_next_event_type(li), + LIBINPUT_EVENT_SWITCH_TOGGLE); + libinput_event_destroy(libinput_get_event(li)); + } + + 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); + /* No switch event, we're still in vanilla (open) state */ + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + /* Make sure kernel state has updated */ + libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); + while (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_SYNC, &ev) >= 0) + ; + ck_assert(!libevdev_get_event_value(evdev, EV_SW, SW_LID)); + + libinput_unref(li); + litest_delete_device(keyboard); +} +END_TEST + void litest_setup_tests_lid(void) { @@ -525,4 +575,5 @@ litest_setup_tests_lid(void) litest_add_no_device("lid:disable_touchpad", lid_suspend_with_touchpad); litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); + litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3); } From d35d122eb1f2ff2f4e69ccfc9b82630bb3a0616a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 22 May 2017 16:00:20 +1000 Subject: [PATCH 6/7] lid: force the lid to open when the keyboard device is removed On unreliable tablets (Surface3), always force the lid switch to open when the paired keyboard is removed. This way the lid can't be stuck in a closed state when there's nothing attached that can actually trigger that state. https://bugs.freedesktop.org/show_bug.cgi?id=101100 Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 34 +++++++++++++++++++++++----------- test/test-lid.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index fe98e6e1..1edb12b0 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -64,6 +64,23 @@ lid_switch_notify_toggle(struct lid_switch_dispatch *dispatch, } } +static void +lid_switch_update_kernel_state(struct lid_switch_dispatch *dispatch, + uint64_t time) +{ + int fd; + const struct input_event ev[2] = { + {{ 0, 0 }, EV_SW, SW_LID, 0 }, + {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 }, + }; + + if (dispatch->reliability != RELIABILITY_WRITE_OPEN) + return; + + fd = libevdev_get_fd(dispatch->device->evdev); + (void)write(fd, ev, sizeof(ev)); +} + static void lid_switch_keyboard_event(uint64_t time, struct libinput_event *event, @@ -77,17 +94,7 @@ 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. */ - } + lid_switch_update_kernel_state(dispatch, time); /* Posting the event here means we preempt the keyboard events that * caused us to wake up, so the lid event is always passed on before @@ -246,11 +253,16 @@ lid_switch_interface_device_removed(struct evdev_device *device, struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch); if (removed_device == dispatch->keyboard.keyboard) { + uint64_t time; + libinput_device_remove_event_listener( &dispatch->keyboard.listener); libinput_device_init_event_listener( &dispatch->keyboard.listener); dispatch->keyboard.keyboard = NULL; + + time = libinput_now(evdev_libinput_context(device)); + lid_switch_update_kernel_state(dispatch, time); } } diff --git a/test/test-lid.c b/test/test-lid.c index 4bf4c059..2257976e 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -555,6 +555,41 @@ START_TEST(lid_update_hw_on_key_closed_on_init) } END_TEST +START_TEST(lid_force_open_if_no_keyboard) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li; + struct litest_device *keyboard; + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD); + + /* separate context for the right state on init */ + li = litest_create_context(); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(sw->uinput)); + + /* We only have the switch device in this context, not the keyboard. + * So don't expect any switch event to be in the pipe and don't + * expect the event to change if we type or toggle the state + */ + while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { + ck_assert_int_ne(libinput_next_event_type(li), + LIBINPUT_EVENT_SWITCH_TOGGLE); + libinput_event_destroy(libinput_get_event(li)); + } + + 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_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + + libinput_unref(li); + litest_delete_device(keyboard); +} +END_TEST void litest_setup_tests_lid(void) { @@ -576,4 +611,5 @@ litest_setup_tests_lid(void) litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3); + litest_add_for_device("lid:buggy", lid_force_open_if_no_keyboard, LITEST_LID_SWITCH_SURFACE3); } From 0c428d6b77359c74e7dda19e3783879638fc1c99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 23 May 2017 13:06:44 +1000 Subject: [PATCH 7/7] Revert "lid: force the lid to open when the keyboard device is removed" This reverts commit 1e2b66fb9a0de8956abc7d996afdd24a11893eb6. --- src/evdev-lid.c | 34 +++++++++++----------------------- test/test-lid.c | 36 ------------------------------------ 2 files changed, 11 insertions(+), 59 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 1edb12b0..fe98e6e1 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -64,23 +64,6 @@ lid_switch_notify_toggle(struct lid_switch_dispatch *dispatch, } } -static void -lid_switch_update_kernel_state(struct lid_switch_dispatch *dispatch, - uint64_t time) -{ - int fd; - const struct input_event ev[2] = { - {{ 0, 0 }, EV_SW, SW_LID, 0 }, - {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 }, - }; - - if (dispatch->reliability != RELIABILITY_WRITE_OPEN) - return; - - fd = libevdev_get_fd(dispatch->device->evdev); - (void)write(fd, ev, sizeof(ev)); -} - static void lid_switch_keyboard_event(uint64_t time, struct libinput_event *event, @@ -94,7 +77,17 @@ lid_switch_keyboard_event(uint64_t time, if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) return; - lid_switch_update_kernel_state(dispatch, time); + 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. */ + } /* Posting the event here means we preempt the keyboard events that * caused us to wake up, so the lid event is always passed on before @@ -253,16 +246,11 @@ lid_switch_interface_device_removed(struct evdev_device *device, struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch); if (removed_device == dispatch->keyboard.keyboard) { - uint64_t time; - libinput_device_remove_event_listener( &dispatch->keyboard.listener); libinput_device_init_event_listener( &dispatch->keyboard.listener); dispatch->keyboard.keyboard = NULL; - - time = libinput_now(evdev_libinput_context(device)); - lid_switch_update_kernel_state(dispatch, time); } } diff --git a/test/test-lid.c b/test/test-lid.c index 2257976e..4bf4c059 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -555,41 +555,6 @@ START_TEST(lid_update_hw_on_key_closed_on_init) } END_TEST -START_TEST(lid_force_open_if_no_keyboard) -{ - struct litest_device *sw = litest_current_device(); - struct libinput *li; - struct litest_device *keyboard; - - litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); - keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD); - - /* separate context for the right state on init */ - li = litest_create_context(); - libinput_path_add_device(li, - libevdev_uinput_get_devnode(sw->uinput)); - - /* We only have the switch device in this context, not the keyboard. - * So don't expect any switch event to be in the pipe and don't - * expect the event to change if we type or toggle the state - */ - while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { - ck_assert_int_ne(libinput_next_event_type(li), - LIBINPUT_EVENT_SWITCH_TOGGLE); - libinput_event_destroy(libinput_get_event(li)); - } - - 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_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); - litest_assert_empty_queue(li); - - libinput_unref(li); - litest_delete_device(keyboard); -} -END_TEST void litest_setup_tests_lid(void) { @@ -611,5 +576,4 @@ litest_setup_tests_lid(void) litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3); - litest_add_for_device("lid:buggy", lid_force_open_if_no_keyboard, LITEST_LID_SWITCH_SURFACE3); }