[PATCH AUTOSEL 6.12 13/21] HID: lenovo: Add support for ThinkPad X1 Tablet Thin Keyboard Gen2
From: Sasha Levin <sashal@kernel.org>
Date: 2025-06-30 21:00:11
Also in:
linux-patches, stable
Subsystem:
hid core layer, lenovo hid drivers, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Derek J. Clark, Mark Pearson, Linus Torvalds
From: Akira Inoue <redacted>
[ Upstream commit a8905238c3bbe13db90065ed74682418f23830c3 ]
Add "Thinkpad X1 Tablet Gen 2 Keyboard" PID to hid-lenovo driver to fix trackpoint not working issue.
Signed-off-by: Akira Inoue <redacted>
Signed-off-by: Jiri Kosina <redacted>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
**YES**
This commit should be backported to stable kernel trees. Here's my
extensive analysis:
## Commit Analysis
This commit adds support for the ThinkPad X1 Tablet Thin Keyboard Gen2
by adding its USB device ID (0x60a4) to the hid-lenovo driver. The
primary issue being fixed is that the trackpoint (pointing stick) is
non-functional without this patch.
## Code Changes Examination
1. **drivers/hid/hid-ids.h**: Adds `USB_DEVICE_ID_LENOVO_X1_TAB2` with
value 0x60a4. This follows the existing pattern where X1_TAB is
0x60a3 and X1_TAB3 is 0x60b5.
2. **drivers/hid/hid-lenovo.c**: The device ID is added to 7 locations:
- `lenovo_input_mapping()`: Enables X1 tablet keyboard-specific input
mappings
- `attr_fn_lock_store()`: Enables FnLock LED control functionality
- `lenovo_event()`: Handles special key events
- `lenovo_led_brightness_set()`: Controls mute/micmute LED indicators
- `lenovo_probe()`: Initializes device with tp10ubkbd infrastructure
- `lenovo_remove()`: Cleanup handling
- `lenovo_devices[]`: Device table entry with HID_GROUP_GENERIC
3. **drivers/hid/hid-multitouch.c**: Adds multitouch support with
`MT_CLS_WIN_8_FORCE_MULTI_INPUT` class, consistent with other X1
Tablet devices.
## Stable Backport Criteria
This commit meets all the stable kernel backporting criteria:
1. **Fixes a real bug**: The trackpoint is completely non-functional
without this patch, affecting users who own this hardware.
2. **Small and contained**: The changes are minimal - just adding a
device ID to existing code paths. No new functionality or
architectural changes.
3. **Obviously correct**: The pattern is identical to existing X1 Tablet
support (Gen1 and Gen3). The commit follows established conventions.
4. **Low risk**: Cannot affect any other hardware since it's guarded by
specific device ID checks.
5. **Hardware enablement**: This is pure hardware enablement for a
specific device that doesn't work at all without this patch.
## Comparison with Similar Commits
Looking at the provided similar commits:
- Commits adding X1 Tablet Gen3 support (Similar #2) and X12 Tab Gen2
support (Similar #4) were marked YES for backporting
- Both fixed similar issues (non-working buttons, trackpoint, FnLock)
- This commit follows the exact same pattern
The commit marked NO (Similar #1) only added partial multitouch support
without the full hid-lenovo driver integration, which is why it wasn't
suitable for stable.
## Conclusion
This is a textbook example of a commit that should be backported to
stable kernels. It enables basic functionality (trackpoint) for specific
hardware that is completely broken without it, using minimal, well-
tested code patterns that cannot regress other devices.
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-lenovo.c | 8 ++++++++
drivers/hid/hid-multitouch.c | 8 +++++++-
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c6424f6259487..49dc86981287a 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h@@ -814,6 +814,7 @@ #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 +#define USB_DEVICE_ID_LENOVO_X1_TAB2 0x60a4 #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 #define USB_DEVICE_ID_LENOVO_X12_TAB 0x60fe #define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index f66194fde8912..b7b4c838980c7 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c@@ -473,6 +473,7 @@ static int lenovo_input_mapping(struct hid_device *hdev, return lenovo_input_mapping_tp10_ultrabook_kbd(hdev, hi, field, usage, bit, max); case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: return lenovo_input_mapping_x1_tab_kbd(hdev, hi, field, usage, bit, max); default:
@@ -584,6 +585,7 @@ static ssize_t attr_fn_lock_store(struct device *dev, break; case USB_DEVICE_ID_LENOVO_TP10UBKBD: case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: ret = lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, value); if (ret)
@@ -778,6 +780,7 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field, return lenovo_event_cptkbd(hdev, field, usage, value); case USB_DEVICE_ID_LENOVO_TP10UBKBD: case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: return lenovo_event_tp10ubkbd(hdev, field, usage, value); default:
@@ -1059,6 +1062,7 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev, break; case USB_DEVICE_ID_LENOVO_TP10UBKBD: case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: ret = lenovo_led_set_tp10ubkbd(hdev, tp10ubkbd_led[led_nr], value); break;
@@ -1290,6 +1294,7 @@ static int lenovo_probe(struct hid_device *hdev, break; case USB_DEVICE_ID_LENOVO_TP10UBKBD: case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: ret = lenovo_probe_tp10ubkbd(hdev); break;
@@ -1377,6 +1382,7 @@ static void lenovo_remove(struct hid_device *hdev) break; case USB_DEVICE_ID_LENOVO_TP10UBKBD: case USB_DEVICE_ID_LENOVO_X1_TAB: + case USB_DEVICE_ID_LENOVO_X1_TAB2: case USB_DEVICE_ID_LENOVO_X1_TAB3: lenovo_remove_tp10ubkbd(hdev); break;
@@ -1427,6 +1433,8 @@ static const struct hid_device_id lenovo_devices[] = { */ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB2) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB3) }, { }
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 93b5c648ef82c..641292cfdaa6f 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c@@ -2116,12 +2116,18 @@ static const struct hid_device_id mt_devices[] = { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) }, - /* Lenovo X1 TAB Gen 2 */ + /* Lenovo X1 TAB Gen 1 */ { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB) }, + /* Lenovo X1 TAB Gen 2 */ + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_X1_TAB2) }, + /* Lenovo X1 TAB Gen 3 */ { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
--
2.39.5