望海之洲


澎湖冰洲的极客地带


VoodooI2C触摸板驱动教程

前言

这篇博客文章,是我在远景发布的教程:【他山之石,可以攻玉】黑苹果 I2C 触摸板驱动教程(分步)【积谷于此,以至四方】黑苹果 I2C 触摸驱动教程(第二版)的姊妹篇。本博客整合了两版帖子(权且定为第三版吧,嘻嘻~)。如远景所言,这篇教程来自 Alexandred VoodooI2C 驱动教程官网,本文基本忠实原文,并尽可能结合我的经验来谈如何修改 DSDT 驱动自己的 I2C 触摸板。

在这篇教程即将开始之前,也欢迎各位加入我的黑苹果触摸板驱动 QQ 群 1:837538729 QQ 群 2:921143329,来询问相关问题。我会尽可能为大家解决问题。


准备工作

参数收集

​ “工欲善其事,必先利其器”。对于 I2C 触摸板来说,首先要做的是明确你的触摸板是不是 I2C 触摸板。 明确了这一点,我们才能有的放矢,根据自己触摸板类型去有针对性地驱动自己的触摸板。

​ 确认自己的设备是不是 I2C 设备其实很简单,在 win 下打开设备管理器,找到人体学输入设备,如果是 I2C 设备,那么现在你应该能看到一个 I2C HID(I2C USB) 设备:

属性

​ 如果你能看到这个设备,说明你的触摸板是 I2C触摸板。否则,你的触摸板就是 PS2 类型的,请安装 VoodooPS2Controller 或者 AppleSmartTouchpad。(下载地址请参见博客的资源页面)

​ 另外需要注意:你需要确认自己的 CPU 平台以及架构代号。一般来说,根据后面 4 位数字型号的第一位,可以推测你的 Intel CPU 为几代 CPU,以及对应的架构。目前支持的架构有这些:

4 - Haswell

5 - Broadwell

6 - Skylake

7 - Kaby Lake

8 - Kaby Lake R / Coffee Lake / Cannon Lake / Whiskey Lake……

如果你的 CPU 低于 4 代,VoodooI2C 是不能在其上工作的。

对于 VoodooI2C 来说,它能识别下面硬件 ID 的 I2C 设备:

‘INT33C2’ 和 ‘INT33C3’ - Haswell

‘INT3432’ 和 ‘INT3433’ - Broadwell

‘pci8086,9d60’, ‘pci8086,9d61’, ‘pci8086,9d62’, ‘pci8086,9d63’, ‘pci8086,a160’ 和 ‘pci8086,a161’ - Skylake / Kaby Lake / Kaby Lake R

‘pci8086,9de8’, ‘pci8086,9de9’, ‘pci8086,a368’ 和 ‘pci8086,a369’ - Coffee Lake / Cannon Lake / Whiskey Lake

​ 如果你确认了你的触摸板/触摸屏是 I2C 设备并且在支持列表里,那么接下来你就可以继续进行你的准备工作。需要说明的是,对于 I2C USB 设备来说,接下来的步骤都没有必要,请直接移步安装步骤!!!

寻找对应的ACPI模块



在 DSDT 里,I2C 触摸设备会对应其 BIOS 设备名称下面,但是在一个完整的 DSDT 里,I2C 设备肯定不止一个,所以我们必须通过找出触摸板的 BIOS 设备名称来定位触摸板的 DSDT 代码片段。方法如下:

1、打开设备管理器,找到 I2C HID 设备,双击打开属性

2、进入详细信息,点击下拉菜单,找到 “ BIOS 设备名称” 一项,并将它记录下来

(有几个记录几个)

BIOS设备名称

​ 这样,我们就完成了寻找对应的 ACPI 模块的操作。一般来说,I2C 触摸设备名字是这些中的一个(但并不绝对):

触摸板:

TPDX, ELAN, SYNA, CYPR, TPAD, ETPD

触摸屏:

TPLX, ELAN, ETPD, SYNA, ATML

注意:这里的 X 代表某一个数字


安装工具



修改 DSDT 我们需要用到两款工具软件: IORegistryExplorer, Maciasl

这里这两款软件都有特殊的要求。IORegistryExplorer 要求为 2.1 版本,Maciasl要求为 Rehabman 大神的编译版,下载地址见博客资源。

