* [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon
@ 2026-11-09 21:43 Hans de Goede
2026-11-10 0:49 ` Mark Pearson
0 siblings, 1 reply; 4+ messages in thread
From: Hans de Goede @ 2026-11-09 21:43 UTC (permalink / raw)
To: Derek J . Clark, Mark Pearson, Jiri Kosina, Benjamin Tissoires
Cc: Hans de Goede, linux-input
The Lenovo ThinkPad T14s gen6/7 snapdragon version I2C-HID keyboard sends
spurirous F23 key-events when the Fn key is pressed/released. Leading to
e.g. garbage ESC-sequences in the terminal when doing FN key combos.
A hwdb entry was added to map these to KEY_UNKNOWN [1], but this also maps
the F23 part of the left-meta + left-shift + F23 combo send by the co-pilot
key to KEY_UNKNOWN making that key unusable.
Add a raw_event filter which removes any 0x72 codes from the 6 scancodes
reported in the standard HID keyboard boot protocol report, but only when
the report's modifier byte is not 0x0a to preserve the F23 press event
when the co-pilot key is pressed.
Link: https://github.com/systemd/systemd/pull/44733 [1]
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-lenovo.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 994e8bc69924..70d18d32fe3c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -473,6 +473,7 @@
#define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */
#define USB_VENDOR_ID_ELAN 0x04f3
+#define I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD 0x000d
#define USB_DEVICE_ID_SB974D 0x0400
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
#define USB_DEVICE_ID_HP_X2 0x074d
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 30bd3f794243..e997d0cf2672 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -812,6 +812,22 @@ static int lenovo_raw_event(struct hid_device *hdev,
size >= 4 && report->id == 0x03))
return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
+ /*
+ * Lenovo ThinkPad T14s gen6/7 snapdragon version filter out spurious
+ * F23 events when Fn key is pressed. F23 cannot be unmapped because of
+ * the copilot key sending left-meta + left-shift + F23. Filter report 8
+ * (keyboard) scancode 0x72 (F23) when the modifier byte is not 0x0a.
+ */
+ if (unlikely(hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD &&
+ size == 9 && data[0] == 8 && data[1] != 0x0a)) {
+ for (int i = 3; i < 9; i++)
+ if (data[i] == 0x72) {
+ memmove(&data[i], &data[i + 1], 8 - i);
+ data[8] = 0;
+ break;
+ }
+ }
+
return 0;
}
@@ -1393,6 +1409,10 @@ static int lenovo_probe(struct hid_device *hdev,
{
int ret;
+ /* Make the T14s keyboard trackpoint a separate input-device */
+ if (hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD)
+ hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "hid_parse failed\n");
@@ -1558,6 +1578,7 @@ static const struct hid_device_id lenovo_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TP10UBKBD) },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD) },
/*
* Note bind to the HID_GROUP_GENERIC group, so that we only bind to the keyboard
* part, while letting hid-multitouch.c handle the touchpad and trackpoint.
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon
2026-11-09 21:43 [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon Hans de Goede
@ 2026-11-10 0:49 ` Mark Pearson
2026-11-10 9:36 ` Hans de Goede
0 siblings, 1 reply; 4+ messages in thread
From: Mark Pearson @ 2026-11-10 0:49 UTC (permalink / raw)
To: Hans de Goede, Derek J . Clark, Jiri Kosina, Benjamin Tissoires
Cc: linux-input
Hi Hans
On Mon, Nov 9, 2026, at 4:43 PM, Hans de Goede wrote:
> The Lenovo ThinkPad T14s gen6/7 snapdragon version I2C-HID keyboard sends
> spurirous F23 key-events when the Fn key is pressed/released. Leading to
Minor - typo (spurirous)
> e.g. garbage ESC-sequences in the terminal when doing FN key combos.
>
> A hwdb entry was added to map these to KEY_UNKNOWN [1], but this also maps
> the F23 part of the left-meta + left-shift + F23 combo send by the co-pilot
> key to KEY_UNKNOWN making that key unusable.
>
> Add a raw_event filter which removes any 0x72 codes from the 6 scancodes
> reported in the standard HID keyboard boot protocol report, but only when
> the report's modifier byte is not 0x0a to preserve the F23 press event
> when the co-pilot key is pressed.
>
Interesting - I'd missed that.
Should I be flagging this to the FW team? I think I'm unlikely to get anything fixed at this point realistically - so don't want to block the patch...but if there's something we can learn from this for maybe the next generation?
> Link: https://github.com/systemd/systemd/pull/44733 [1]
> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
> ---
> drivers/hid/hid-ids.h | 1 +
> drivers/hid/hid-lenovo.c | 21 +++++++++++++++++++++
> 2 files changed, 22 insertions(+)
>
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 994e8bc69924..70d18d32fe3c 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -473,6 +473,7 @@
> #define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */
>
> #define USB_VENDOR_ID_ELAN 0x04f3
> +#define I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD 0x000d
> #define USB_DEVICE_ID_SB974D 0x0400
> #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
> #define USB_DEVICE_ID_HP_X2 0x074d
> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
> index 30bd3f794243..e997d0cf2672 100644
> --- a/drivers/hid/hid-lenovo.c
> +++ b/drivers/hid/hid-lenovo.c
> @@ -812,6 +812,22 @@ static int lenovo_raw_event(struct hid_device *hdev,
> size >= 4 && report->id == 0x03))
> return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
>
> + /*
> + * Lenovo ThinkPad T14s gen6/7 snapdragon version filter out spurious
> + * F23 events when Fn key is pressed. F23 cannot be unmapped because of
> + * the copilot key sending left-meta + left-shift + F23. Filter report 8
> + * (keyboard) scancode 0x72 (F23) when the modifier byte is not 0x0a.
> + */
> + if (unlikely(hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD &&
> + size == 9 && data[0] == 8 && data[1] != 0x0a)) {
> + for (int i = 3; i < 9; i++)
> + if (data[i] == 0x72) {
> + memmove(&data[i], &data[i + 1], 8 - i);
> + data[8] = 0;
> + break;
> + }
> + }
> +
> return 0;
> }
>
> @@ -1393,6 +1409,10 @@ static int lenovo_probe(struct hid_device *hdev,
> {
> int ret;
>
> + /* Make the T14s keyboard trackpoint a separate input-device */
> + if (hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD)
> + hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
> +
Shouldn't this be in a separate commit?
> ret = hid_parse(hdev);
> if (ret) {
> hid_err(hdev, "hid_parse failed\n");
> @@ -1558,6 +1578,7 @@ static const struct hid_device_id
> lenovo_devices[] = {
> { HID_USB_DEVICE(USB_VENDOR_ID_IBM,
> USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) },
> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
> USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) },
> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
> USB_DEVICE_ID_LENOVO_TP10UBKBD) },
> + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN,
> I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD) },
> /*
> * Note bind to the HID_GROUP_GENERIC group, so that we only bind to
> the keyboard
> * part, while letting hid-multitouch.c handle the touchpad and
> trackpoint.
> --
> 2.56.0
Mark
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon
2026-11-10 0:49 ` Mark Pearson
@ 2026-11-10 9:36 ` Hans de Goede
2026-11-10 12:27 ` Mark Pearson
0 siblings, 1 reply; 4+ messages in thread
From: Hans de Goede @ 2026-11-10 9:36 UTC (permalink / raw)
To: Mark Pearson, Derek J . Clark, Jiri Kosina, Benjamin Tissoires
Cc: linux-input
Hi,
On 10-Nov-26 01:49, Mark Pearson wrote:
> Hi Hans
>
> On Mon, Nov 9, 2026, at 4:43 PM, Hans de Goede wrote:
>> The Lenovo ThinkPad T14s gen6/7 snapdragon version I2C-HID keyboard sends
>> spurirous F23 key-events when the Fn key is pressed/released. Leading to
>
> Minor - typo (spurirous)
Ack.
>> e.g. garbage ESC-sequences in the terminal when doing FN key combos.
>>
>> A hwdb entry was added to map these to KEY_UNKNOWN [1], but this also maps
>> the F23 part of the left-meta + left-shift + F23 combo send by the co-pilot
>> key to KEY_UNKNOWN making that key unusable.
>>
>> Add a raw_event filter which removes any 0x72 codes from the 6 scancodes
>> reported in the standard HID keyboard boot protocol report, but only when
>> the report's modifier byte is not 0x0a to preserve the F23 press event
>> when the co-pilot key is pressed.
>>
> Interesting - I'd missed that.
>
> Should I be flagging this to the FW team? I think I'm unlikely to get anything fixed at this point realistically - so don't want to block the patch...but if there's something we can learn from this for maybe the next generation?
For future hw it would be nice if just pressing Fn by itself would not send
any spurious keypresses. Or at least not on the I2C-HID side. If this is
an EC event instead we can just filter it in the EC driver.
>> Link: https://github.com/systemd/systemd/pull/44733 [1]
>> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
>> ---
>> drivers/hid/hid-ids.h | 1 +
>> drivers/hid/hid-lenovo.c | 21 +++++++++++++++++++++
>> 2 files changed, 22 insertions(+)
>>
>> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> index 994e8bc69924..70d18d32fe3c 100644
>> --- a/drivers/hid/hid-ids.h
>> +++ b/drivers/hid/hid-ids.h
>> @@ -473,6 +473,7 @@
>> #define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */
>>
>> #define USB_VENDOR_ID_ELAN 0x04f3
>> +#define I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD 0x000d
>> #define USB_DEVICE_ID_SB974D 0x0400
>> #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
>> #define USB_DEVICE_ID_HP_X2 0x074d
>> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
>> index 30bd3f794243..e997d0cf2672 100644
>> --- a/drivers/hid/hid-lenovo.c
>> +++ b/drivers/hid/hid-lenovo.c
>> @@ -812,6 +812,22 @@ static int lenovo_raw_event(struct hid_device *hdev,
>> size >= 4 && report->id == 0x03))
>> return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
>>
>> + /*
>> + * Lenovo ThinkPad T14s gen6/7 snapdragon version filter out spurious
>> + * F23 events when Fn key is pressed. F23 cannot be unmapped because of
>> + * the copilot key sending left-meta + left-shift + F23. Filter report 8
>> + * (keyboard) scancode 0x72 (F23) when the modifier byte is not 0x0a.
>> + */
>> + if (unlikely(hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD &&
>> + size == 9 && data[0] == 8 && data[1] != 0x0a)) {
>> + for (int i = 3; i < 9; i++)
>> + if (data[i] == 0x72) {
>> + memmove(&data[i], &data[i + 1], 8 - i);
>> + data[8] = 0;
>> + break;
>> + }
>> + }
>> +
>> return 0;
>> }
>>
>> @@ -1393,6 +1409,10 @@ static int lenovo_probe(struct hid_device *hdev,
>> {
>> int ret;
>>
>> + /* Make the T14s keyboard trackpoint a separate input-device */
>> + if (hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD)
>> + hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
>> +
>
> Shouldn't this be in a separate commit?
No this "quirk" is the default behavior of the hid-generic driver. This driver
now will take over control from the hid-generic driver because of the device-id
addition below.
So setting this quirk preserves the existing default behavior.
>
>> ret = hid_parse(hdev);
>> if (ret) {
>> hid_err(hdev, "hid_parse failed\n");
>> @@ -1558,6 +1578,7 @@ static const struct hid_device_id
>> lenovo_devices[] = {
>> { HID_USB_DEVICE(USB_VENDOR_ID_IBM,
>> USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) },
>> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
>> USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) },
>> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
>> USB_DEVICE_ID_LENOVO_TP10UBKBD) },
>> + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN,
>> I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD) },
>> /*
>> * Note bind to the HID_GROUP_GENERIC group, so that we only bind to
>> the keyboard
>> * part, while letting hid-multitouch.c handle the touchpad and
>> trackpoint.
>> --
>> 2.56.0
>
> Mark
Regards,
Hans
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon
2026-11-10 9:36 ` Hans de Goede
@ 2026-11-10 12:27 ` Mark Pearson
0 siblings, 0 replies; 4+ messages in thread
From: Mark Pearson @ 2026-11-10 12:27 UTC (permalink / raw)
To: Hans de Goede, Derek J . Clark, Jiri Kosina, Benjamin Tissoires
Cc: linux-input
On Tue, Nov 10, 2026, at 4:36 AM, Hans de Goede wrote:
> Hi,
>
> On 10-Nov-26 01:49, Mark Pearson wrote:
>> Hi Hans
>>
>> On Mon, Nov 9, 2026, at 4:43 PM, Hans de Goede wrote:
>>> The Lenovo ThinkPad T14s gen6/7 snapdragon version I2C-HID keyboard sends
>>> spurirous F23 key-events when the Fn key is pressed/released. Leading to
>>
>> Minor - typo (spurirous)
>
> Ack.
>
>>> e.g. garbage ESC-sequences in the terminal when doing FN key combos.
>>>
>>> A hwdb entry was added to map these to KEY_UNKNOWN [1], but this also maps
>>> the F23 part of the left-meta + left-shift + F23 combo send by the co-pilot
>>> key to KEY_UNKNOWN making that key unusable.
>>>
>>> Add a raw_event filter which removes any 0x72 codes from the 6 scancodes
>>> reported in the standard HID keyboard boot protocol report, but only when
>>> the report's modifier byte is not 0x0a to preserve the F23 press event
>>> when the co-pilot key is pressed.
>>>
>> Interesting - I'd missed that.
>>
>> Should I be flagging this to the FW team? I think I'm unlikely to get anything fixed at this point realistically - so don't want to block the patch...but if there's something we can learn from this for maybe the next generation?
>
> For future hw it would be nice if just pressing Fn by itself would not send
> any spurious keypresses. Or at least not on the I2C-HID side. If this is
> an EC event instead we can just filter it in the EC driver.
>
Ack. Thanks - I'll let them know.
>
>>> Link: https://github.com/systemd/systemd/pull/44733 [1]
>>> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
>>> ---
>>> drivers/hid/hid-ids.h | 1 +
>>> drivers/hid/hid-lenovo.c | 21 +++++++++++++++++++++
>>> 2 files changed, 22 insertions(+)
>>>
>>> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>>> index 994e8bc69924..70d18d32fe3c 100644
>>> --- a/drivers/hid/hid-ids.h
>>> +++ b/drivers/hid/hid-ids.h
>>> @@ -473,6 +473,7 @@
>>> #define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */
>>>
>>> #define USB_VENDOR_ID_ELAN 0x04f3
>>> +#define I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD 0x000d
>>> #define USB_DEVICE_ID_SB974D 0x0400
>>> #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
>>> #define USB_DEVICE_ID_HP_X2 0x074d
>>> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
>>> index 30bd3f794243..e997d0cf2672 100644
>>> --- a/drivers/hid/hid-lenovo.c
>>> +++ b/drivers/hid/hid-lenovo.c
>>> @@ -812,6 +812,22 @@ static int lenovo_raw_event(struct hid_device *hdev,
>>> size >= 4 && report->id == 0x03))
>>> return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
>>>
>>> + /*
>>> + * Lenovo ThinkPad T14s gen6/7 snapdragon version filter out spurious
>>> + * F23 events when Fn key is pressed. F23 cannot be unmapped because of
>>> + * the copilot key sending left-meta + left-shift + F23. Filter report 8
>>> + * (keyboard) scancode 0x72 (F23) when the modifier byte is not 0x0a.
>>> + */
>>> + if (unlikely(hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD &&
>>> + size == 9 && data[0] == 8 && data[1] != 0x0a)) {
>>> + for (int i = 3; i < 9; i++)
>>> + if (data[i] == 0x72) {
>>> + memmove(&data[i], &data[i + 1], 8 - i);
>>> + data[8] = 0;
>>> + break;
>>> + }
>>> + }
>>> +
>>> return 0;
>>> }
>>>
>>> @@ -1393,6 +1409,10 @@ static int lenovo_probe(struct hid_device *hdev,
>>> {
>>> int ret;
>>>
>>> + /* Make the T14s keyboard trackpoint a separate input-device */
>>> + if (hdev->product == I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD)
>>> + hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
>>> +
>>
>> Shouldn't this be in a separate commit?
>
> No this "quirk" is the default behavior of the hid-generic driver. This driver
> now will take over control from the hid-generic driver because of the device-id
> addition below.
>
> So setting this quirk preserves the existing default behavior.
>
Ah - my bad. Thanks for the explain.
>>
>>> ret = hid_parse(hdev);
>>> if (ret) {
>>> hid_err(hdev, "hid_parse failed\n");
>>> @@ -1558,6 +1578,7 @@ static const struct hid_device_id
>>> lenovo_devices[] = {
>>> { HID_USB_DEVICE(USB_VENDOR_ID_IBM,
>>> USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) },
>>> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
>>> USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) },
>>> { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
>>> USB_DEVICE_ID_LENOVO_TP10UBKBD) },
>>> + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN,
>>> I2C_DEVICE_ID_ELAN_LENOVO_T14S_KEYBOARD) },
>>> /*
>>> * Note bind to the HID_GROUP_GENERIC group, so that we only bind to
>>> the keyboard
>>> * part, while letting hid-multitouch.c handle the touchpad and
>>> trackpoint.
>>> --
>>> 2.56.0
>>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Mark
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-10 12:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 21:43 [PATCH] HID: lenovo: suppress spurious F23 key events on ThinkPad T14s gen6/7 snapdragon Hans de Goede
2026-11-10 0:49 ` Mark Pearson
2026-11-10 9:36 ` Hans de Goede
2026-11-10 12:27 ` Mark Pearson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox