panda/python/isotp.py

143 lines
3.4 KiB
Python
Raw Normal View History

import binascii
2020-06-11 17:42:21 -06:00
import time
DEBUG = False
2017-09-30 13:21:36 -06:00
def msg(x):
if DEBUG:
print("S:", binascii.hexlify(x))
2017-09-30 13:21:36 -06:00
if len(x) <= 7:
2019-10-13 19:15:04 -06:00
ret = bytes([len(x)]) + x
2017-09-30 13:21:36 -06:00
else:
assert False
return ret.ljust(8, b"\x00")
2017-09-30 13:21:36 -06:00
2018-01-22 22:15:41 -07:00
kmsgs = []
def recv(panda, cnt, addr, nbus):
global kmsgs
ret = []
while len(ret) < cnt:
kmsgs += panda.can_recv()
nmsgs = []
for ids, ts, dat, bus in kmsgs:
if ids == addr and bus == nbus and len(ret) < cnt:
ret.append(dat)
else:
# leave around
nmsgs.append((ids, ts, dat, bus))
kmsgs = nmsgs[-256:]
return ret
2018-01-22 22:15:41 -07:00
2018-03-09 18:37:47 -07:00
def isotp_recv_subaddr(panda, addr, bus, sendaddr, subaddr):
msg = recv(panda, 1, addr, bus)[0]
2019-07-19 20:35:50 -06:00
# TODO: handle other subaddr also communicating
assert msg[0] == subaddr
2018-03-09 18:37:47 -07:00
if msg[1] & 0xf0 == 0x10:
2018-03-09 18:37:47 -07:00
# first
tlen = ((msg[1] & 0xf) << 8) | msg[2]
2018-03-09 18:37:47 -07:00
dat = msg[3:]
# 0 block size?
CONTINUE = bytes([subaddr]) + b"\x30" + b"\x00" * 6
2018-03-09 18:37:47 -07:00
panda.can_send(sendaddr, CONTINUE, bus)
idx = 1
for mm in recv(panda, (tlen - len(dat) + 5) // 6, addr, bus):
assert mm[0] == subaddr
assert mm[1] == (0x20 | (idx & 0xF))
2018-03-09 18:37:47 -07:00
dat += mm[2:]
idx += 1
elif msg[1] & 0xf0 == 0x00:
2018-03-09 18:37:47 -07:00
# single
tlen = msg[1] & 0xf
2018-03-09 18:37:47 -07:00
dat = msg[2:]
else:
print(binascii.hexlify(msg))
2018-03-09 18:37:47 -07:00
assert False
return dat[0:tlen]
# **** import below this line ****
2020-06-11 17:42:21 -06:00
def isotp_send(panda, x, addr, bus=0, recvaddr=None, subaddr=None, rate=None):
2018-01-22 19:55:10 -07:00
if recvaddr is None:
recvaddr = addr + 8
2018-01-22 19:55:10 -07:00
2018-03-08 15:39:36 -07:00
if len(x) <= 7 and subaddr is None:
2017-09-30 13:21:36 -06:00
panda.can_send(addr, msg(x), bus)
2018-03-08 15:39:36 -07:00
elif len(x) <= 6 and subaddr is not None:
2019-10-13 19:15:04 -06:00
panda.can_send(addr, bytes([subaddr]) + msg(x)[0:7], bus)
2017-09-30 13:21:36 -06:00
else:
2018-03-08 15:39:36 -07:00
if subaddr:
ss = bytes([subaddr, 0x10 + (len(x) >> 8), len(x) & 0xFF]) + x[0:5]
2018-03-08 15:39:36 -07:00
x = x[5:]
else:
ss = bytes([0x10 + (len(x) >> 8), len(x) & 0xFF]) + x[0:6]
2018-03-08 15:39:36 -07:00
x = x[6:]
2017-09-30 13:21:36 -06:00
idx = 1
sends = []
while len(x) > 0:
2018-03-08 15:39:36 -07:00
if subaddr:
sends.append(((bytes([subaddr, 0x20 + (idx & 0xF)]) + x[0:6]).ljust(8, b"\x00")))
2018-03-08 15:39:36 -07:00
x = x[6:]
else:
2019-10-13 19:15:04 -06:00
sends.append(((bytes([0x20 + (idx & 0xF)]) + x[0:7]).ljust(8, b"\x00")))
2018-03-08 15:39:36 -07:00
x = x[7:]
2017-09-30 13:21:36 -06:00
idx += 1
# actually send
panda.can_send(addr, ss, bus)
2018-01-22 19:55:10 -07:00
rr = recv(panda, 1, recvaddr, bus)[0]
if rr.find(b"\x30\x01") != -1:
for s in sends[:-1]:
panda.can_send(addr, s, 0)
rr = recv(panda, 1, recvaddr, bus)[0]
panda.can_send(addr, sends[-1], 0)
else:
2020-06-11 17:42:21 -06:00
if rate is None:
panda.can_send_many([(addr, None, s, bus) for s in sends])
else:
for dat in sends:
panda.can_send(addr, dat, bus)
time.sleep(rate)
2017-09-30 13:21:36 -06:00
2018-03-08 15:39:36 -07:00
def isotp_recv(panda, addr, bus=0, sendaddr=None, subaddr=None):
if sendaddr is None:
sendaddr = addr - 8
2018-03-08 15:39:36 -07:00
if subaddr is not None:
dat = isotp_recv_subaddr(panda, addr, bus, sendaddr, subaddr)
else:
msg = recv(panda, 1, addr, bus)[0]
2019-10-13 19:15:04 -06:00
if msg[0] & 0xf0 == 0x10:
2018-03-08 15:39:36 -07:00
# first
tlen = ((msg[0] & 0xf) << 8) | msg[1]
2018-03-08 15:39:36 -07:00
dat = msg[2:]
# 0 block size?
CONTINUE = b"\x30" + b"\x00" * 7
2018-03-08 15:39:36 -07:00
panda.can_send(sendaddr, CONTINUE, bus)
idx = 1
for mm in recv(panda, (tlen - len(dat) + 6) // 7, addr, bus):
assert mm[0] == (0x20 | (idx & 0xF))
2018-03-08 15:39:36 -07:00
dat += mm[1:]
idx += 1
elif msg[0] & 0xf0 == 0x00:
2018-03-08 15:39:36 -07:00
# single
tlen = msg[0] & 0xf
2018-03-08 15:39:36 -07:00
dat = msg[1:]
else:
assert False
dat = dat[0:tlen]
2017-09-30 13:21:36 -06:00
if DEBUG:
print("R:", binascii.hexlify(dat))
2017-09-30 13:21:36 -06:00
return dat