[db:标题]

摘要:荣耀 MagicBook 笔记本安装了汇顶的触控板,此触控板在Linux下被识别为鼠标,导致无法使用触控板手势等功能,其解决方案为……
UPD 2023/11/28:补丁已并入内核主线,并在v6.6.3发布。以下解决方案不再需要。 TL;DR 安装软件包 hid-tools,然后运行命令: sudo hid-feature set -f 30000 3 $(sudo hid-feature list-devices | grep BLTP7853 | awk -F: '{print $1}') 问题现象 荣耀 MagicBook 笔记本安装了汇顶的触控板,此触控板在Linux下被识别为鼠标,导致无法使用触控板手势等功能。该触控板自称为 BLTP7853:00 347D:7853 Touchpad,识别码为 347d:7853。问题表现为此触控板被识别为了两个设备(见 /proc/bus/input/devices),且有 Touchpad 字样的设备无数据。 `/proc/bus/input/devices` 中的部分输出 I: Bus=0018 Vendor=347d Product=7853 Version=0100 N: Name="BLTP7853:00 347D:7853 Mouse" P: Phys=i2c-BLTP7853:00 S: Sysfs=/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-1/i2c-BLTP7853:00/0018:347D:7853.0001/input/input11 U: Uniq= H: Handlers=event7 mouse0 B: PROP=0 B: EV=17 B: KEY=70000 0 0 0 0 B: REL=903 B: MSC=10 I: Bus=0018 Vendor=347d Product=7853 Version=0100 N: Name="BLTP7853:00 347D:7853 Touchpad" P: Phys=i2c-BLTP7853:00 S: Sysfs=/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-1/i2c-BLTP7853:00/0018:347D:7853.0001/input/input12 U: Uniq= H: Handlers=event8 mouse1 B: PROP=5 B: EV=1b B: KEY=e520 10000 0 0 0 0 B: ABS=2e0800000000003 B: MSC=20 分析 由于 /dev/input/eventX 无输出,此问题显然与 X11 或者 libinput 无关,而是一个内核漏洞。其中模块 hid_multitouch 是头号怀疑对象。 (以下分析来自 @nexplorer-3e)在 Windows 设备管理器中,也存在两个设备:I2C HID Device 和 Microsoft Input Configuration Device,且这两个设备的设备识别码均为 BLTP7853。在微软的文档中有关于此的说明:触摸板必需 HID 顶级集合 - 输入模式功能报告。 触摸板必需 HID 顶级集合 - 输入模式功能报告 摘录 输入模式功能报告由主机传达给 Windows 精确式触摸板,用于指示应该将哪个顶级集合用于输入报告。 可将两个集合用于输入报告:鼠标集合和 Windows 精确式触摸板集合。 默认情况下,在进行冷启动/电源周期时,Windows 精确式触摸板应使用鼠标集合报告输入。 Windows 精确式触摸板在任何时候应仅使用一个给定集合报告数据,并且在从主机收到指示所需输入模式的相应功能报告后,应该只从另一个集合进行报告。 主机指定的用于输入模式的值(用法 0x52)决定了应该用于报告输入的集合。 输入模式值 输入报告 0 鼠标集合 3 Windows 精确式触摸板集合 主机可以在读取报表描述符后,随时向 Windows 精确式触摸板发出输入模式功能报告(包括可能通过活动集合报告数据时)。 如果报告数据时发生模式切换,则所有触点和按钮状态都应报告为向上弹起,并且所有使用该集合进行的报告都应停止。 在所有触点实际上都已向上弹起后,可以使用新指定的集合进行报告。 输入模式不应由 Windows 精确式触摸板跨电源周期或主机发起的重置(USB 重置、HID I2C HIR、HID SPI HIR)保留;但是输入模式可以跨任何设备发起的重置(例如 HID I2C DIR、HID SPI DIR 等)保留。 实验性解决方案 根据 @nexplorer-3e 提供的分析可知,我们只需将输入模式(Inputmode)设置为 3 即可。借助 hid-tools 工具(在我的发行版上可直接使用 pacman 安装),我们可以方便的对其进行设置,使用下面命令即可 sudo hid-feature set -f <Inputmode feature id> 3 <device node path> 其中 <Inputmode feature id> 替换为输入模式功能编号(似乎总是 30000),<device node path> 替换为触控板设备的路径即可。 获得触控板设备的路径和输入模式功能编号 首先使用如下命令得到设备路径: sudo hid-feature list-devices | grep BLTP7853 可得到类似于如下的输出: /dev/hidraw1: BLTP7853:00 347D:7853 这说明在我的系统中,触控板设备的路径为 /dev/hidraw1。然后使用命令 sudo hid-feature list /dev/hidraw0 | grep Inputmode 可得到类似于如下的输出: 30000 | 0 | Digitizers | Inputmode | [ 0, 10] | 1 | 8 输入模式功能编号为 30000。 解决方案 @nexplorer-3e 已经向 LKML 提交了补丁,不过此补丁尚未合并入内核主线。 我们可以手工编译 hid-multitouch 模块来将此补丁应用到当前的内核中。首先查看内核版本(uname -r),然后下载对应的内核源代码,注意通常需要从你的发行版而不是 kernel.org 上下载代码,因为发行版会应用一些额外的补丁。在我的例子中,我正在使用的内核是 6.6.1-1-MANJARO,它的构建脚本来自于 core/linux66。 得到正在运行的内核的源代码后,打开 drivers/hid/hid-multitouch.c 并在注释 /* Ilitek dual touch panel */ 前(大约在 2050 行,取决于具体的内核版本,也可添加在其他合理位置,添加在此处只是为了保证按照设备的字典序排列)添加如下代码: /* HONOR GLO-GXXX panel */ { .driver_data = MT_CLS_VTL, HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, 0x347d, 0x7853) }, 然后获得正在运行的内核编译时的配置,这可以使用命令: zcat /proc/config.gz > .config 并使用如下命令编译内核(请根据实际硬件情况调整编译线程数): make prepare make -j16 因为编译出的内核模块的 BTF 数据版本可能不能与正在运行的内核完全一致,故去除 BTF 信息: objcopy --remove-section=.BTF drivers/hid/hid-multitouch.ko 最后使用编译出的模块替换原来的模块: sudo modprobe -v -r hid-multitouch sudo modprobe -v ./drivers/hid/hid-multitouch.ko 错误排查 如果 modprobe 报错,可使用命令 sudo dmesg 查看内核日志 确认无误后,可将模块文件放入系统目录以便在下次开机时自动装载: zstd ./drivers/hid/hid-multitouch.ko -o hid-multitouch.ko.zst cp /lib/modules/$(uname -r)/kernel/drivers/hid/hid-multitouch.ko.zst hid-multitouch.ko.zst.old # 可选,备份 sudo cp hid-multitouch.ko.zst /lib/modules/$(uname -r)/kernel/drivers/hid/ 关于副作用 这会加载一个缺少签名,BTF的树外的模块进入内核,并使内核进入污染模式,这通常不是一个问题。 参考资料 My touchpad was recognized as a mouse | Manjaro Linux Forum 触摸板必需 HID 顶级集合 | Microsoft Learn HID: multitouch: Add quirk for HONOR GLO-GXXX touchpad | Kernel Patchwork Packages core/linux66 | Manjaro Gitlab