下载驱动

​ VoodooI2C 要求必须运行在 Clover(四叶草),除此之外,一个稳定的 Mac 环境也是先决条件,确保在驱动触摸板前你的显卡和电池电量显示已经正常工作,并且你还需要提取好一份完整的DSDT。这个地方我不想过多解释DSDT相关基础知识,有需要了解的请移步这里

​ 在这些工作完成之后,我们就可以开始下载 VoodooI2C 驱动。 最好的获取方法是进入 Github 获取最新的驱动(下载地址)。在 Releases 下的驱动最稳定。

​ 下载 Releases 的压缩包后,我们解压,会得到 1 个核心驱动和 5 个目标驱动,对 VoodooI2C 来说,它需要两个驱动来完成工作:VoodooI2C.kext(核心驱动)+ 一个目标驱动。

​ 我们一共有四个目标驱动可供选择,它们的区别见下表:

驱动名称 功能 轮询模式 中断模式 是否需要调整 IONameMatch
VoodooI2CELAN 支持 ELAN 触摸板 ✔️ ✔️
VoodooI2CHID 支持大多数 I2C HID 多点触摸设备 ✔️ ✔️
VoodooI2CUPDDEngine UPDD 多点触控引擎 ✔️ ✔️
VoodooI2CFTE 支持 FTE 触摸板 ✔️ ✔️


准备修改

预备知识

​ 我们修改DSDT的目的,其核心在于让驱动识别触摸板的 GPIO 控制器,从而让驱动识别触摸板。对于极少的笔记本来说(如使用 Haswell 和 Boardwell 的设备),由于 GPIO 控制器本身就已经可以驱动,所以这类设备通常不需要打补丁也可以正常使用 VoodooI2C。

​ VoodooI2C 支持三种模式: APIC 中断模式,GPIO 中断模式轮询模式,这三种模式各有特点:APIC 中断基本不需要进行修改,功能完美,但是仅有极少数设备支持,GPIO 中断模式功能支持比较完善,但是修改量通常比较大,而且有可能出现 BUG 或者占用资源过高的问题(当然也更容易五国)(现在按理来说可以通过修补 FMCN & SSCN 来解决);而轮询模式是一种非常低效的模式,功能的支持可能会不太完善,不过轮询模式相比较中断模式而言适用范围更广。

​ 这两种模式究竟使用哪一种,需要结合你的 DSDT 代码和使用的驱动来定。目前能够同时支持这两种模式的驱动只有 VoodooI2CHID

补丁应用

​ 无论你使用哪一种工作模式,你首先都需要给你的 DSDT 应用 Windows 补丁。这个补丁可以在补丁源下面找到,根据你的出厂 Windows 系统版本来应用补丁就好,一般我们用的比较多的都是 Windows 10 Patch。

​ 如果你运行在 Skylake 的 CPU 下,通常你需要应用补丁源下的 SKL I2C Controller 补丁。这个补丁对于 Skylake 不一定会起作用,但是通常打上这个补丁也不会出什么问题,所以最好是应用这个补丁。

​ 如果你是 Skylake 平台或以上,那么如果想使用 GPIO 中断模式,你就必须对 GPIO 打补丁。应用补丁源下 GPIO Controller 补丁(中断模式)。

下面,就针对这轮询和中断这两种方式进行 DSDT 修改讲解。



DSDT 修改

中断模式

接下来我们先介绍 GPIO 中断模式。这里的情况比较复杂,在做这项工作之前,请务必备份好自己的原有 DSDT,然后进行修改。注意:接下来的 DSDT 修改全都在你的触摸设备代码下进行,不要去修改其他地方!!!

确认你的中断控制器类型

这一步需要确认你的中断控制器究竟是何种类型,在没有安装 VoodooI2C 驱动时,打开 IORegistryExplorer,搜索前面保存的 BIOS 设备名称,然后定位到 IOinterruptSpecifiers一项

iointerrupt

可以看到,窗口出现了一组十六进制数值。其中,最前面的两位数称为APIC pin值,这个值是你后面 DSDT 修改的重要依据,把它记录下来。

如果你没有 IOinterruptSpecifiers 这一项或者 APIC pin 值不大于 2F(十六进制如何比较大小请自行百度),那么请移步到安装步骤。(此处有概率有例外)

