数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 83|回复: 2

[外设] 使用ESP32+ELAN触摸板打造Windows精确式触摸板设备

[复制链接]
发表于 5 小时前 | 显示全部楼层 |阅读模式
本帖最后由 bblueice 于 2025-12-27 15:11 编辑
观前提醒:作者不是计算机专业的。所以以下有什么涉及到专业错误的请指出来,作者虚心接受一切批评。

之前开发的ESP32 HID设备都是通过HID通信控制硬盘盒控制中心什么的。但其实这些只是进行简单的通信,并没有完全掌握HID设备的相关开发。

正好最近无聊,于是打算做一些进阶的东西来打发时间。

三年前刚上大学的时候从笔记本换到台式机主力,突然从触摸板+鼠标转到纯鼠标的我在面对部分场景时显得有些吃力。

之前都是鼠标配合触摸板使用的,只有纯鼠标后在桌面上划拉半天才想起来我已经没有触摸板(悲。心想要是在台式机上能用上触摸板多好啊。

暑假开始整HID玩后,这个愿望就显得越发强烈了……

于是这个计划便也提上日程了(喜。

目前已经完成:

硬件:
  • PCB设计
  • 材料选型


软件:
  • Microsoft精确式触摸板握手
  • ELAN TouchPad驱动
  • 从Mouse Mode (仅支持单指) 切换到Absolute Mode (支持多指), 感谢@ApprehensiveAnt9858
  • 单指触摸支持
  • 多指滑动手势支持
  • 物理按键支持(左键 & 右键)


未完成的:
  • 外壳设计 (SOLIDWORKS建模)
  • 为后续的蓝牙支持添加电池(蓝牙无线模式下指纹模块不可用)
  • 多指Tap手势支持(技术力有限暂时做不出来 ╥﹏╥)





网上已经有老哥尝试过了,他参考了外国大神的支持,使用的是ESP32+Synatics触摸板(P/S2协议)。

但是P/S2总感觉有一点小膈应……说不上来为什么,并且他的支持最高只有3指,最重要的是,他的多指手势并不是原生的,缺失了很多我想要的手势(要知道Windows原生支持的精确式触摸板功能是很完善的)。当然他用的也不是我们文章所使用到的USB HID技术栈。

叠个甲。这位老哥的思路是很好的,我没有批判这位老哥的意思,我只是觉得他的方案有太多局限性,如果再深入一点的话表现会更好(

所以我打算基于原生的HID触摸板,通过ESP32,造一个移动精确式触摸板设备,来满足自己的日常需要。



首先之一当然是要挑一块合适的触摸板啦。

根据Windows文档可以确定,主要的Windows精确式触摸板可以通过四种总线类型与主机进行连接:

  • USB HID
  • I2C HID
  • SPI HID
  • 第三方私有HID设备



无论是USB HID还是第三方私有HID设备,都好像不符合我的DIY之魂……

那么接下来就只剩下I2C HID和SPI HID类型的精确式触摸板了。

其实这两类在笔记本上很常见,但找到一块合适的触摸板有点难,需要找到合适的。

通过一篇老文章,我得知了来自ELAN Technology的触摸板能够支持标准的Microsoft HID over I2C Protocol:



选择范围瞬间缩小了不少。

查阅了大量包括笔记本图纸在内的资料后,我最终选择了板号Rev.A S8974A的触摸板:





这个触控板使用了ELAN 33370A作为触摸板主控,适用于R9000X 2021R/2022、小新Pro14、ThinkBook14 G4+,采用I2C HID协议。

与笔记本连接的定义如下:



插个题外话:感觉如果纯触摸板的话有点浪费了,于是我又购入了一个HP的指纹模块FM3483/3633,它可以通过USB总线提供Fingerprint for Windows Hello支持:



沟通触摸板和电脑USB HID的硬件依旧是我们的老熟人,ESP32-S2FN4R2。

ESP32-S2和指纹模块通过来自Microchip的USB2513B连接在同一块板子上:





硬件讲完了接下来就要到软件实现了,首先是多指识别。

在Windows体系里,多指手势并不是由应用或者触摸板硬件直接“声明”出来的,而是系统基于底层触点数据自动识别的。

也就是说,精确式触摸板只会上报原始触控数据:

  • 当前有多少个手指
  • 每个手指的唯一ID、X/Y坐标、是否接触、是否抬起
  • 时间连续的多帧数据

假如我做了一个三指触摸,从逻辑层面来说是这样的:
第一帧:3个触点,位置A/B/C
第二帧:3个触点,整体向上移动
第三帧:3个触点,继续向上
第四帧:全部抬起

当原始触控数据上报到系统后,Windows的精确式触摸板驱动会:

  • 解析HID报告
  • 把每个触点转换成内部的指针对象
  • 将这些指针数据送入到Input堆栈


系统就会知道:

  • 同一时间存在N个指针
  • 他们的运动轨迹和生命周期

最后系统会通过非公开的手势识别引擎判断多指触控类型。



接下来是触摸板的通信相关了。

HID通信在网上有很多文章,基本原理就是大差不差。所以这里主要分析的是I2C通信。

根据Windows精确式触摸板——设备总线连接定义,如果设备通过I2C连接到Host,至少需要5个引脚:

  • 数据脚(SDA)
  • 时钟脚(SCL)
  • 中断脚(INT)
  • 电源脚(VCC)
  • 接地脚(GND)


同时手册中建议至少使用400KHz的I2C始终速度且应独享一个I2C控制器,不然可能会导致I2C总线端超量。最后在设备开发中我使用了800KHZ作为通信基准速度。

另外手册中也提到了Touchpad I2C Over USB这一情况:

如果决定使用某个 USB 桥将 I²C Windows 精确式触摸板连接到其 Windows 主机,则该桥应使用设备的独特属性(wVendorID、wProductID、wVersionID)将触摸板公开为独特的设备节点。

所以最后开发的时候,我们需要在USB描述符中声明HID TouchPad和Multi-Touch。

这里要注意的是不要尝试去伪装原有的ELAN触摸板,不然的话可能会加载错误的驱动,最后进入错误的设备路径导致设备无法被识别。

我们需要让Windows相信,这是一个USB HID Touchpad,不是笔记本内建的触摸板,以此来防止驱动栈误判。

感谢前辈们的辛勤付出,在开发中间层的时候,我们在开发的时候可以参考Linux源码部分hid-elan.c来开发中间层。

所以我们在开发的时候可以根据源码中的定义开发。



关于ELAN TouchPad,由于在这方面“几乎”没有人做过(我基本没查到),所以相关资料很少。

首先是地址确认,随便写了个地址程序,确定其ADDR为0x15(0x78那个不知道是什么,后续都是基于0x15开发的):



理论上来说这时候直接读接收内容直接转译就行,但是这里开始就有大坑了。

根据一篇很老的参考资料可以得知,ELAN触摸板有两种运行方式,一种是Mouse Mode(仅支持单指,多指没数据,Report ID为0x01),另外一种是Absolute Mode(支持多指,Report ID为0x04)。

但是如果没有经过BIOS/EC的私有协商后,ELAN触摸板触摸板固件对MCU暴露的是Mouse Mode而不是Absolute Mode。

我们可以从raw data看到,它传来的数据基本就和鼠标没区别(xy位移而不是绝对坐标值),Report ID也是0x01:



后面多方查找后,我在Reddit论坛的一篇帖子上找到了一名网友 @ApprehensiveAnt9858 的解决方法,他通过抓取HID报文获得了这个诱骗代码:

  1. int elan_i2c_write_payload(uint8_t addr, uint16_t reg, const uint8_t* data, size_t len) {
  2.   Wire.beginTransmission(addr);
  3.   Wire.write(reg & 0xFF);       // LSB
  4.   Wire.write((reg >> 8) & 0xFF); // MSB
  5.   for (size_t i = 0; i < len; i++) {
  6.     Wire.write(data[i]);
  7.   }
  8.   return Wire.endTransmission();
  9. }

  10. elan_i2c_write_payload(I2C_ADDR, 0x0005, abs_mode_cmd, sizeof(abs_mode_cmd));

  11.   uint8_t abs_mode_cmd[] = {
  12.   0x33, 0x03, 0x06, 0x00,
  13.   0x05, 0x00, 0x03, 0x03,
  14.   0x00
  15. };
复制代码

这个代码通过HID描述符读取让触摸板固件认为有一个完整Host,它可以作用于Vendor Feature Report,固件内部状态机识别后开启PTP Collection。

最后的效果如下:







让触摸板进入PTP Mode后就简单的多了,剩下的两个大坑,一个是逆向ELAN I2C HID数据转译到USB,另一个是严格按照Microsoft Precision Touchpad HID格式去写转译层就行。

文中的代码和参考资料我会放在项目末尾。

最后的可以成功模拟出精确触摸板:






实物/测试大概是这样:

请忽略图中的胶布,因为fpc买短了所以只能先用胶布固定开发,等后面画个壳子装起来。









写在最后:

  • 因为小弟水平实在有限,所以希望大佬们可以帮忙优化一下代码,顺便请求各位大佬们做一下最后的多指tap适配,在此谢过各位大佬们~(๑˃̵ᴗ˂̵)
  • 项目仅适用于部分ELAN触摸板,Synaptic等其他厂家的触摸板需自行适配。



资料参考:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

打赏

参与人数 1家元 +18 收起 理由
jf201006 + 18 謝謝分享

查看全部打赏

发表于 5 小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 来自手机浏览器 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-12-27 21:03 , Processed in 0.124800 second(s), 10 queries , Gzip On, Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表