Skip to content

Commit 8c2ad9a

Browse files
Sasha Finkelsteinmarcan
authored andcommitted
Add z2 touch panel tracing
Signed-off-by: Sasha Finkelstein <[email protected]>
1 parent fb36e30 commit 8c2ad9a

1 file changed

Lines changed: 221 additions & 0 deletions

File tree

proxyclient/hv/trace_z2.py

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# SPDX-License-Identifier: MIT
2+
3+
import struct
4+
from construct import *
5+
6+
from m1n1.hv import TraceMode
7+
from m1n1.proxyutils import RegMonitor
8+
from m1n1.utils import *
9+
10+
from m1n1.trace import ADTDevTracer
11+
from m1n1.trace.asc import ASCTracer, ASCRegs, EP, EPState, msg, msg_log, DIR
12+
from m1n1.trace.dart import DARTTracer
13+
from m1n1.trace.gpio import GPIOTracer
14+
from m1n1.trace.spi import SPITracer
15+
16+
DARTTracer = DARTTracer._reloadcls()
17+
ASCTracer = ASCTracer._reloadcls()
18+
SPITracer = SPITracer._reloadcls()
19+
20+
# SPI HID transport tracer for 2021 macbook models
21+
22+
kbd_node = None
23+
for node in hv.adt.walk_tree():
24+
try:
25+
if node.compatible[0] == "spi-1,spimc":
26+
for c in node:
27+
try:
28+
if c.compatible[0] == "hid-transport,k1":
29+
kbd_node = c
30+
break
31+
except AttributeError:
32+
continue
33+
except AttributeError:
34+
continue
35+
if kbd_node is not None:
36+
break
37+
38+
39+
class Z2Tracer(SPITracer):
40+
def start(self):
41+
super().start()
42+
self.txbuffer = []
43+
self.rxbuffer = []
44+
self.want_bytes = 0
45+
self.state = Z2Tracer.preboot
46+
def w_TXDATA(self, data):
47+
self.txbuffer.append(data.value)
48+
self.check_msg_finished()
49+
def r_RXDATA(self, data):
50+
self.rxbuffer.append(data.value)
51+
self.check_msg_finished()
52+
def check_msg_finished(self):
53+
if min(len(self.txbuffer), len(self.rxbuffer)) < self.want_bytes:
54+
return
55+
self.state(self)
56+
def bad_state(self):
57+
pass
58+
def error(self):
59+
self.log(f"RXBUF {' '.join(hex(x) for x in self.rxbuffer)}")
60+
self.log(f"TXBUF {' '.join(hex(x) for x in self.txbuffer)}")
61+
self.log(f"state: {self.state}")
62+
self.log("Tracer desynchronized, shutting down")
63+
self.state = Z2Tracer.bad_state
64+
def consume_bytes(self, n):
65+
self.txbuffer = self.txbuffer[n:]
66+
self.rxbuffer = self.rxbuffer[n:]
67+
def preboot(self):
68+
if self.txbuffer[0] == 0:
69+
self.want_bytes = 4
70+
self.state = Z2Tracer.init_zeros
71+
elif self.txbuffer[0] == 0x1e:
72+
self.want_bytes = 16
73+
self.state = Z2Tracer.processing_init_data
74+
else:
75+
self.error()
76+
def init_zeros(self):
77+
self.log("sent 4 zeroes")
78+
self.consume_bytes(4)
79+
self.state = Z2Tracer.preboot
80+
def processing_init_data(self):
81+
self.log("Sent init data")
82+
self.want_bytes = 2
83+
self.consume_bytes(16)
84+
self.state = Z2Tracer.main_hbpp
85+
def main_hbpp(self):
86+
if self.txbuffer[0] == 0x1a and self.txbuffer[1] == 0xa1:
87+
self.log("Sent int ack")
88+
self.consume_bytes(2)
89+
elif self.txbuffer[0] == 0x18 and self.txbuffer[1] == 0xe1:
90+
self.log("Sent nop")
91+
self.consume_bytes(2)
92+
elif self.txbuffer[0] == 0x1f and self.txbuffer[1] == 0x01:
93+
self.log("Sent request cal")
94+
self.consume_bytes(2)
95+
elif self.txbuffer[0] == 0x30 and self.txbuffer[1] == 0x01:
96+
self.state = Z2Tracer.send_blob_cmd
97+
self.want_bytes = 10
98+
elif self.txbuffer[0] == 0x1e and self.txbuffer[1] == 0x33:
99+
self.state = Z2Tracer.send_rmw_cmd
100+
self.want_bytes = 16
101+
elif self.txbuffer[0] == 0xee and self.txbuffer[1] == 0x00:
102+
self.state = Z2Tracer.main_z2
103+
self.want_bytes = 16
104+
else:
105+
self.error()
106+
def send_blob_cmd(self):
107+
length = (self.txbuffer[2] << 8 | self.txbuffer[3]) * 4
108+
self.consume_bytes(10)
109+
self.want_bytes = length + 4
110+
self.log(f"Sending blob of length {length}")
111+
self.state = Z2Tracer.send_blob_tail
112+
def send_blob_tail(self):
113+
self.log("Finished sendind blob")
114+
self.consume_bytes(self.want_bytes)
115+
self.want_bytes = 2
116+
self.state = Z2Tracer.main_hbpp
117+
def send_rmw_cmd(self):
118+
self.log('Sent RMW command')
119+
self.want_bytes = 2
120+
self.consume_bytes(16)
121+
self.state = Z2Tracer.main_hbpp
122+
def main_z2(self):
123+
if self.txbuffer[0] == 0xee:
124+
self.log("sent wake cmd")
125+
self.consume_bytes(16)
126+
elif self.txbuffer[0] == 0xe2:
127+
self.log("sent get device info cmd")
128+
self.consume_bytes(16)
129+
self.state = Z2Tracer.read_device_info_reply
130+
elif self.txbuffer[0] == 0xeb:
131+
length = (self.rxbuffer[1] | (self.rxbuffer[2] << 8)) + 5
132+
length = (length + 3) & (-4)
133+
self.consume_bytes(16)
134+
self.want_bytes = length
135+
self.state = Z2Tracer.read_interrupt_data
136+
elif self.txbuffer[0] == 0xe3:
137+
self.log(f"got report info for {self.txbuffer[1]}, len is {self.rxbuffer[3]}")
138+
self.consume_bytes(16)
139+
elif self.txbuffer[0] == 0xe7:
140+
self.want_bytes = self.txbuffer[3] + 5
141+
self.consume_bytes(16)
142+
self.state = Z2Tracer.reading_report_long
143+
elif self.txbuffer[0] == 0xe6:
144+
self.consume_bytes(16)
145+
self.state = Z2Tracer.read_report_reply
146+
else:
147+
self.error()
148+
def reading_report_long(self):
149+
self.log(f"got report {' '.join(hex(x) for x in self.rxbuffer)}")
150+
self.consume_bytes(self.want_bytes)
151+
self.want_bytes = 16
152+
self.state = Z2Tracer.main_z2
153+
def read_interrupt_data(self):
154+
data = self.rxbuffer[5:]
155+
tstamp2 = data[4] | (data[5] << 8) | (data[6] << 16)
156+
tx = [f"TS1 {hex(data[1])} TS2 {tstamp2} UNK1: {mxformat(data[7:16])} UNK2: {mxformat(data[17:24])}"]
157+
if len(data) >= 16:
158+
ntouch = data[16]
159+
for i in range(ntouch):
160+
ptr = 24 + 30 * i
161+
finger = data[ptr]
162+
state = data[ptr + 1]
163+
x = data[ptr + 4] | (data[ptr + 5] << 8)
164+
y = data[ptr + 6] | (data[ptr + 7] << 8)
165+
wj = data[ptr + 12] | (data[ptr + 13] << 8)
166+
wn = data[ptr + 14] | (data[ptr + 15] << 8)
167+
dg = data[ptr + 16] | (data[ptr + 17] << 8)
168+
prs = data[ptr + 18] | (data[ptr + 19] << 8)
169+
tx.append(f"F: {hex(finger)} S: {hex(state)} X: {x} Y: {y} MAJ: {wj} MIN: {wn} ANG: {dg} PRS: {prs} UNK1: {mxformat(data[ptr + 2:ptr+4])} UNK2: {mxformat(data[ptr + 8:ptr+12])} UNK3: {mxformat(data[ptr + 20:ptr+30])}")
170+
self.log(';'.join(tx))
171+
else:
172+
self.log(f"??? {mxformat(data)}")
173+
self.consume_bytes(self.want_bytes)
174+
self.want_bytes = 16
175+
self.state = Z2Tracer.main_z2
176+
def read_device_info_reply(self):
177+
self.log(f"got device info {' '.join(hex(x) for x in self.rxbuffer[:16])}")
178+
self.consume_bytes(16)
179+
self.state = Z2Tracer.main_z2
180+
def read_report_reply(self):
181+
self.log(f"got report {' '.join(hex(x) for x in self.rxbuffer[:16])}")
182+
self.consume_bytes(16)
183+
self.state = Z2Tracer.main_z2
184+
185+
def mxformat(ls):
186+
return ''.join(xformat(x) for x in ls)
187+
def xformat(x):
188+
x = hex(x)[2:]
189+
if len(x) == 1:
190+
x = '0' + x
191+
return x
192+
193+
194+
195+
# trace interrupts
196+
aic_phandle = getattr(hv.adt["/arm-io/aic"], "AAPL,phandle")
197+
spi_node = kbd_node._parent
198+
199+
#if getattr(spi_node, "interrupt-parent") == aic_phandle:
200+
# for irq in getattr(spi_node, "interrupts"):
201+
# hv.trace_irq(node.name, irq, 1, hv.IRQTRACE_IRQ)
202+
#for irq in hv.adt['/arm-io/gpio'].interrupts:
203+
# hv.trace_irq('/arm-io/gpio', irq, 1, hv.IRQTRACE_IRQ)
204+
205+
spi_tracer = Z2Tracer(hv, "/arm-io/" + spi_node.name)
206+
spi_tracer.start()
207+
208+
spi_pins_nub = {
209+
0x0: "clock32khz",
210+
}
211+
212+
#gpio_tracer_nub = GPIOTracer(hv, "/arm-io/nub-gpio", spi_pins_nub, verbose=0)
213+
#gpio_tracer_nub.start()
214+
215+
spi_pins = {
216+
0x6d: "enable_cs",
217+
0x8b: "reset"
218+
}
219+
220+
#gpio_tracer = GPIOTracer(hv, "/arm-io/gpio", spi_pins, verbose=0)
221+
#gpio_tracer.start()

0 commit comments

Comments
 (0)