Skip to content
/ linux Public

Commit 409d190

Browse files
blhoward2Sasha Levin
authored andcommitted
HID: multitouch: add quirks for Lenovo Yoga Book 9i
[ Upstream commit 822bc5b ] The Lenovo Yoga Book 9i is a dual-screen laptop, with a single composite USB device providing both touch and tablet interfaces for both screens. All inputs report through a single device, differentiated solely by report numbers. As there is no way for udev to differentiate the inputs based on USB vendor/product ID or interface numbers, custom naming is required to match against for downstream configuration. A firmware bug also results in an erroneous InRange message report being received after the stylus leaves proximity, blocking later touch events. Add required quirks for Gen 8 to Gen 10 models, including a new quirk providing for custom input device naming and dropping erroneous InRange reports. Signed-off-by: Brian Howard <blhoward2@gmail.com> Tested-by: Brian Howard <blhoward2@gmail.com> Tested-by: Kris Fredrick <linux.baguette800@slmail.me> Reported-by: Andrei Shumailov <gentoo1993@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220386 Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5ed818e commit 409d190

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@
840840
#define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5
841841
#define USB_DEVICE_ID_LENOVO_X12_TAB 0x60fe
842842
#define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae
843+
#define USB_DEVICE_ID_LENOVO_YOGABOOK9I 0x6161
843844
#define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E 0x600e
844845
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d
845846
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019

drivers/hid/hid-multitouch.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
7676
#define MT_QUIRK_DISABLE_WAKEUP BIT(21)
7777
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
7878
#define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
79+
#define MT_QUIRK_YOGABOOK9I BIT(24)
7980

8081
#define MT_INPUTMODE_TOUCHSCREEN 0x02
8182
#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -229,6 +230,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
229230
#define MT_CLS_RAZER_BLADE_STEALTH 0x0112
230231
#define MT_CLS_SMART_TECH 0x0113
231232
#define MT_CLS_APPLE_TOUCHBAR 0x0114
233+
#define MT_CLS_YOGABOOK9I 0x0115
232234
#define MT_CLS_SIS 0x0457
233235

234236
#define MT_DEFAULT_MAXCONTACT 10
@@ -425,6 +427,14 @@ static const struct mt_class mt_classes[] = {
425427
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
426428
MT_QUIRK_ALWAYS_VALID |
427429
MT_QUIRK_CONTACT_CNT_ACCURATE,
430+
},
431+
{ .name = MT_CLS_YOGABOOK9I,
432+
.quirks = MT_QUIRK_ALWAYS_VALID |
433+
MT_QUIRK_FORCE_MULTI_INPUT |
434+
MT_QUIRK_SEPARATE_APP_REPORT |
435+
MT_QUIRK_HOVERING |
436+
MT_QUIRK_YOGABOOK9I,
437+
.export_all_inputs = true
428438
},
429439
{ }
430440
};
@@ -1566,6 +1576,38 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
15661576
if (rdata && rdata->is_mt_collection)
15671577
return mt_touch_report(hid, rdata);
15681578

1579+
/* Lenovo Yoga Book 9i requires consuming and dropping certain bogus reports */
1580+
if (rdata && rdata->application &&
1581+
(rdata->application->quirks & MT_QUIRK_YOGABOOK9I)) {
1582+
1583+
bool all_zero_report = true;
1584+
1585+
for (int f = 0; f < report->maxfield && all_zero_report; f++) {
1586+
struct hid_field *fld = report->field[f];
1587+
1588+
for (int i = 0; i < fld->report_count; i++) {
1589+
unsigned int usage = fld->usage[i].hid;
1590+
1591+
if (usage == HID_DG_INRANGE ||
1592+
usage == HID_DG_TIPSWITCH ||
1593+
usage == HID_DG_BARRELSWITCH ||
1594+
usage == HID_DG_BARRELSWITCH2 ||
1595+
usage == HID_DG_CONTACTID ||
1596+
usage == HID_DG_TILT_X ||
1597+
usage == HID_DG_TILT_Y) {
1598+
1599+
if (fld->value[i] != 0) {
1600+
all_zero_report = false;
1601+
break;
1602+
}
1603+
}
1604+
}
1605+
}
1606+
1607+
if (all_zero_report)
1608+
return;
1609+
}
1610+
15691611
if (field && field->hidinput && field->hidinput->input)
15701612
input_sync(field->hidinput->input);
15711613
}
@@ -1762,6 +1804,30 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
17621804
break;
17631805
}
17641806

1807+
/* Lenovo Yoga Book 9i requires custom naming to allow differentiation in udev */
1808+
if (hi->report && td->mtclass.quirks & MT_QUIRK_YOGABOOK9I) {
1809+
switch (hi->report->id) {
1810+
case 48:
1811+
suffix = "Touchscreen Top";
1812+
break;
1813+
case 56:
1814+
suffix = "Touchscreen Bottom";
1815+
break;
1816+
case 20:
1817+
suffix = "Stylus Top";
1818+
break;
1819+
case 40:
1820+
suffix = "Stylus Bottom";
1821+
break;
1822+
case 80:
1823+
suffix = "Emulated Touchpad";
1824+
break;
1825+
default:
1826+
suffix = "";
1827+
break;
1828+
}
1829+
}
1830+
17651831
if (suffix) {
17661832
hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
17671833
"%s %s", hdev->name, suffix);
@@ -2267,6 +2333,12 @@ static const struct hid_device_id mt_devices[] = {
22672333
USB_VENDOR_ID_LENOVO,
22682334
USB_DEVICE_ID_LENOVO_X12_TAB2) },
22692335

2336+
/* Lenovo Yoga Book 9i */
2337+
{ .driver_data = MT_CLS_YOGABOOK9I,
2338+
HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
2339+
USB_VENDOR_ID_LENOVO,
2340+
USB_DEVICE_ID_LENOVO_YOGABOOK9I) },
2341+
22702342
/* Logitech devices */
22712343
{ .driver_data = MT_CLS_NSMU,
22722344
HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH_WIN_8,

0 commit comments

Comments
 (0)