给MacBook写一个更好的Windows触摸板驱动程序
适用于Apple MacBook / Magic Trackpad的Wi??ndows Precision触摸板驱动程序实现
众所周知 Boot Camp 的触摸板驱动不是那么好用,所以我们就来实现一个在 Windows 10 上能用的触摸板驱动吧。微软在 Windows 8.1 后加入了一套新的触摸板模型,叫做 Precision Touchpad,相关文档可以看这里。微软建议是用硬件( USB 或者 I2C )来实现 PTP 的 HID 设备,对于像 MacBook 这种不是原生 PTP HID 的设备来说,我们可以写一个 HID Miniport 驱动来把它变成一个 PTP HID 设备。
要完成这个 HID Miniport 驱动,驱动需要注册自己为一个过滤驱动,然后把后续的事情交给 HID KMDF/UMDF (mshidkmdf/mshidumdf),再完成相关的 IOCTL Routine。注意 HID KMDF/UMDF 的 IOCTL 略有不同,且一些 IO 操作也不同,比如 KMDF 可以直接读 IRP 包的 Buffer,而 UMDF 必须走 WDF 的那套拿 Buffer。
之后驱动需要实现 PTP?所需要的所有 HID 描述符和 Top-level Collection。HID 的描述符会被对应到相应的 C Struct 里。
之后需要配置和读取设备。配置设备其实就是给触摸板写一个 HID Feature Report 来打开触摸板模式,在基于 USB 的 MacBook 触摸板可以用 USB Control Transfer,基于 SPI 的触摸板需要给 IoTarget 发?IOCTL_HID_SET_FEATURE
?的 Internal Device Control。
之后便可以读取设备。在基于 USB 的 MacBook 触摸板上,可以使用中断,而 SPI 的需要使用轮询。按照 PTP 的 HID 描述符要求把数据喂回去然后完成请求即可。
几个坑和提示
- 设备 D0/D3 转换的时候可以关掉触摸板来省电(反正 MacBook 没 S0ix )
- 一定要精确报告每个 Input Frame 的测量时间,不然加速度会变得非常奇怪(你可以用?
KeQueryPerformanceCounter
/?QueryPerformanceCounter
,分别对应 km 和 um )来获得每一次读取的差值。注意在 HID 报告里,Timing 的单位是 100 微秒,且这个 Timing 的数据只有两个 2 Byte。数据允许 Rollover ) - 没有来得及完成的 Request 在转换和 Unload 时清理掉(
STATUS_CANCELLED
)。不然等着蓝屏吧 - Polling 单独开一个 System Thread,然后 Synchronous IOCTL Request 能不用就不要用(我还需要改 SPI 的这一部分)。
Q & A
为什么要这么干?好好用 macOS 不好吗?
因为我能这么干,为什么不这么干呢。其实有一些硬需求用 Windows 也挺好的。
有没有演示?
设备支持
某些MacBook Pro和MacBook Air存在问题。我正在研究它。如果你有安装Windows的设备,请联系我,这样我就可以远程查看问题(因为我没有很多设备)。
- ?非Retina MacBook
- ?一些非Retina MacBook Pro(2011年和2012年)
- ?配备Retina显示屏的MacBook Pro(MacBookPro 10,1,MacBookPro10,2和MacBookPro11,1)
- ?所有最近的MacBook Air(请报告您的型号是否不受支持)
- ?Apple Magic Trackpad 2(不稳定)
- ?(正在进行中)带Retina显示屏的MacBook Pro(2014年,2015年)
- ?(正在进行中)?MacBook Pro 2015,2016,2017
- 超简单的MySQL主从复制配置步骤
- 解决Centos下vsftp无法上传文件的问题,附vsftp配置详解
- 为iFrame添加动态载入效果,提高用户体验
- 分享超炫的表白页面和爱的纪念日源码
- 分享WordPress Mobile Pack汉化精简版及隐藏指定插件更新提示的方法
- Tomcat重启脚本For Windows
- js获取url中?后的参数,修复移动版无法切换到电脑版的BUG
- nginx配置文件参数详解
- LVS中Windows作为真实主机(RealServer)时的设置方法
- 菜鸟教程:Ngnix安装详解
- 教你如何去掉友荐和无觅的隐藏外链和版权链接
- 重置多说配置后的问题,这是不让我从良的节奏啊(附禁用谷歌在线字体的方法)!
- 10个超有趣的Linux命令
- 张戈博客惊现WordPress恶意代码,各位WP博主要注意下了!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 算法篇:树之翻转树
- 每日一题 | 约瑟夫问题
- 编码的浪漫:完美序列化的官方评测
- 【Vulnhub】symfonos2
- PWN入门(unsafe unlink)
- tf_cnn_benchmark 显存问题
- Spark on Kubernetes PodTemplate 的配置
- IO ports
- 【android系统】使用s3来上传下载文件
- 【Spark on Kubernetes】Executor环境变量
- Python获取字典值
- 应用程序InetlliJ IDEA不能打开
- yum install空间不足
- prometheus-nginxlog-exporter构建Nginx日志监控
- s3cmd put文件的过程