From nobody Tue Dec 2 02:43:44 2025 Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0650D321F54 for ; Tue, 18 Nov 2025 02:07:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763431664; cv=none; b=Ttf9kPZ9yDh/MGNjNcT7MZwQSbAWv3oG3GjdYT4w4tU8mQlPOIc37bGCuo+bIUzR0+OfTgpxWK7qsyFwlXuDpRPmymg7Wr+bEl/MyW4dzJ2L+CwOUpRZeV9e1mj1TRznyEOATvRmDUnhzpN/uHxsDyO3Ih84NzaPL3FgwB65BdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763431664; c=relaxed/simple; bh=o2QKtTD44YN+e8qaYopfIklkqMVOUdi9rq0+W5hx278=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=Kovt5PgqfJgRUFjeREW2MPRyJio1p2902I2U4b21PaS9A5rnKNEI/cPRy/Vkd/voy4DKcJ5Pcjb+bkhalFXO55jFKXLTvyFNgB9Z0ZvunRNLW0iPfbQqp06e3S3Dd2vD1u/knGoreG2oTbNXgtnhWjqR9X6ArezMOF8AsI6lwr8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gxppdoh7; arc=none smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gxppdoh7" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-880499b2bc7so48753386d6.3 for ; Mon, 17 Nov 2025 18:07:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763431662; x=1764036462; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=jh1QIfEZMIp5h4bee6+/t3kNjwgrq8onLyDs47w4Ztw=; b=gxppdoh7uTsnQT1+t4kbKOf63wSjkIl7b9Po+kY8AvjfTUkrcm7+ZEGbLWaeIGCOxb esaapMasl96HUiipzV6ULNgNKM6naPw/AxKW6VNTaRET08TSariBOkjTSvR1ogqzbXGr gmC2jjyB3nlf+kb2cU/UdPPnQr/vhM5JkrOpkrEzm4DLAW49DqkstI3yrAjiWVr/JBGV yaBGnPLcrAzvsIkl3zJEpzSeyacKlmPiU5s3ZuONyUP5mpXg1QMSb486qckVJx/KTbfl j9fHxCBlMKPMErHTz1XEtI2F+2t84v8sG+5TbDdeCd/ID+zhonOJlurSQXQqxWWzKew+ PNPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763431662; x=1764036462; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=jh1QIfEZMIp5h4bee6+/t3kNjwgrq8onLyDs47w4Ztw=; b=Bf5KQ0uMCkj0qIsN8AvIo/acxbgUDRYtI0R4gJ44ZUMPMCLcZdmkXjLfry/T4wvedB Y/HcsLRoCJ6af6lgN8HIIhVxwp5ROzK6kvBJTDqR3rv2Wdo99LBfWQMOVIV0DldDEFSX ql7nXl8R8rhjOIIOOouTDYkYtgXoIjh/kG7WY8Px+JUgSf420hQIhBzCn1TCq++3jz8i mAIskdGnkVMcCWMbThNES2oawIZOhpcjmKmt6PvwEXg3ChB/Nob+bMAydE66W7pjMXws ZCYm7ochg8R9FWgxX08EAmkzEYoFL7bvgNA1ds1mWR28Fzew+1PTNdKqeM20cJr6Viw9 PrzQ== X-Forwarded-Encrypted: i=1; AJvYcCXoAbCp/rOJXejc/n96Wzm08ugzOlgoLYmJZvNV3Jj5TrqNHob3tcpiNaGTsP2AvDemItuNz55Z9Tog+ZM=@vger.kernel.org X-Gm-Message-State: AOJu0YzQXr5ofVAasOTGHa1d0z1jYquW/mxzuB8TRjj8QsTzdMiqliS6 sHUqDlJnKZXJsZFDepGaLroQV8JqiiYvL0/tUyb8rcc0q8b4DWGIE71o X-Gm-Gg: ASbGncs0kY/ZNxNSYG/3o9zRFSygTLwpk/BBAtvnlZdRGnLlan3E6XsK25J7XzLp2lm 5FnsusFN0d3e4KT5BKI1TogzZlAkajp2gq+CR6ODpslfPWzv1HnGwbb8eaQOXD0Pdo/joXpiZiu Jj17vppfMabqYQThfJZ/Wft7zAsinD+lGaCEpTuq+YiXyc/P5N2mMdaC8ytH7lVImK6cBu7d0q7 w31QO5ipNF4qX5lZlZOY1Yvi0stsPFXVgckcxnMyoaJkq5gkUCEWgvlEgkW9iuEtm9S8XYx9VO7 PKBQK9enftrB/+fEk1095cXqT3CKr2tEU6GVhbVZpewkuwwlN7m/pDR9IGuJU3Llc9wjSUhDGpN qLcMwhyWZuNfFntjoCqQze5eX73FfgFvCGa79UzsieFNcoPtjSBWVajgF4JkW69gRNHqMCp0n5r UHKuwkkkhzPNoivQibqZy7ftZzyY/N6kiAXgEITAM0SZJQpuU4Cq1ZaKZVArnwaRM/IpcNkAQ= X-Google-Smtp-Source: AGHT+IGoqcQKgUIUh8dXIrcnrONk2oUR1Q1PCtS89nErtNnSj/oGJUO4MdNBIqxDlaSlVwfRkyKesQ== X-Received: by 2002:a05:6214:508b:b0:880:57b3:cd04 with SMTP id 6a1803df08f44-88292586a0cmr163975306d6.1.1763431661884; Mon, 17 Nov 2025 18:07:41 -0800 (PST) Received: from localhost.localdomain (pool-100-36-128-72.washdc.fios.verizon.net. [100.36.128.72]) by smtp.googlemail.com with ESMTPSA id 6a1803df08f44-8828613962esm104966846d6.0.2025.11.17.18.07.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Nov 2025 18:07:41 -0800 (PST) From: Brian Howard To: Cc: blhoward2@gmail.com, Andrei Shumailov , Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] HID: multitouch: add quirks for Lenovo Yoga Book 9i Date: Mon, 17 Nov 2025 21:07:21 -0500 Message-ID: <20251118020723.6600-1-blhoward2@gmail.com> X-Mailer: git-send-email 2.49.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add required quirks for Lenovo Yoga Book 9i Gen 8 to Gen 10 models,=20 including a new quirk providing for custom input device naming and=20 dropping erroneous InRange reports. 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 (with everything other than X/Y=20 as 0) being received after the stylus leaves proximity, blocking later=20 touch events.=20 Signed-off-by: Brian Howard Tested-by: Brian Howard Reported-by: Andrei Shumailov Closes: https://bugzilla.kernel.org/show_bug.cgi?id=3D220386 --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 73 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0723b4b1c9ec..e896a6310bb2 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -833,6 +833,7 @@ #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 #define USB_DEVICE_ID_LENOVO_X12_TAB 0x60fe #define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae +#define USB_DEVICE_ID_LENOVO_YOGABOOK9I 0x6161 #define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E 0x600e #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 179dc316b4b5..a828aac59cb2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -76,6 +76,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_DISABLE_WAKEUP BIT(21) #define MT_QUIRK_ORIENTATION_INVERT BIT(22) #define MT_QUIRK_APPLE_TOUCHBAR BIT(23) +#define MT_QUIRK_YOGABOOK9I BIT(24) =20 #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 @@ -229,6 +230,7 @@ static void mt_post_parse(struct mt_device *td, struct = mt_application *app); #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 #define MT_CLS_SMART_TECH 0x0113 #define MT_CLS_APPLE_TOUCHBAR 0x0114 +#define MT_CLS_YOGABOOK9I 0x0115 #define MT_CLS_SIS 0x0457 =20 #define MT_DEFAULT_MAXCONTACT 10 @@ -424,6 +426,14 @@ static const struct mt_class mt_classes[] =3D { .quirks =3D MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE, + }, + { .name =3D MT_CLS_YOGABOOK9I, + .quirks =3D MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_FORCE_MULTI_INPUT | + MT_QUIRK_SEPARATE_APP_REPORT | + MT_QUIRK_HOVERING | + MT_QUIRK_YOGABOOK9I, + .export_all_inputs =3D true }, { } }; @@ -1557,6 +1567,7 @@ static void mt_report(struct hid_device *hid, struct = hid_report *report) struct mt_device *td =3D hid_get_drvdata(hid); struct hid_field *field =3D report->field[0]; struct mt_report_data *rdata; + int f, i; =20 if (!(hid->claimed & HID_CLAIMED_INPUT)) return; @@ -1565,6 +1576,38 @@ static void mt_report(struct hid_device *hid, struct= hid_report *report) if (rdata && rdata->is_mt_collection) return mt_touch_report(hid, rdata); =20 + /* Lenovo Yoga Book 9i requires consuming and dropping certain bogus repo= rts */ + if (rdata && rdata->application && + (rdata->application->quirks & MT_QUIRK_YOGABOOK9I)) { + + bool all_zero_report =3D true; + + for (f =3D 0; f < report->maxfield && all_zero_report; f++) { + struct hid_field *fld =3D report->field[f]; + + for (i =3D 0; i < fld->report_count; i++) { + unsigned int usage =3D fld->usage[i].hid; + + if (usage =3D=3D HID_DG_INRANGE || + usage =3D=3D HID_DG_TIPSWITCH || + usage =3D=3D HID_DG_BARRELSWITCH || + usage =3D=3D HID_DG_BARRELSWITCH2 || + usage =3D=3D HID_DG_CONTACTID || + usage =3D=3D HID_DG_TILT_X || + usage =3D=3D HID_DG_TILT_Y) { + + if (fld->value[i] !=3D 0) { + all_zero_report =3D false; + break; + } + } + } + } + + if (all_zero_report) + return; + } + if (field && field->hidinput && field->hidinput->input) input_sync(field->hidinput->input); } @@ -1761,6 +1804,30 @@ static int mt_input_configured(struct hid_device *hd= ev, struct hid_input *hi) break; } =20 + /* Lenovo Yoga Book 9i requires custom naming to allow differentiation in= udev */ + if (hi->report && td->mtclass.quirks & MT_QUIRK_YOGABOOK9I) { + switch (hi->report->id) { + case 48: + suffix =3D "Touchscreen Top"; + break; + case 56: + suffix =3D "Touchscreen Bottom"; + break; + case 20: + suffix =3D "Stylus Top"; + break; + case 40: + suffix =3D "Stylus Bottom"; + break; + case 80: + suffix =3D "Emulated Touchpad"; + break; + default: + suffix =3D ""; + break; + } + } + if (suffix) { hi->input->name =3D devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s %s", hdev->name, suffix); @@ -2266,6 +2333,12 @@ static const struct hid_device_id mt_devices[] =3D { USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB2) }, =20 + /* Lenovo Yoga Book 9i */ + { .driver_data =3D MT_CLS_YOGABOOK9I, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_YOGABOOK9I) }, + /* Logitech devices */ { .driver_data =3D MT_CLS_NSMU, HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH_WIN_8, --=20 2.49.0