移除 APIC 中断控制器 相关代码

VoodooI2C在以 GPIO 中断模式调用DSDT中触摸设备的_CRS方法时,一律使用 SBFG 参数而不是 SBFI 参数。因此到这里,我们需要对 CRS 方法进行修改,使其正确返回 SBFG 的值。

用 MaciASL 打开你的 DSDT,然后搜索 SBFG (或者你的设备名),定位并仔细翻阅,你应该会找到一段类似于这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings               
{
Name (SBFI, ResourceTemplate ()
{
I2cSerialBusV2 (0x0015, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C1",
0x00, ResourceConsumer, , Exclusive,
)
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, )
{
0x0000006D,
}
})
Return (SBFI)
}

找到之后,首先要将 SBFI 更名为 SBFB,并删除下段代码:

1
2
3
4
5
                   Interrupt (ResourceConsumer, Level, ActiveLow, 
Exclusive, ,, )
{
0x0000006D,
}

比如以我的为例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 Name (SBFB, ResourceTemplate ()
{
I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, _Y2A, Exclusive,
)
})
}
Name (SBFI, ResourceTemplate ()
{
Interrupt (ResourceConsumer, Level, ActiveLow,
Exclusive, ,, )
{
0x0000006D,
}

根据上面要求,就应该修改为:

1
2
3
4
5
6
7
8
Name (SBFB, ResourceTemplate ()
{
I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.PCI0.I2C0",
0x00, ResourceConsumer, _Y2A, Exclusive,
)
})
}

SBFG (Gpioint) 修改

首先尝试在你触摸设备所对应的 DSDT 代码里搜索类似如下的这段代码:

1
2
3
4
5
6
7
8
9
Name (SBFG, ResourceTemplate ()    
{
GpioInt (Level, ActiveLow, ExclusiveAndWake,PullDefault,0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0000
}
})

比如我的是这样:

1
2
3
4
5
6
7
8
9
Name (SBFG, ResourceTemplate ()    
{
GpioInt (Level, ActiveLow, ExclusiveAndWake,PullDefault,0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0038
}
})

如果并没有这段代码,那么你需要在触摸设备的根目录下补上这段代码,像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Scope (_SB.PCI0.I2C0)
{
Device (TPAD)
{
Name (SBFG, ResourceTemplate ()
{
GpioInt (Level, ActiveLow, Exclusive, PullUp, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0038
}
})

......

如果有这段代码但蓝色字样的数值为 0,那么你就需要看看自己 _CRS 方法里是不是只有这一行语句:

1
Return (ConcatenateResTemplate (SBFB, SBFG))

​ 如果只有这行代码,那么你就可以转入后续的完善热补丁步骤;否则就需要给其添加 GPIO Pin 数值。

​ 如果你是 SunrisePoint 架构 6 代 至 8 代 Kaby Lake-R 处理器(比如:8250U, 8550U)查找 表一,寻找你之前的 APIC Pin 值,得到一个 IRQ 值;然后再前往 表二 根据 IRQ 找到一个对应的GPIO Pin值(10进制),把它转换为16进制值。如果这个十六进制数介于 5c 到 77 之间,那么这个数就是你需要的 GPIO Pin值。如果这个数不在这俩数之间,那你就会发现:你的 16 进制 APIC pin 值在表一对应了两个或以上的 IRQ 值。这就需要你分别对多个值进行测试,看哪个才是正确的。有的时候,也可能超出区间但是却只有一个值,那么尝试这个值就好。

​ 如果你是 CannonPoint(Lake) 架构 8/9 代标压 Coffee Lake(-R),查找 表一,寻找你之前的 APIC Pin 值,得到一个 IRQ 值;然后再前往 表二 根据 IRQ 找到一个对应的 GPIO Pin 值(10进制),接着转到 GPIO Pin 转换公式,你会看到 "CHIPSET_GPP(数字, 基数, 终止, gpio_基数), /* GPP_X */" 用之前 IRQ 中 "GPP_" 后面的 英文字母(A, B, C...)找到你对应的转换值,用你的 10 进制 GPIO Pin 值减去“基数”然后加上“gpio_基数”,把最后得到数字转换为 16 进制就是你最后的 GPIO Pin

​ 如果你是 CannonPoint(Lake) 架构 8 代低压刷新 Whiskylake:以 65U 结尾的处理器(比如:8265U, 8565U),查找 表一,寻找你之前的 APIC Pin 值,得到一个 IRQ 值;然后再前往 表二 根据 IRQ 找到一个对应的GPIO Pin值(10进制),接着转到 GPIO Pin 转换公式,你会看到 "CHIPSET_GPP(数字, 基数, 终止, gpio_基数), /* GPP_X */" 用之前 IRQ 中 "GPP_" 后面的 英文字母(A, B, C...)找到你对应的转换值,用你的 10 进制 GPIO Pin 值减去“基数”然后加上“gpio_基数”,把最后得到数字转换为 16 进制就是你最后的 GPIO Pin

​ 不过在某些极端状况下,你找到的值都不起作用的话。那么此时,你只能去尝试些比较常见的数值了,如0x17、0x1b、0x340x55。(仅限 SunrisePoint)

​ 总之,在完成之后,你需要把得到的 16 进制 GPIO pin 数值填入 SBFG 语句块里,像这样:

1
2
3
4
5
6
7
8
9
Name (SBFG, ResourceTemplate ()    
{
GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x17 // 这一行就是你需要填写的位置!
}
})

CRS 返回值的修改

##

​ 到这里,去 _CRS 方法下,确保所有返回语句只有这一条存在,像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
{
Store (Zero, Local0)
Store (Zero, Local1)
Store (DerefOf (Index (DerefOf (Index (TPID, Local0)), Zero)), Local1)
While (LAnd (LNotEqual (Local1, 0xFE), LNotEqual (Local1, TPDF)))
{
Increment (Local0)
If (LGreaterEqual (Local0, SizeOf (TPID)))
{
Break
}

Store (DerefOf (Index (DerefOf (Index (TPID, Local0)), Zero)), Local1)
}

Store (DerefOf (Index (DerefOf (Index (TPID, Local0)), One)), ADR0)
Store (DerefOf (Index (DerefOf (Index (TPID, Local0)), 0x02)), HID2)
Return (ConcatenateResTemplate (SBFB, SBFG))
}

轮询模式

轮询模式所做的修改相对较少,我们只需要保证以下三点即可:

1、确保没有应用GPIO Controller 补丁

2、确保没有做GPIO 的手动修改

3、确保CRS返回值中只不返回 SBFG (Gpioint)

补充说明

在这针对一些问题,楼主进行下补充:

1、不是所有没有 IOinterruptSpecifiers 值或者值小于 2F 的设备都可以直接使用 VoodooI2C。这类设备中,有一部分必须依赖轮询方式。这类触摸板只需按照上面轮询的方法去修改即可。
2、对于八代的支持问题。在八代中,Kaby Lake R是唯一一个完美支持的,而对于 Coffee Lake、Cannon Lake、Whiskey Lake 等,代码移植已经进入尾声,现在诚邀这些设备参与测试,感谢你的配合。

3、GPIO Pin 值问题。在找到 16 进制的 GPIO Pin 值的过程中,有时候可能出现找到的值只有一个却不在区间的情况,此时也要进行试验,如果不满足再试验其他。



热补丁移植

热补丁的修改是基于 DSDT 进行的,所以当这个教程 DSDT 修改部分和安装部分走完后,如果你确认你的 DSDT 可以驱动触摸板,就可以尝试将其提取出来,改造为热补丁。如果你的 DSDT 没有解决问题,也不要想着测试这个方法。

目前六代的 Skylake 的 I2C Controller 热补丁已经制作完成,也可以进行热补丁移植工作了。

添加 GPIO 与 XOSI 热补丁

下载 SSDT-XOSI.amlSSDT-GPIO.aml(如果你使用轮询模式,那么不要下载这个),解压并放在 ACPI/Patched 目录下,然后在四叶草编辑器的 ACPI 选项卡下添加如下两个改名补丁:

1
2
3
4
5
6
7
change _OSI to XOSI

Find5F4F5349 Replace:584F5349

change _STA to XSTA in GPI0

Find: 5F535441 Replace: 58535441 TgtBridge:47504930

如果你是六代Skylake的,那么还需要添加 SKL I2C Controller热补丁(详情见后文下载)

代码复制

接下来,将你修改好的触摸设备的 ACPI 代码复制到SSDT-触摸样本.dsl的 DefinitionBlock 大括号内里,像这样:

复制之后

复制之后,我们还要修正名称,来确保这个 SSDT 是正确的。修正的地方有三处:

修改名称

第一处第二处都修正为你的 BIOS 名称,而第三处则还要带上 BIOS 名称的全路径(以我的为例):

修改后

补充:经过本人实测,第一处的修不修改其实没有太大影响,不修改也是可以的。

除错

接下来,我们就进入了给热补丁排错的过程。

点击 编译 (Compile),你会发现此时热补丁会报一堆错误。这里面的错误,大多是因为缺少东西所致。你可能需要因此添加很多东西,比如引用Device、Method,还有一些数据等等。

在我提供的样本里,已经提供了两个示例展示如何引用。在这,我还是补几张图说明下引用的过程。比如,以我的报错为例。你可以看到,在其中有一条提示缺少了 TPDD:

报错

所以对应地,我们去 DSDT 搜索,直到最后定位到相应的数值(或者方法、设备以及它们的引用,最后定位只能是这几种):

tpdd

第一处表示了它的构造区域,第二处则表示这个名称的值。接下来,我们复制这个数据及其对应的构造区域到SSDT中:

tpdd修改

再点击 Compile,与 TPDD 相关的报错应该都消失了。

除了这个之外,有时候我们缺失的是设备或者方法,我们只需要从 MaciASL 下方确认它的全路径,然后使用这条语句引用即可:

1
External (xxxx.xxxx.xxxx, DeviceObj) //如果是方法,就使用Method0bj;如果是区域则使用FieldUnitObj

注意:这条语句要放在 DefinitionBlock 块内的最前面!

总之,最后你的 SSDT 要同 DSDT 一样没有 ERROR,这才算完成:

通过

热补丁教程中提及的有关热补丁我已经分享出来,点击这里下载


安装

​ 到这里,我们的修改就完成了,接下来就是安装。将你修改好的 DSDT(热补丁)放入 ACPI/patched,再放入驱动。在这个时候,我们需要注意,系统里 AppleIntelLpssI2C.kext 和 AppleIntelLpssI2CController.kext 这两个驱动有可能会导致 VoodooI2C 驱动不工作,因此,有必要移除这两个驱动。你可以选择直接删除它们然后重建缓存,也可以选择用四叶草 Config进行屏蔽。屏蔽的配置文件详见这里

​ 如果你使用的是热补丁方式,我们还需要改名 DSDT 里的触摸设备,来保证热补丁工作。

​ 首先利用 Hackintool 的计算器将你的触摸设备 BIOS 名称转换为 16 位 ASCII 码,然后给这个触摸设备改个名字来保证其不加载(比如改 TPAD 为 XPAD),再次生成一串 16 位 ASCII 码,它们共同构成了一个 ACPI 补丁,用四叶草编辑器把它填入:

XPAD

​ 接下来我们重启,如果配置正确,那么现在你应该可以使用你的触摸板了。如果仍然不能使用,那么你需要重新排查,看看自己的操作是否存在问题。有其是热补丁,要格外注意啰嗦模式里面的 ACPI Error,如果出现这个要及时查看自己的配置文件 ACPI 改名是否正确。



其他

VoodooI2C 使用 CSG 以及白果手势引擎来支持各种多点触控。其中,2.1.1后的版本,换用了白果手势引擎 (Magic Trackpad 2 模拟器)。这类手势可以通过系统设置里面触摸板的相关选项来设置。

下面就是Voodooi2c所支持的所有手势列表:

CSG手势:
1
2
3
4
5
6
7
8
9
·单击
·两指滚动
·三指配合alt的上下左右滚动
·四指滑动
·拖动(在“辅助功能”里的“鼠标和触摸板”中找到相关设置选项)
·向下 - Command + W
·向左- Command + Q
·向上 - 显示桌面
·向下 - Command + F11
白果手势:
1
2
3
·双指通知中心
·双指缩放
·双指返回(Safari浏览器)

另外,2.1.2以上的版本,加入了“鼠标插入时忽略内建触摸板”的功能配置以及“打字防误碰支持”(需要配合新版VoodooPS2Controller

教程已经大致更新完毕,后续仍会有补充。

教程中少部分内容由 Bat.bat 修补

-------------本文已结束,感谢您的阅读!!!-------------