mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 16:00:06 +02:00
quirks: add trackpoint integration attribute
Some versions [1] of the Lenovo ThinkPad Compact USB Keyboard with TrackPoint USB have the pointing stick on an event node that has keys but is not a regular keyboard. Thus the stick falls through the cracks and gets disabled on tablet mode switch. Instead of adding more hacks let's do this properly: tag the pointing stick as external and have the code in place to deal with that. [1] This may be caused by recent kernel changes Fixes #291 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
3dc27d5d38
commit
8dfe8c68eb
7 changed files with 91 additions and 10 deletions
|
|
@ -180,3 +180,6 @@ AttrEventCodeDisable=EV_ABS;BTN_STYLUS;EV_KEY:0x123;
|
||||||
Disables the evdev event type/code tuples on the device. Entries may be
|
Disables the evdev event type/code tuples on the device. Entries may be
|
||||||
a named event type, or a named event code, or a named event type with a
|
a named event type, or a named event code, or a named event type with a
|
||||||
hexadecimal event code, separated by a single colon.
|
hexadecimal event code, separated by a single colon.
|
||||||
|
AttrPointingStickIntegration=internal|external
|
||||||
|
Indicates the integration of the pointing stick. This is a string enum.
|
||||||
|
Only needed for external pointing sticks. These are rare.
|
||||||
|
|
|
||||||
|
|
@ -76,13 +76,20 @@ MatchName=*TPPS/2 Elan TrackPoint*
|
||||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX1Carbon6th*
|
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX1Carbon6th*
|
||||||
AttrTrackpointMultiplier=0.4
|
AttrTrackpointMultiplier=0.4
|
||||||
|
|
||||||
[Lenovo ThinkPad Compact USB Keyboard with TrackPoint]
|
[Lenovo ThinkPad Compact USB Keyboard with TrackPoint (keyboard)]
|
||||||
MatchUdevType=keyboard
|
MatchUdevType=keyboard
|
||||||
MatchBus=usb
|
MatchBus=usb
|
||||||
MatchVendor=0x17EF
|
MatchVendor=0x17EF
|
||||||
MatchProduct=0x6047
|
MatchProduct=0x6047
|
||||||
AttrKeyboardIntegration=external
|
AttrKeyboardIntegration=external
|
||||||
|
|
||||||
|
[Lenovo ThinkPad Compact USB Keyboard with TrackPoint (trackpoint)]
|
||||||
|
MatchUdevType=pointingstick
|
||||||
|
MatchBus=usb
|
||||||
|
MatchVendor=0x17EF
|
||||||
|
MatchProduct=0x6047
|
||||||
|
AttrPointingStickIntegration=external
|
||||||
|
|
||||||
# Lenovo Thinkpad Yoga (not the consumer versions) disables the keyboard
|
# Lenovo Thinkpad Yoga (not the consumer versions) disables the keyboard
|
||||||
# mechanically. We must not disable the keyboard because some keys are
|
# mechanically. We must not disable the keyboard because some keys are
|
||||||
# still accessible on the screen and volume rocker.
|
# still accessible on the screen and volume rocker.
|
||||||
|
|
|
||||||
|
|
@ -1382,8 +1382,8 @@ fallback_tablet_mode_switch_event(uint64_t time,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fallback_keyboard_pair_tablet_mode(struct evdev_device *keyboard,
|
fallback_pair_tablet_mode(struct evdev_device *keyboard,
|
||||||
struct evdev_device *tablet_mode_switch)
|
struct evdev_device *tablet_mode_switch)
|
||||||
{
|
{
|
||||||
struct fallback_dispatch *dispatch =
|
struct fallback_dispatch *dispatch =
|
||||||
fallback_dispatch(keyboard->dispatch);
|
fallback_dispatch(keyboard->dispatch);
|
||||||
|
|
@ -1391,8 +1391,12 @@ fallback_keyboard_pair_tablet_mode(struct evdev_device *keyboard,
|
||||||
if ((keyboard->tags & EVDEV_TAG_EXTERNAL_KEYBOARD))
|
if ((keyboard->tags & EVDEV_TAG_EXTERNAL_KEYBOARD))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((keyboard->tags &
|
if ((keyboard->tags & EVDEV_TAG_TRACKPOINT)) {
|
||||||
(EVDEV_TAG_TRACKPOINT|EVDEV_TAG_INTERNAL_KEYBOARD)) == 0)
|
if (keyboard->tags & EVDEV_TAG_EXTERNAL_MOUSE)
|
||||||
|
return;
|
||||||
|
/* This filters out all internal keyboard-like devices (Video
|
||||||
|
* Switch) */
|
||||||
|
} else if ((keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (evdev_device_has_model_quirk(keyboard,
|
if (evdev_device_has_model_quirk(keyboard,
|
||||||
|
|
@ -1429,7 +1433,7 @@ fallback_interface_device_added(struct evdev_device *device,
|
||||||
struct evdev_device *added_device)
|
struct evdev_device *added_device)
|
||||||
{
|
{
|
||||||
fallback_lid_pair_keyboard(device, added_device);
|
fallback_lid_pair_keyboard(device, added_device);
|
||||||
fallback_keyboard_pair_tablet_mode(device, added_device);
|
fallback_pair_tablet_mode(device, added_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
32
src/evdev.c
32
src/evdev.c
|
|
@ -387,10 +387,34 @@ static void
|
||||||
evdev_tag_trackpoint(struct evdev_device *device,
|
evdev_tag_trackpoint(struct evdev_device *device,
|
||||||
struct udev_device *udev_device)
|
struct udev_device *udev_device)
|
||||||
{
|
{
|
||||||
if (libevdev_has_property(device->evdev,
|
struct quirks_context *quirks;
|
||||||
INPUT_PROP_POINTING_STICK) ||
|
struct quirks *q;
|
||||||
parse_udev_flag(device, udev_device, "ID_INPUT_POINTINGSTICK"))
|
char *prop;
|
||||||
device->tags |= EVDEV_TAG_TRACKPOINT;
|
|
||||||
|
if (!libevdev_has_property(device->evdev,
|
||||||
|
INPUT_PROP_POINTING_STICK) &&
|
||||||
|
!parse_udev_flag(device, udev_device, "ID_INPUT_POINTINGSTICK"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
device->tags |= EVDEV_TAG_TRACKPOINT;
|
||||||
|
|
||||||
|
quirks = evdev_libinput_context(device)->quirks;
|
||||||
|
q = quirks_fetch_for_device(quirks, device->udev_device);
|
||||||
|
if (q && quirks_get_string(q, QUIRK_ATTR_TRACKPOINT_INTEGRATION, &prop)) {
|
||||||
|
if (streq(prop, "internal")) {
|
||||||
|
/* noop, this is the default anyway */
|
||||||
|
} else if (streq(prop, "external")) {
|
||||||
|
device->tags |= EVDEV_TAG_EXTERNAL_MOUSE;
|
||||||
|
evdev_log_info(device,
|
||||||
|
"is an external pointing stick\n");
|
||||||
|
} else {
|
||||||
|
evdev_log_info(device,
|
||||||
|
"tagged with unknown value %s\n",
|
||||||
|
prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quirks_unref(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ quirk_get_name(enum quirk q)
|
||||||
case QUIRK_ATTR_PALM_SIZE_THRESHOLD: return "AttrPalmSizeThreshold";
|
case QUIRK_ATTR_PALM_SIZE_THRESHOLD: return "AttrPalmSizeThreshold";
|
||||||
case QUIRK_ATTR_LID_SWITCH_RELIABILITY: return "AttrLidSwitchReliability";
|
case QUIRK_ATTR_LID_SWITCH_RELIABILITY: return "AttrLidSwitchReliability";
|
||||||
case QUIRK_ATTR_KEYBOARD_INTEGRATION: return "AttrKeyboardIntegration";
|
case QUIRK_ATTR_KEYBOARD_INTEGRATION: return "AttrKeyboardIntegration";
|
||||||
|
case QUIRK_ATTR_TRACKPOINT_INTEGRATION: return "AttrPointingStickIntegration";
|
||||||
case QUIRK_ATTR_TPKBCOMBO_LAYOUT: return "AttrTPKComboLayout";
|
case QUIRK_ATTR_TPKBCOMBO_LAYOUT: return "AttrTPKComboLayout";
|
||||||
case QUIRK_ATTR_PRESSURE_RANGE: return "AttrPressureRange";
|
case QUIRK_ATTR_PRESSURE_RANGE: return "AttrPressureRange";
|
||||||
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: return "AttrPalmPressureThreshold";
|
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: return "AttrPalmPressureThreshold";
|
||||||
|
|
@ -660,6 +661,13 @@ parse_attr(struct quirks_context *ctx,
|
||||||
p->type = PT_STRING;
|
p->type = PT_STRING;
|
||||||
p->value.s = safe_strdup(value);
|
p->value.s = safe_strdup(value);
|
||||||
rc = true;
|
rc = true;
|
||||||
|
} else if (streq(key, quirk_get_name(QUIRK_ATTR_TRACKPOINT_INTEGRATION))) {
|
||||||
|
p->id = QUIRK_ATTR_TRACKPOINT_INTEGRATION;
|
||||||
|
if (!streq(value, "internal") && !streq(value, "external"))
|
||||||
|
goto out;
|
||||||
|
p->type = PT_STRING;
|
||||||
|
p->value.s = safe_strdup(value);
|
||||||
|
rc = true;
|
||||||
} else if (streq(key, quirk_get_name(QUIRK_ATTR_TPKBCOMBO_LAYOUT))) {
|
} else if (streq(key, quirk_get_name(QUIRK_ATTR_TPKBCOMBO_LAYOUT))) {
|
||||||
p->id = QUIRK_ATTR_TPKBCOMBO_LAYOUT;
|
p->id = QUIRK_ATTR_TPKBCOMBO_LAYOUT;
|
||||||
if (!streq(value, "below"))
|
if (!streq(value, "below"))
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ enum quirk {
|
||||||
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
|
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
|
||||||
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
|
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
|
||||||
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||||
|
QUIRK_ATTR_TRACKPOINT_INTEGRATION,
|
||||||
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
|
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
|
||||||
QUIRK_ATTR_PRESSURE_RANGE,
|
QUIRK_ATTR_PRESSURE_RANGE,
|
||||||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||||
|
|
|
||||||
|
|
@ -1205,6 +1205,39 @@ START_TEST(quirks_parse_string_attr)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(quirks_parse_integration_attr)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
char *do_not_use; /* freed before we can use it */
|
||||||
|
bool
|
||||||
|
|
||||||
|
rc = test_attr_parse(dev,
|
||||||
|
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||||
|
"internal",
|
||||||
|
(qparsefunc)quirks_get_string,
|
||||||
|
&do_not_use);
|
||||||
|
ck_assert(rc);
|
||||||
|
rc = test_attr_parse(dev,
|
||||||
|
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||||
|
"external",
|
||||||
|
(qparsefunc)quirks_get_string,
|
||||||
|
&do_not_use);
|
||||||
|
ck_assert(rc);
|
||||||
|
rc = test_attr_parse(dev,
|
||||||
|
QUIRK_ATTR_TRACKPOINT_INTEGRATION,
|
||||||
|
"internal",
|
||||||
|
(qparsefunc)quirks_get_string,
|
||||||
|
&do_not_use);
|
||||||
|
ck_assert(rc);
|
||||||
|
rc = test_attr_parse(dev,
|
||||||
|
QUIRK_ATTR_TRACKPOINT_INTEGRATION,
|
||||||
|
"external",
|
||||||
|
(qparsefunc)quirks_get_string,
|
||||||
|
&do_not_use);
|
||||||
|
ck_assert(rc);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(quirks_model_one)
|
START_TEST(quirks_model_one)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -1433,6 +1466,7 @@ TEST_COLLECTION(quirks)
|
||||||
litest_add_for_device("quirks:parsing", quirks_parse_uint_attr, LITEST_MOUSE);
|
litest_add_for_device("quirks:parsing", quirks_parse_uint_attr, LITEST_MOUSE);
|
||||||
litest_add_for_device("quirks:parsing", quirks_parse_double_attr, LITEST_MOUSE);
|
litest_add_for_device("quirks:parsing", quirks_parse_double_attr, LITEST_MOUSE);
|
||||||
litest_add_for_device("quirks:parsing", quirks_parse_string_attr, LITEST_MOUSE);
|
litest_add_for_device("quirks:parsing", quirks_parse_string_attr, LITEST_MOUSE);
|
||||||
|
litest_add_for_device("quirks:parsing", quirks_parse_integration_attr, LITEST_MOUSE);
|
||||||
|
|
||||||
litest_add_for_device("quirks:model", quirks_model_one, LITEST_MOUSE);
|
litest_add_for_device("quirks:model", quirks_model_one, LITEST_MOUSE);
|
||||||
litest_add_for_device("quirks:model", quirks_model_zero, LITEST_MOUSE);
|
litest_add_for_device("quirks:model", quirks_model_zero, LITEST_MOUSE);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue