1
1
# python library to interface with panda
2
+ from __future__ import print_function
3
+ import binascii
2
4
import struct
3
5
import hashlib
4
6
import socket
5
7
import usb1
6
- from usb1 import USBErrorIO , USBErrorOverflow
7
8
8
- try :
9
- from hexdump import hexdump
10
- except :
11
- pass
9
+ __version__ = '0.0.1'
10
+
11
+ class PandaHashMismatchException (Exception ):
12
+ def __init__ (self , hash_ , expected_hash ):
13
+ super (PandaHashMismatchException , self ).__init__ (
14
+ "Hash '%s' did not match the expected hash '%s'" % \
15
+ (binascii .hexlify (hash_ ), binascii .hexlify (expected_hash )))
12
16
13
17
def parse_can_buffer (dat ):
14
18
ret = []
@@ -33,7 +37,7 @@ def __init__(self, ip="192.168.0.10", port=1338):
33
37
34
38
def can_recv (self ):
35
39
ret = []
36
- while 1 :
40
+ while True :
37
41
try :
38
42
dat , addr = self .sock .recvfrom (0x200 * 0x10 )
39
43
if addr == (self .ip , self .port ):
@@ -61,7 +65,8 @@ def controlRead(self, request_type, request, value, index, length, timeout=0):
61
65
return self .__recv ()
62
66
63
67
def bulkWrite (self , endpoint , data , timeout = 0 ):
64
- assert len (data ) <= 0x10
68
+ if len (data ) > 0x10 :
69
+ raise ValueError ("Data must not be longer than 0x10" )
65
70
self .sock .send (struct .pack ("HH" , endpoint , len (data ))+ data )
66
71
self .__recv () # to /dev/null
67
72
@@ -73,18 +78,20 @@ def close(self):
73
78
self .sock .close ()
74
79
75
80
class Panda (object ):
81
+ REQUEST_TYPE = usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE
82
+
76
83
def __init__ (self , serial = None , claim = True ):
77
84
if serial == "WIFI" :
78
85
self .handle = WifiHandle ()
79
- print "opening WIFI device"
86
+ print ( "opening WIFI device" )
80
87
else :
81
88
context = usb1 .USBContext ()
82
89
83
90
self .handle = None
84
91
for device in context .getDeviceList (skip_on_error = True ):
85
92
if device .getVendorID () == 0xbbaa and device .getProductID () == 0xddcc :
86
93
if serial is None or device .getSerialNumber () == serial :
87
- print "opening device" , device .getSerialNumber ()
94
+ print ( "opening device" , device .getSerialNumber () )
88
95
self .handle = device .open ()
89
96
if claim :
90
97
self .handle .claimInterface (0 )
@@ -109,7 +116,7 @@ def list():
109
116
# ******************* health *******************
110
117
111
118
def health (self ):
112
- dat = self .handle .controlRead (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xd2 , 0 , 0 , 13 )
119
+ dat = self .handle .controlRead (Panda . REQUEST_TYPE , 0xd2 , 0 , 0 , 13 )
113
120
a = struct .unpack ("IIBBBBB" , dat )
114
121
return {"voltage" : a [0 ], "current" : a [1 ],
115
122
"started" : a [2 ], "controls_allowed" : a [3 ],
@@ -121,82 +128,79 @@ def health(self):
121
128
122
129
def enter_bootloader (self ):
123
130
try :
124
- self .handle .controlWrite (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xd1 , 0 , 0 , '' )
125
- except Exception :
131
+ self .handle .controlWrite (Panda .REQUEST_TYPE , 0xd1 , 0 , 0 , b'' )
132
+ except Exception as e :
133
+ print (e )
126
134
pass
127
135
128
136
def get_serial (self ):
129
- dat = str (self .handle .controlRead (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xd0 , 0 , 0 , 0x20 ))
130
- assert dat [0x1c :] == hashlib .sha1 (dat [0 :0x1c ]).digest ()[0 :4 ]
137
+ dat = self .handle .controlRead (Panda .REQUEST_TYPE , 0xd0 , 0 , 0 , 0x20 )
138
+ hashsig , calc_hash = dat [0x1c :], hashlib .sha1 (dat [0 :0x1c ]).digest ()[0 :4 ]
139
+ if hashsig != calc_hash :
140
+ raise PandaHashMismatchException (calc_hash , hashsig )
131
141
return [dat [0 :0x10 ], dat [0x10 :0x10 + 10 ]]
132
142
133
143
def get_secret (self ):
134
- dat = str (self .handle .controlRead (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xd0 , 1 , 0 , 0x10 ))
135
- return dat .encode ("hex" )
144
+ return self .handle .controlRead (Panda .REQUEST_TYPE , 0xd0 , 1 , 0 , 0x10 )
136
145
137
146
# ******************* configuration *******************
138
147
139
148
def set_controls_allowed (self , on ):
140
- if on :
141
- self .handle .controlWrite (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xdc , 0x1337 , 0 , '' )
142
- else :
143
- self .handle .controlWrite (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xdc , 0 , 0 , '' )
149
+ self .handle .controlWrite (Panda .REQUEST_TYPE , 0xdc , (0x1337 if on else 0 ), 0 , b'' )
144
150
145
151
def set_gmlan (self , on , bus = 2 ):
146
- if on :
147
- self .handle .controlWrite (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xdb , 1 , bus , '' )
148
- else :
149
- self .handle .controlWrite (usb1 .TYPE_VENDOR | usb1 .RECIPIENT_DEVICE , 0xdb , 0 , bus , '' )
152
+ self .handle .controlWrite (Panda .REQUEST_TYPE , 0xdb , 1 , bus , b'' )
150
153
151
154
def set_uart_baud (self , uart , rate ):
152
- self .handle .controlWrite (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe1 , uart , rate , '' )
155
+ self .handle .controlWrite (Panda . REQUEST_TYPE , 0xe1 , uart , rate , b '' )
153
156
154
157
def set_uart_parity (self , uart , parity ):
155
158
# parity, 0=off, 1=even, 2=odd
156
- self .handle .controlWrite (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe2 , uart , parity , '' )
159
+ self .handle .controlWrite (Panda . REQUEST_TYPE , 0xe2 , uart , parity , b '' )
157
160
158
161
def set_uart_callback (self , uart , install ):
159
- self .handle .controlWrite (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe3 , uart , int (install ), '' )
162
+ self .handle .controlWrite (Panda . REQUEST_TYPE , 0xe3 , uart , int (install ), b '' )
160
163
161
164
# ******************* can *******************
162
165
163
166
def can_send_many (self , arr ):
164
167
snds = []
168
+ transmit = 1
169
+ extended = 4
165
170
for addr , _ , dat , bus in arr :
166
- transmit = 1
167
- extended = 4
168
171
if addr >= 0x800 :
169
172
rir = (addr << 3 ) | transmit | extended
170
173
else :
171
174
rir = (addr << 21 ) | transmit
172
175
snd = struct .pack ("II" , rir , len (dat ) | (bus << 4 )) + dat
173
- snd = snd .ljust (0x10 , '\x00 ' )
176
+ snd = snd .ljust (0x10 , b '\x00 ' )
174
177
snds .append (snd )
175
178
176
- while 1 :
179
+ while True :
177
180
try :
178
- self .handle .bulkWrite (3 , '' .join (snds ))
181
+ print ("DAT: %s" % b'' .join (snds ).__repr__ ())
182
+ self .handle .bulkWrite (3 , b'' .join (snds ))
179
183
break
180
- except (USBErrorIO , USBErrorOverflow ):
181
- print "CAN: BAD SEND MANY, RETRYING"
184
+ except (usb1 . USBErrorIO , usb1 . USBErrorOverflow ):
185
+ print ( "CAN: BAD SEND MANY, RETRYING" )
182
186
183
187
def can_send (self , addr , dat , bus ):
184
188
self .can_send_many ([[addr , None , dat , bus ]])
185
189
186
190
def can_recv (self ):
187
- dat = ""
188
- while 1 :
191
+ dat = bytearray ()
192
+ while True :
189
193
try :
190
194
dat = self .handle .bulkRead (1 , 0x10 * 256 )
191
195
break
192
- except (USBErrorIO , USBErrorOverflow ):
193
- print "CAN: BAD RECV, RETRYING"
196
+ except (usb1 . USBErrorIO , usb1 . USBErrorOverflow ):
197
+ print ( "CAN: BAD RECV, RETRYING" )
194
198
return parse_can_buffer (dat )
195
199
196
200
# ******************* serial *******************
197
201
198
202
def serial_read (self , port_number ):
199
- return self .handle .controlRead (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe0 , port_number , 0 , 0x40 )
203
+ return self .handle .controlRead (Panda . REQUEST_TYPE , 0xe0 , port_number , 0 , 0x40 )
200
204
201
205
def serial_write (self , port_number , ln ):
202
206
return self .handle .bulkWrite (2 , chr (port_number ) + ln )
@@ -205,22 +209,22 @@ def serial_write(self, port_number, ln):
205
209
206
210
# pulse low for wakeup
207
211
def kline_wakeup (self ):
208
- ret = self .handle .controlWrite (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xf0 , 0 , 0 , "" )
212
+ self .handle .controlWrite (Panda . REQUEST_TYPE , 0xf0 , 0 , 0 , b'' )
209
213
210
214
def kline_drain (self , bus = 2 ):
211
215
# drain buffer
212
- bret = ""
213
- while 1 :
214
- ret = self .handle .controlRead (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe0 , bus , 0 , 0x40 )
216
+ bret = bytearray ()
217
+ while True :
218
+ ret = self .handle .controlRead (Panda . REQUEST_TYPE , 0xe0 , bus , 0 , 0x40 )
215
219
if len (ret ) == 0 :
216
220
break
217
- bret += str ( ret )
221
+ bret += ret
218
222
return bret
219
223
220
224
def kline_ll_recv (self , cnt , bus = 2 ):
221
- echo = ""
225
+ echo = bytearray ()
222
226
while len (echo ) != cnt :
223
- echo += str ( self .handle .controlRead (usb1 . TYPE_VENDOR | usb1 . RECIPIENT_DEVICE , 0xe0 , bus , 0 , cnt - len (echo ) ))
227
+ echo += self .handle .controlRead (Panda . REQUEST_TYPE , 0xe0 , bus , 0 , cnt - len (echo ))
224
228
return echo
225
229
226
230
def kline_send (self , x , bus = 2 , checksum = True ):
@@ -238,13 +242,12 @@ def get_checksum(dat):
238
242
self .handle .bulkWrite (2 , chr (bus )+ ts )
239
243
echo = self .kline_ll_recv (len (ts ), bus = bus )
240
244
if echo != ts :
241
- print "**** ECHO ERROR %d ****" % i
242
- print echo . encode ( "hex" )
243
- print ts . encode ( "hex" )
245
+ print ( "**** ECHO ERROR %d ****" % i )
246
+ print ( binascii . hexlify ( echo ) )
247
+ print ( binascii . hexlify ( ts ) )
244
248
assert echo == ts
245
249
246
250
def kline_recv (self , bus = 2 ):
247
251
msg = self .kline_ll_recv (2 , bus = bus )
248
252
msg += self .kline_ll_recv (ord (msg [1 ])- 2 , bus = bus )
249
253
return msg
250
-
0 commit comments