Merge branch 'wip/keyboard-integration-property'

This commit is contained in:
Peter Hutterer 2017-05-29 13:20:39 +10:00
commit f139d8fbc3
8 changed files with 147 additions and 50 deletions

View file

@ -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,
@ -74,11 +89,12 @@ 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,
LIBINPUT_SWITCH_LID,
dispatch->lid_is_closed);
lid_switch_notify_toggle(dispatch, dispatch->device, time);
}
static void
@ -116,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;
}
}
@ -198,29 +210,26 @@ 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 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);
}
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
@ -251,10 +260,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
@ -262,24 +273,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);
}
}

View file

@ -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

View file

@ -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),

View file

@ -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),

View file

@ -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);
}

View file

@ -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
##########################################

View file

@ -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:<modalias>
ENV{ID_INPUT_KEYBOARD}=="1", \
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:keyboard:"
# libinput:name:<name>:dmi:<dmi string>
KERNELS=="input*", \
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'"

View file

@ -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