进阶篇-用热补丁驱动你的触摸板
版权©️声明 : 本文章神楽小白(GZ小白)的部落阁
前言
当你的触摸板无法正常工作时,或者一点也不工作时,那你可能就需要修改ACPI来修补修补你的触摸板来,使其能够正常工作。
毕竟一台笔记本电脑,用不了触摸板实在是太难受了。(如果你有钱买妙控板,那就另当别论了)
确定设备路径
1.进入Windows系统 ,打开设备管理器 ,找到人体输入学设备 ,确认自己是不是I2C触摸板(有可能是I2C USB),如果找不到I2C HID设备 ,下面的鼠标又没有PS2的时候,把每个都打开看看有没有Bios Device Name 里有 I2C 的 。
2.然后右键查看属性,在详细信息里找到触摸板的位置路径
像这里的路径就是:
_SB.PCI0.I2C0.TPD0
我们把它记下来吧,之后会用到。
确定APIC PIn
继续在Windows 下,设备管理器 中确认一下你的APIC Pin ,到如图所示位置:
在这个地方我们也能找到需要的APIC Pin 。
声明:如果这里括号里的值大于等于 1024(10进制),直接去做热补丁,删掉所有有关操作系统的判断就好了
你也可以在Mac 下查看APIC Pin
到Mac系统下,使用IORegistryExplorer 查看APIC Pin
在右上角搜索自己的触摸板名称,比如根据我们之前照出来的路径,触摸板设备的名称就为TPD0
那么我们为什么需要知道APIC Pin呢?因为APIC Pin 可以帮助你判断你的触摸板的工作状态 ,如果你的Pin小于2F 那么你的触摸板在macOS 就是APIC中断模式 的,你可以理解为“半免躯模式 ”了,几乎不需要做什么修改就能够比较好的驱动。当然,这是极少数的情况。
大部分人应该都是大于2F 的,因此触摸板会是GPIO中断模式 ,但因为在macOS下绝大部分人 的GPIO中断 模式无法直接驱动,才需要制作热补丁来使其正常工作。
归纳一下就是:
Pin < 2F 或者 无IOInterruptSpecifiers ,为APIC
Pin > 2F 需要制作热补丁使触摸板在GPIO模式 下正常工作
APIC中断,GPIO中断与轮询
这里我们稍微了解一下触摸板工作的三个模式:
APIC中断 :上文有提到,也就是最好的一个工作模式 ,当然只有极少数人 有这个运气是APIC中断
GPIO中断 :Windows系统下用的也是这个模式,是仅次于APIC中断 的,比较高效 ,也是我们首先推荐的模式。触摸板热补丁也是主要针对GPIO中断 有比较多的修改 。
轮询 :最低效的一个模式,但相比GPIO中断 ,这个模式的适用范围更广,大部分机子都能适用这个,虽然有时候可能有些问题,如,指针漂移 或者不灵敏 等,但却更容易驱动 。GPIO中断无法使用 的情况下,我们就选择使用轮询 模式。
总结归纳:
效率:APIC中断 > GPIO中断 > 轮询
驱动难易成度:GPIO中断 > 轮询 ,这里APIC中断 不作讨论,看你运气。
触摸板热补丁制作
在这个板块,我会教你如何去做触摸板热补丁(Hotpatch) ,包括GPIO中断 和轮询 两个模式的制作教程。我也会给出一个案例用于讲解,此案例请不要拿去直接用 (没有人会那么傻吧)。
首先我们用Maciasl 打开DSDT ,并新建一个文件。然后我们将DSDT的DefinitionBlock 部分复制到新建的文件中,并将其中的DSDT 的字符串改为SSDT ,如图:
然后我们根据之前确定的触摸板设备路径(_SB.PCI0.I2C0.TPD0)找到我们需要修改的 设备(Device) 。很简单,我们按Option + F 在搜索框中输入自己触摸板的名称 ,我们这里的是TPD0 ,然后回车搜索 ,找到位于**_SB.PCI0.I2C0下的 TPD0**设备。如图:
然后我们在新建的SSDT 中,先添加路径Scope(_SB.PCI0.I2C0) ,然后将整个TPD0设备 复制进去(一定要注意对应括号,不要复制错了 ),如图:
然后我们将TPD0 进行改名 ,改成TPXX 或者其他的什么都可以,只要不与DSDT中其他的设备名称相同有冲突。我们在新建的SSDT中查找 TPD0 ,并将所有找到的TPD0 ,都改成TPXX (或者自己改的名称)。
改名前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 DefinitionBlock ("", "SSDT", 2, "DELL ", "CBX3 ", 0x01072009) { Scope (_SB.PCI0.I2C0) { Device (TPD0) { Name (HID2, Zero) Name (SBFB, ResourceTemplate () { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "NULL", 0x00, ResourceConsumer, _Y38, Exclusive, ) }) Name (SBFG, ResourceTemplate () { GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, , ) { // Pin list 0x0000 } }) Name (SBFI, ResourceTemplate () { Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, _Y39) { 0x00000000, } }) CreateWordField (SBFB, \_SB.PCI0.I2C0.TPD0._Y38._ADR, BADR) // _ADR: Address CreateDWordField (SBFB, \_SB.PCI0.I2C0.TPD0._Y38._SPE, SPED) // _SPE: Speed CreateWordField (SBFG, 0x17, INT1) CreateDWordField (SBFI, \_SB.PCI0.I2C0.TPD0._Y39._INT, INT2) // _INT: Interrupts Method (GTID, 1, Serialized) { If (Arg0) { Switch (CBID) { Case (0x0896) { Return ("DELL0896") } Case (0x0895) { Return ("DELL0895") } Case (0x0894) { Return ("DELL0894") } Case (0x08A5) { Return ("DELL08A5") } Case (0x08A6) { Return ("DELL08A6") } Case (0x089C) { Return ("DELL089C") } Case (0x089D) { Return ("DELL089D") } Case (0x089E) { Return ("DELL089E") } Case (0x089F) { Return ("DELL089F") } Case (0x08A7) { Return ("DELL08A7") } Case (0x08A8) { Return ("DELL08A8") } Case (0x08A9) { Return ("DELL08A9") } Case (0x08BC) { Return ("DELL08BC") } Case (0x08BD) { Return ("DELL08BD") } Case (0x08C0) { Return ("DELL08C0") } Case (0x0949) { Return ("DELL0949") } Default { Return ("DELL0949") } } } Else { Return (0x20) } } Method (_INI, 0, Serialized) // _INI: Initialize { If ((OSYS < 0x07DC)) { SRXO (GPDI, One) } INT1 = GNUM (GPDI) INT2 = INUM (GPDI) If ((TPDM == Zero)) { SHPO (GPDI, One) } If ((TPDT == One)) { _HID = "SYNA2393" HID2 = 0x20 Return (Zero) } If ((TPDT == 0x02)) { _HID = "06CB2846" HID2 = 0x20 Return (Zero) } If ((TPDT == 0x06)) { _HID = "ALPS0000" HID2 = 0x20 BADR = 0x2C Return (Zero) } If ((TPDT == 0x05)) { _HID = GTID (One) HID2 = TPDH /* \TPDH */ Switch (CBID) { Case (0x08BC) { BADR = 0x15 } Case (0x08BD) { BADR = TPDB /* \TPDB */ } Case (0x08C0) { BADR = TPDB /* \TPDB */ } Default { BADR = TPDB /* \TPDB */ } } If ((TPDS == Zero)) { SPED = 0x000186A0 } If ((TPDS == One)) { SPED = 0x00061A80 } If ((TPDS == 0x02)) { SPED = 0x000F4240 } Return (Zero) } } Name (_HID, "XXXX0000") // _HID: Hardware ID Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID Name (_S0W, 0x03) // _S0W: S0 Device Wake State Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { If ((Arg0 == HIDG)) { Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2)) } If ((Arg0 == TP7G)) { Return (TP7D (Arg0, Arg1, Arg2, Arg3, SBFB, SBFG)) } Return (Buffer (One) { 0x00 // . }) } Method (_STA, 0, NotSerialized) // _STA: Status { If (((TPDT != Zero) && (I2CN & One))) { Return (0x0F) } Return (Zero) } Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { If ((OSYS < 0x07DC)) { Return (SBFI) /* \_SB_.PCI0.I2C0.TPD0.SBFI */ } If ((TPDM == Zero)) { Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG)) } Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFI)) } } } }
改名后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 DefinitionBlock ("", "SSDT", 2, "DELL ", "CBX3 ", 0x01072009) { Scope (_SB.PCI0.I2C0) { Device (TPXX) //这里将TPD0改为了TPXX { ······ CreateWordField (SBFB, \_SB.PCI0.I2C0.TPXX._Y38._ADR, BADR) // 这里将TPD0改为了TPXX CreateDWordField (SBFB, \_SB.PCI0.I2C0.TPXX._Y38._SPE, SPED) // 这里将TPD0改为了TPXX CreateWordField (SBFG, 0x17, INT1) CreateDWordField (SBFI, \_SB.PCI0.I2C0.TPXX._Y39._INT, INT2) // 这里将TPD0改为了TPXX ······ //没有改动的地方就没有列出来了 } } }
其实我们不难发现,其实也就Device 和CreateWordField 那里需要改。
然后我们注意到Method (_CRS, 0, NotSerialized) ,我们需要对他进行修改,我们看到这里有许多判断语句 ,其实我们只需要一句Return (ConcatenateResTemplate (XXXX, XXXX))
,其它都可以删除掉。当然,如果你的**_CRS里面还有些 赋值语句或者 其他的一些语句**,不只有If判断语句 的话,那么就不要乱删 了,以防出现问题。
修正 TPXX
内容:
所有 TPD0
替换为 TPXX
。
补丁中 _STA
部分替换为:
1 2 3 4 5 6 7 8 9 10 11 Method (_STA, 0, NotSerialized) { If (_OSI ("Darwin")) { Return (0x0F) } Else { Return (Zero) } }
GPIO中断实现
这里建议您先实现了轮询模式,再来移植中断
实现GPIO中断 ,我们需要做如下修改。
首先,我们先来讲解一些触摸板的相关内容 。我们可以在触摸板设备 中找到如下,GpioInt (GPIO中断)、Interrupt (APIC中断) 。
先看SBFI ,这个用来实现APIC中断 的,当这个值无效的时候(也就是APIC Pin 大于2F 的时候),走的是轮询
1 2 3 4 5 6 7 8 9 ······ Name (SBFI, ResourceTemplate () { Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, _Y39) { 0x00000000, } }) ······
我们再来看SBFB ,这个轮询 和中断 都可以调用。当然也有的**_CSR里面不返回这个,而是返回了>I2CM ,其实两者的用处是一样的,但 I2CM**里面包括了更多的东西。
我们可以这样理解吧,I2CM >=SBFB
1 2 3 4 5 6 7 8 9 ······ Name (SBFB, ResourceTemplate () { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "NULL", 0x00, ResourceConsumer, _Y38, Exclusive, ) }) ······
这里有一个重点,那就是SBFG ,其实我们看的不是SBFG 这个名字,而是里面的GpioInt ,这是中断所需要的。
1 2 3 4 5 6 7 8 9 10 11 ······ Name (SBFG, ResourceTemplate () { GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, , ) { // Pin list 0x0000 } }) ······
讲解完了这些,我们就正式开始动手进行修改吧
。
补全缺少的内容 。如果你发现你没有GpioInt ,那么你就复制下面那段代码到自己建立的触摸板设备 (TPXX)中。
1 2 3 4 5 6 7 8 9 10 11 ······ Name (SBFG, ResourceTemplate () { GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, , ) { // Pin list 0x0000 } }) ······
大部分人都是会有GpioInt 的,所以一般不需要这个步骤,没有的人不仅需要补上,而且需要计算GPIO Pin 。
所以说,有这个GpioInt 的,是不需要去算GPIO Pin 的,它自己会自动注入 的,当然你想去算一个Gpio Pin也没事,不影响。
计算GPIO Pin(可选择,见上面第1步的说明) 。计算这个Pin的时候,我们需要用到刚开始我们记录的APIC Pin (我之前记录的ACPI Pin 是0x33 )。我们需要将APIC Pin 转换为10进制,0x33 转换过来就是51 ,然后我们把APICPIN = 51
代入以下公式
这里我们要根据不同的处理器 选择,
Skylake :
1 2 3 4 5 6 If APICPIN > 47 And APICPIN <= 79 Then GPIOPIN = APICPIN - 24 GPIOPIN2 = APICPIN + 72 ElseIf APICPIN > 79 And APICPIN <= 119 Then GPIOPIN = APICPIN - 24 End If
CoffeeLake-H :
1 2 3 4 5 6 7 8 9 10 11 12 If APICPIN > 47 And APICPIN <= 71 Then GPIOPIN = APICPIN - 16 GPIOPIN2 = APICPIN + 240 If APICPIN > 47 And APICPIN <= 59 Then GPIOPIN3 = APICPIN + 304 ElseIf APICPIN > 71 And APICPIN <= 95 Then GPIOPIN = APICPIN - 8 GPIOPIN3 = APICPIN + 152 GPIOPIN2 = APICPIN + 120 ElseIf APICPIN > 95 And APICPIN <= 119 Then GPIOPIN = APICPIN If APICPIN > 108 And APICPIN <= 115 Then GPIOPIN2 = APICPIN + 20 End If
CoffeeLake-LF 和Whiskylake :
1 2 3 4 5 6 7 8 9 10 If APICPIN > 47 And APICPIN <= 71 Then GPIOPIN = APICPIN - 16 GPIOPIN2 = APICPIN + 80 ElseIf APICPIN > 71 And APICPIN <= 95 Then GPIOPIN2 = APICPIN + 184 GPIOPIN = APICPIN + 88 ElseIf APICPIN > 95 And APICPIN <= 119 Then GPIOPIN = APICPIN If APICPIN > 108 And APICPIN <= 115 Then GPIOPIN2 = APICPIN - 44 End If
最后,我们会得出GPIOPIN 的10进制,我们将其再转为16进制即可。
不过在某些极端状况下,你找到的值都不起作用的话。那么此时,你只能去尝试些比较常见的数值了,如0x17、0x1b、0x34 和0x55 。(仅限 SunrisePoint)
计算好了就把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 0x0017 // 这一行就是你需要填写的位置! } })
接下来就是**_CSR中返回语句的修改了,之前有提到我们 _CSR中,我们主要修改的就是其中的 Return返回语句**,那么GPIO中断呢,需要返回的是SBFB (或是I2CM等)和SBFG 。下面是原来的**_CSR**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { If ((OSYS < 0x07DC)) { Return (SBFI) /* \_SB_.PCI0.I2C0.TPD0.SBFI */ } If ((TPDM == Zero)) { Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG)) } Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFI)) }
这里,我们可以看到上面两个判断语句 ,我们都可以删除,删到最后就留一条Return (ConcatenateResTemplate (XXXX, XXXX))
就行了。如果你的CSR 里面还有其他的赋值语句 等等或者你搞不懂哪些可以删除 ,那么你就不要乱删除了,以防删错了,直接修改所有Return语句就行了。修改结果如下:
1 2 3 4 5 Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG)) //Return (ConcatenateResTemplate (SBFB, SBFG)) }
这里我们返回了I2CM 和SBFG 确定了GPIO中断 模式。
到这里GPIO中断 模式的修改就完成了!
轮询模式实现
这个模式就很简单了,你不需要像GPIO中断 模式那样添加GPIO Pin,我们直接修改CSR 中的返回语句,最终返回为SBFB 和SBFI 就行,修改结果如下:
1 2 3 4 5 Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFI)) //Return (ConcatenateResTemplate (SBFB, SBFI)) }
修改好了GPIO中断 或者轮询 到这里你的补丁本体就基本完成了!
禁用原触摸板设备
这里我们有两个方法来禁用触摸板设备,第一个方法为预置变量法 ,第二个方法为**_STA的修改法**,其中,第二个方法是通用的,第一个方法不一定对所有人适用!
预置变量法禁用原设备
目的:禁用原设备,防着你仿冒的设备与原设备发生冲突
这里需要我们观察原设备里的**_STA**,如下:
1 2 3 4 5 6 7 8 9 Method (_STA, 0, NotSerialized) // _STA: Status { If (((TPDT != Zero) && (I2CN & One))) { Return (0x0F) } Return (Zero) }
我们看这个If判断语句 ,意思是如果TPDT 不等于Zero ,那么则返回0x0F ,也就是启用设备。那我们不就只需要让TPDT 等于0不就行了吗?那样的话,它就不会执行If语句下的内容了。接下来我们在SSDT 中新建一个Scope作用域 ,路径为根目录 并把TPDT赋值为Zero ,添加If判断语句 确定其只在macOS 下生效,如下所示:
1 2 3 4 5 6 7 Scope (\) { If (_OSI ("Darwin")) { TPDT = Zero } }
_STA修改法禁用原设备
这个需要我们新建一个SSDT ,然后我们先写入根作用域 (把DSDT中的DefinitionBlock 复制到SSDT中就行,然后将里面的DSDT 改为SSDT ),如下:
1 2 3 DefinitionBlock ("", "SSDT", 2, "DELL", "CBX3", 0x01072009) { }
然后我们再添加Scope作用域 ,路径就是**原设备(TPD0)**的路径,如下:
1 2 3 4 5 6 DefinitionBlock ("", "SSDT", 2, "DELL", "CBX3", 0x01072009) { Scope (_SB.PCI0.I2C0.TPD0) { } }
然后把我下面给出的**_STA复制到这个 Scope作用域**中
1 2 3 4 5 6 7 8 9 10 11 Method (_STA, 0, NotSerialized) // _STA: Status { If (_OSI ("Darwin")) { Return (Zero) } Else { Return (XSTA()) } }
这个**_STA的意思差不多就是,在 macOS下返回 Zero**,也就是设备禁用 状态,在其他系统下,返回XSTA
接下来补充引用声明 就行了,需要补充的引用声明有两个,一个是TPD0 这个设备的,还有一个就是XSTA 的,写引用声明可以参考我论坛里的教程:
http://bbs.pcbeta.com/viewthread-1866928-1-1.html
也可以看本教程最后一块内容:排错-补充引用声明
最后补丁结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 DefinitionBlock ("", "SSDT", 2, "DELL", "CBX3", 0x01072009) { External (_SB.PCI0.I2C0.TPD0,DeviceObj) External (_SB.PCI0.I2C0.TPD0.XSTA,MethodObj) Scope (_SB.PCI0.I2C0.TPD0) { Method (_STA, 0, NotSerialized) // _STA: Status { If (_OSI ("Darwin")) { Return (Zero) } Else { Return (XSTA()) } } } }
当然使用这个方法不仅需要补丁,还需要添加重命名 ,防止**_STA**发生冲突。
我们需要用到Hex Friend 这个软件,我们使用Hex Friend 打开DSDT ,按Option + F (你的可能不同)打开搜索框 ,在搜索框左侧 ,将Hex 改为Text ,然后在Find 里搜索你的触摸板设备,我这里是TPD0,左边对于二进制的数字 ,右边对应字符 ,在二进制中会用高亮 标出你的触摸板设备代表的二进制,然后观察你的这串高亮的数字之后是不是跟着08 ,是的话,你就找到了自己的触摸板设备,接着需要在右边 找到你的触摸板设备,在沿着你的触摸板设备,找到下面的**_STA并把它选中,向右拉长 ,同时左边的 高亮数字也在拉长,大致拉两段多一点就差不多了,复制你 左边的高亮数字**,粘贴在Find 里搜索,如果除了你现在这段没有搜到其他的,那么就可以了,否则继续拉长再搜索,直到确定只有你这段没有重复!
然后我们打开config 在ACPI 部分中,添加重命名补丁:
1 2 3 4 5 Comment:I2C _STA to XSTA in TPD0 Find:5F535441 00A01390 929354 //这是我给出的DSDT中的,你们别抄 Replace:58535441 00A01390 929354 //在Replace中将开头的5F改成了58,意思可就是将_STA中的下划线改成了X,其他不变
这个拉长的方法是OC 和CLOVER 通用的,下面再介绍CLOVER 可以用的另一种方法。
在CLOVER 中,重命名有一个“桥”可以作为圈定重命名的范围 ,这个“桥”也就是TgtBridge 。如何使用这个TgtBridge 呢?很简单,首先我们先将**_STA这四个字符转换为 16进制**,利用Hackintool 就行,打开Hackintool 的计算器,在字符串转换 中,将**_STA填入到 ASCII中,复制转换出来的 16进制**,以此类推,再得到XSTA 的16进制 ,如下:
1 2 3 4 5 6 7 Comment:I2C _STA to XSTA in TPD0 Find:5F535441 //_STA Replace:58535441 //XSTA TgtBridge:
那么TgtBridge 怎么填呢?我们修改的**_STA是不是在 TPD0下,那么就把 _STA的范围也控制在 TPD0就行了,我们将 TPD0以上面的方法,也转换为 16进制就行了,填入到 TgtBridge**中去。最后结果如下:
1 2 3 4 5 6 7 Comment:I2C _STA to XSTA in TPD0 Find:5F535441 //_STA Replace:58535441 //XSTA TgtBridge:54504430 //TPD0
排错-补充引用声明
正确制作完触摸板补丁后,我们会有一些错误,而处理这些错误,需要我们补充引用声明。
见我写的这篇教程中:http://bbs.pcbeta.com/viewthread-1866928-1-1.html
比如我们点击编译 ,GNUM 报错了,那么我们到DSDT 中去搜素GNUM ,找到其被定义的位置所在,写成引用声明External 即可。
最终完成的补丁如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 DefinitionBlock ("", "SSDT", 2, "DELL ", "TPXX ", 0x01072009) { External (_SB_.GNUM, MethodObj) // 1 Arguments External (_SB_.INUM, MethodObj) // 1 Arguments External (_SB_.PCI0.HIDD, MethodObj) // 5 Arguments External (_SB_.PCI0.HIDG, IntObj) External (_SB_.PCI0.I2C0, DeviceObj) External (_SB_.PCI0.I2C0.I2CX, IntObj) External (_SB_.PCI0.I2CM, MethodObj) // 3 Arguments External (_SB_.PCI0.TP7D, MethodObj) // 6 Arguments External (_SB_.PCI0.TP7G, IntObj) External (_SB_.SHPO, MethodObj) // 2 Arguments External (CBID, FieldUnitObj) External (GPDI, FieldUnitObj) External (TPDB, FieldUnitObj) External (TPDH, FieldUnitObj) External (TPDM, FieldUnitObj) External (TPDS, FieldUnitObj) External (TPDT, FieldUnitObj) Scope (\) { If (_OSI ("Darwin")) { TPDT = Zero } } Scope (_SB.PCI0.I2C0) { Device (TPXX) { Name (HID2, Zero) Name (SBFB, ResourceTemplate () { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "NULL", 0x00, ResourceConsumer, _Y00, Exclusive, ) }) Name (SBFG, ResourceTemplate () { GpioInt (Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, , ) { // Pin list 0x0000 } }) Name (SBFI, ResourceTemplate () { Interrupt (ResourceConsumer, Level, ActiveLow, ExclusiveAndWake, ,, _Y01) { 0x00000000, } }) CreateWordField (SBFB, \_SB.PCI0.I2C0.TPXX._Y00._ADR, BADR) // _ADR: Address CreateDWordField (SBFB, \_SB.PCI0.I2C0.TPXX._Y00._SPE, SPED) // _SPE: Speed CreateWordField (SBFG, 0x17, INT1) CreateDWordField (SBFI, \_SB.PCI0.I2C0.TPXX._Y01._INT, INT2) // _INT: Interrupts Method (GTID, 1, Serialized) { If (Arg0) { Switch (CBID) { Case (0x0896) { Return ("DELL0896") } Case (0x0895) { Return ("DELL0895") } Case (0x0894) { Return ("DELL0894") } Case (0x08A5) { Return ("DELL08A5") } Case (0x08A6) { Return ("DELL08A6") } Case (0x089C) { Return ("DELL089C") } Case (0x089D) { Return ("DELL089D") } Case (0x089E) { Return ("DELL089E") } Case (0x089F) { Return ("DELL089F") } Case (0x08A7) { Return ("DELL08A7") } Case (0x08A8) { Return ("DELL08A8") } Case (0x08A9) { Return ("DELL08A9") } Case (0x08BC) { Return ("DELL08BC") } Case (0x08BD) { Return ("DELL08BD") } Case (0x08C0) { Return ("DELL08C0") } Case (0x0949) { Return ("DELL0949") } Default { Return ("DELL0949") } } } Else { Return (0x20) } } Method (_INI, 0, Serialized) // _INI: Initialize { INT1 = GNUM (GPDI) INT2 = INUM (GPDI) If ((TPDM == Zero)) { SHPO (GPDI, One) } If (One) { _HID = "SYNA2393" HID2 = 0x20 Return (Zero) } If (One) { _HID = "06CB2846" HID2 = 0x20 Return (Zero) } If (One) { _HID = "ALPS0000" HID2 = 0x20 BADR = 0x2C Return (Zero) } If (One) { _HID = GTID (One) HID2 = TPDH /* External reference */ Switch (CBID) { Case (0x08BC) { BADR = 0x15 } Case (0x08BD) { BADR = TPDB /* External reference */ } Case (0x08C0) { BADR = TPDB /* External reference */ } Default { BADR = TPDB /* External reference */ } } If ((TPDS == Zero)) { SPED = 0x000186A0 } If ((TPDS == One)) { SPED = 0x00061A80 } If ((TPDS == 0x02)) { SPED = 0x000F4240 } Return (Zero) } } Name (_HID, "XXXX0000") // _HID: Hardware ID Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID Name (_S0W, 0x03) // _S0W: S0 Device Wake State Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { If ((Arg0 == HIDG)) { Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2)) } If ((Arg0 == TP7G)) { Return (TP7D (Arg0, Arg1, Arg2, Arg3, SBFB, SBFG)) } Return (Buffer (One) { 0x00 // . }) } Method (_STA, 0, NotSerialized) // _STA: Status { If (_OSI ("Darwin")) { Return (0x0F) } Else { Return (Zero) } } Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG)) } } } }
这里也给出样本的DSDT 与SSDT :
链接: https://pan.baidu.com/s/1eGHOyGc6AleEr1aHZxWYaA
提取密码:s9t2
鸣谢
特别感谢以下几位大佬的支持:
@penghuibingzhou
本教程建立在penghuibingzhou 的教程上,进行了修改,本家如下:
https://www.penghubingzhou.cn/2019/01/06/VoodooI2C%20DSDT%20Edit/
@Bat.bat
感谢Bat大佬 的鼎力支持!
本教程由Bat 进行指导和修改!在Bat 大佬的大力帮助下,教程进行了修改和完善,纠正了许多错误的地方!
加入博主的Hackintosh交流群:679838716