Skip to content

Commit 07fa6e6

Browse files
committed
Initial commit of miscellaneous E-mount reverse engineering scripts and tools
See my libsigrokdecode and sigrok_dumps repos for more info emount_plotdata.py is probably the most interesting unless you've got a logic analyzer setup
0 parents  commit 07fa6e6

File tree

5 files changed

+327
-0
lines changed

5 files changed

+327
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Miscellaneous tools and scripts for reverse engineering Sony's E-mount lens protocol
2+
3+
I'll organize/document this better later - but take a look at my libsigrokdecode repo along with my sigrok_dumps repo

capture_emount.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
sigrok-cli -d fx2lafw -c samplerate=6M --continuous -C 0=BODY_VD_LENS,1=VCC,2=LENS_CS_BODY,3=RXD,4=TXD,5=BODY_CS_LENS -t VCC=1 -w -O srzip -o $1

decode_emount.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
sigrok-cli -i $1 -P sony_emount:rx_cs=LENS_CS_BODY:rx=RXD:tx=TXD:tx_cs=BODY_CS_LENS

emount_plotdata.py

+316
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
#!/usr/bin/python
2+
3+
import argparse
4+
import binascii
5+
import struct
6+
import matplotlib.pyplot as plt
7+
import numpy as np
8+
9+
parser = argparse.ArgumentParser(description='Process emount data')
10+
parser.add_argument('--infile', dest='infile', help='input file')
11+
12+
args = parser.parse_args()
13+
14+
infile=open(args.infile,'r')
15+
16+
def apertureval(fstop):
17+
return hex(int((16.0+2*log(fstop,2))*256.0))
18+
19+
def valtoaperture(val):
20+
return 2**(val/512.0-8.0)
21+
22+
seen_lens = []
23+
24+
timespos = []
25+
mpos1 = []
26+
mpos2 = []
27+
speeds_p = []
28+
speeds_s = []
29+
#times32 = []
30+
#mpos32_1 = []
31+
#mpos32_2 = []
32+
#times34 = []
33+
#mpos34 = []
34+
35+
times1D = []
36+
pos1D = []
37+
38+
times1C = []
39+
pos1C = []
40+
41+
times1F = []
42+
pos1F = []
43+
44+
times22 = []
45+
pos22 = []
46+
47+
times3C = []
48+
pos3C = []
49+
50+
aperturetimes = []
51+
apertures1 = []
52+
apertures2 = []
53+
54+
aperturestattimes = []
55+
aperturestats1 = []
56+
aperturestats2 = []
57+
58+
times_cslot1 = []
59+
types_cslot1 = []
60+
cslot1_lens = [0x1D, 0x20]
61+
62+
times_cslot2 = []
63+
types_cslot2 = []
64+
cslot2_lens = [0x16, 0x17, 0x1a, 0x1b, 0x1e, 0x24, 0x27]
65+
66+
lasttime = None
67+
lastpos_p = None
68+
lastpos_s = None
69+
speedp = None
70+
speeds = None
71+
72+
min_pos = 99999999999999
73+
max_pos = 0
74+
75+
for line in infile:
76+
[pktts,data] = line.split(',',1)
77+
pktts = float(pktts)
78+
[lenstr,data] = data.split(',',1)
79+
pktlen = int(lenstr.split(':',1)[1],16)
80+
payloadlen = pktlen - 8
81+
[ftype,snum,speed,rxtx,data] = data.split(',',4)
82+
rxtx = int(rxtx.split(':',1)[1])
83+
if hex(pktlen) not in seen_lens:
84+
seen_lens.append(hex(pktlen))
85+
pktdata = bytearray.fromhex(data.split('\"',2)[1])
86+
if(rxtx == 0):
87+
bytesproc = 0
88+
while(bytesproc < payloadlen):
89+
cmdid = pktdata[bytesproc]
90+
if(cmdid == 0x6):
91+
timespos.append(pktts)
92+
motorpos1 = struct.unpack('<H', pktdata[bytesproc+3:bytesproc+5])[0]
93+
if(motorpos1 == 0):
94+
motorpos1 = None
95+
#This looks like a Metabones IV bug
96+
elif(motorpos1 == 0x7fff):
97+
print "Metabones bug 1"
98+
motorpos1 = None
99+
elif(motorpos1 == 0xa000):
100+
print "Metabones bug 2"
101+
motorpos1 = None
102+
# elif(motorpos1 == 0x01c0):
103+
# print "Metabones bug 3"
104+
# motorpos1 = None
105+
else:
106+
if(motorpos1 > max_pos):
107+
max_pos = motorpos1
108+
if(motorpos1 < min_pos):
109+
min_pos = motorpos1
110+
motorpos2 = struct.unpack('<H', pktdata[bytesproc+21:bytesproc+23])[0]
111+
if(motorpos2 == 0):
112+
motorpos2 = None
113+
114+
mpos1.append(motorpos1)
115+
mpos2.append(motorpos2)
116+
if(lasttime):
117+
if(motorpos1 is not None):
118+
speedp = (motorpos1-lastpos_p)/(pktts-lasttime)
119+
lastpos_p = motorpos1
120+
else:
121+
speedp = None
122+
if(motorpos2 is not None):
123+
speeds = (motorpos2-lastpos_s)/(pktts-lasttime)
124+
lastpos_s = motorpos2
125+
else:
126+
speeds = None
127+
speeds_p.append(speedp)
128+
speeds_s.append(speeds)
129+
lasttime = pktts
130+
if(motorpos1):
131+
lastpos_p = motorpos1
132+
if(motorpos2):
133+
lastpos_s = motorpos2
134+
#May actually be multiple status responses, but so far always seem to be the same order
135+
#but I should look for potential patterns when motorpos2 is 0
136+
bytesproc += 40
137+
elif(cmdid == 0x05):
138+
#This almost surely is actually multiple status responses - but the packets in this status slot are ALWAYS 0x69 bytes long
139+
#and so far I haven't analyzed this status packet at all
140+
bytesproc += 97
141+
aperturestattimes.append(pktts)
142+
#Aperture is bytes 1-2 and 3-4
143+
#One appears to lead the other - I'm guessing a predicted/current or current/last like motor pos
144+
#Possible reason for publishing "last" is to mitigate the impact of a lost response message
145+
(aperture1,aperture2)=struct.unpack_from('<HH', pktdata, offset=1)
146+
aperturestats1.append(valtoaperture(aperture1))
147+
aperturestats2.append(valtoaperture(aperture2))
148+
#Bytes 78 and 79 repeat the two bytes of the last 0x2F command
149+
#Strangely, 0x2F hops between the two command timeslots depending on where in the focusing phase
150+
#you are
151+
elif(cmdid == 0x1C):
152+
bytesproc += 2
153+
elif(cmdid == 0x1D):
154+
bytesproc += 2
155+
elif(cmdid == 0x1F):
156+
bytesproc += 2
157+
elif(cmdid == 0x22):
158+
bytesproc += 3
159+
elif(cmdid == 0x3C):
160+
bytesproc += 4
161+
else:
162+
print "Unknown response ID seen: " + hex(cmdid) + " in packet with len " + hex(pktlen)
163+
break
164+
165+
else:
166+
bytesproc= 0
167+
while(bytesproc < payloadlen):
168+
cmdid = pktdata[bytesproc]
169+
if(cmdid == 0x1C):
170+
bytesproc += 1
171+
times1C.append(pktts)
172+
pos1C.append(lastpos_p)
173+
elif(cmdid == 0x1D):
174+
times1D.append(pktts)
175+
positioncmd = struct.unpack('<H', pktdata[bytesproc+1:bytesproc+3])[0]
176+
if(positioncmd == 0):
177+
positioncmd = None
178+
pos1D.append(positioncmd)
179+
bytesproc += 5
180+
elif(cmdid == 0x03):
181+
aperturetimes.append(pktts)
182+
(aperture1,aperture2)=struct.unpack_from('<HH', pktdata, offset=4)
183+
apertures1.append(valtoaperture(aperture1))
184+
apertures2.append(valtoaperture(aperture2))
185+
bytesproc += 21
186+
elif(cmdid == 0x04):
187+
bytesproc += 14
188+
elif(cmdid == 0x22):
189+
data22 = struct.unpack('<H', pktdata[bytesproc+1:bytesproc+3])[0]
190+
times22.append(pktts)
191+
pos22.append(data22)
192+
bytesproc += 3
193+
elif(cmdid == 0x2F):
194+
# print str(pktts) + ": " + binascii.hexlify(pktdata[bytesproc:bytesproc+3])
195+
bytesproc += 3
196+
elif(cmdid == 0x3C):
197+
print str(pktts) + ": " + binascii.hexlify(pktdata[bytesproc:bytesproc+8])
198+
bytesproc += 8
199+
times3C.append(pktts)
200+
pos3C.append(lastpos_p)
201+
elif(cmdid == 0x1F):
202+
print str(pktts) + ": " + binascii.hexlify(pktdata[bytesproc:bytesproc+14])
203+
bytesproc += 14
204+
times1F.append(pktts)
205+
pos1F.append(lastpos_p)
206+
else:
207+
print "Unknown command ID seen: " + hex(cmdid) + " in packet with len " + hex(pktlen)
208+
break
209+
210+
# if pktlen == 0x30:
211+
# motorpos1 = struct.unpack('<H',pktdata[3:5])[0]
212+
# times30.append(pktts)
213+
# mpos30_1.append(motorpos1)
214+
# if(motorpos1 > max_pos):
215+
# max_pos = motorpos1
216+
# if(motorpos1 < min_pos):
217+
# min_pos = motorpos1
218+
#
219+
# motorpos2 = struct.unpack('<H',pktdata[21:23])[0]
220+
# if(motorpos2 == 0):
221+
# motorpos2 = None
222+
# mpos30_2.append(motorpos2)
223+
#
224+
# if(lasttime):
225+
# speedp = (motorpos1-lastpos_p)/(pktts-lasttime)
226+
# if(motorpos2):
227+
# speeds = (motorpos2-lastpos_s)/(pktts-lasttime)
228+
# else:
229+
# speeds = None
230+
# speeds30_p.append(speedp)
231+
# speeds30_s.append(speeds)
232+
# lasttime = pktts
233+
# lastpos_p = motorpos1
234+
# lastpos_s = motorpos2
235+
#
236+
#
237+
# if pktlen == 0x32:
238+
# firstcmd = pktdata[0]
239+
# if(firstcmd == 0x1D):
240+
# offset = 2
241+
# elif(firstcmd == 0x1C):
242+
# offset = 2
243+
# elif(firstcmd == 0x1F):
244+
# offset = 2
245+
# elif(firstcmd == 0x06):
246+
# offset = 0
247+
# else:
248+
# print "Saw unknown command " + hex(firstcmd)
249+
# break
250+
#
251+
# times32.append(pktts)
252+
# motorpos1 = struct.unpack('<H',pktdata[offset+3:offset+5])[0]
253+
# if(motorpos1 == 0):
254+
# motorpos1 = None
255+
# mpos32_1.append(motorpos1)
256+
# motorpos2 = struct.unpack('<H',pktdata[offset+21:offset+23])[0]
257+
# if(motorpos2 == 0):
258+
# motorpos2 = None
259+
# mpos32_2.append(motorpos2)
260+
# if pktlen == 0x34:
261+
# firstcmd = pktdata[0]
262+
# if(firstcmd == 0x3C):
263+
# offset = 4
264+
# elif(firstcmd == 0x06):
265+
# offset = 0
266+
# else:
267+
# print "Saw unknown command " + hex(firstcmd)
268+
# break
269+
# motorpos1 = struct.unpack('<H',pktdata[offset+3:offset+5])[0]
270+
# if(motorpos1 == 0):
271+
# motorpos1 = None
272+
# times34.append(pktts)
273+
# mpos34.append(motorpos1)
274+
#
275+
276+
if pktlen in cslot1_lens:
277+
times_cslot1.append(pktts)
278+
types_cslot1.append(cslot1_lens.index(pktlen))
279+
280+
if pktlen in cslot2_lens:
281+
times_cslot2.append(pktts)
282+
types_cslot2.append(cslot2_lens.index(pktlen))
283+
284+
seen_lens.sort()
285+
286+
print seen_lens
287+
288+
#print motordata
289+
plt.figure(1)
290+
plt1 = plt.subplot(311)
291+
plt1.plot(timespos,mpos1,'b',timespos,mpos2,'r')
292+
plt1.plot(times1D,pos1D,'co', times1C, pos1C, 'rx')
293+
plt1.plot(times1F,pos1F,'y^',times3C,pos3C,'g^',times22,pos22,'b^')
294+
types_cslot2 = np.array(types_cslot2)
295+
#plt.vlines(times_cslot2,18000+types_cslot2*250,18250+types_cslot2*250)
296+
#plt.axis([6.2,7.2,18500,19500])
297+
298+
plt2 = plt.subplot(312,sharex=plt1)
299+
plt2.plot(timespos,speeds_p,'b',timespos,speeds_s,'r')
300+
plt2.axhline(color='k')
301+
302+
plt3 = plt.subplot(313,sharex=plt1)
303+
plt3.semilogy(aperturetimes,apertures1,'b',aperturetimes,apertures2,'r')
304+
plt3.semilogy(aperturestattimes,aperturestats1,'c',aperturestattimes,aperturestats2,'g')
305+
#plt3.axis([None,None,-0.5,6.5])
306+
#plt.axis([6.2,7.2,-0.5,6.5])
307+
308+
#plt.subplot(313)
309+
#plt.plot(times_cslot1,types_cslot1,'m*')
310+
#plt.axis([None,None,-0.2,1.2])
311+
312+
print("Min position: " + str(min_pos) + ", max position: " + str(max_pos))
313+
plt.show()
314+
infile.close()
315+
316+

multidecode.mk

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
%.txt: %.sr
2+
/media/extradisk/adodd/emount/sigrok_data/decode_emount.sh $< &> $@
3+
4+
all: $(subst .sr,.txt,$(wildcard *.sr))

0 commit comments

Comments
 (0)