python-validity/validitysensor/usb.py
2020-07-10 01:06:39 +12:00

122 lines
3.5 KiB
Python

import usb.core as ucore
from binascii import *
from .util import assert_status, unhex
from struct import unpack
from usb.util import claim_interface, release_interface
from threading import Thread
from usb.core import USBError
from .blobs import init_hardcoded, init_hardcoded_clean_slate
supported_devices=[
(0x138a, 0x0097),
(0x06cb, 0x009a),
]
def custom_match(d):
return (d.idVendor, d.idProduct) in supported_devices
class Usb():
def __init__(self):
self.interrupt_cb = None
self.trace_enabled = False
self.quit = None
self.dev = None
def open(self, vendor=None, product=None):
if vendor is not None and product is not None:
dev = ucore.find(idVendor=vendor, idProduct=product)
else:
dev = ucore.find(custom_match=custom_match)
self.open_dev(dev)
def open_dev(self, dev):
self.dev = dev
self.dev.default_timeout = 15000
self.thread = Thread(target=lambda: self.int_thread())
self.thread.daemon = True
self.thread.start()
def close(self):
if self.dev is not None:
try:
self.dev.reset()
self.dev = None
except:
pass
finally:
self.thread.join()
def usb_dev(self):
return self.dev
def send_init(self):
#self.dev.set_configuration()
# TODO analyse responses, detect hardware type
assert_status(self.cmd(unhexlify('01')))
assert_status(self.cmd(unhexlify('19')))
# 43 -- get partition header(?) (02 -- fwext partition)
# c28c745a in response is a FwextBuildtime = 0x5A748CC2
rsp=self.cmd(unhexlify('4302'))
assert_status(self.cmd(init_hardcoded))
(err,), rsp = unpack('<H', rsp[:2]), rsp[2:]
if err != 0:
# fwext is not loaded
print('Clean slate')
self.cmd(init_hardcoded_clean_slate)
def cmd(self, out):
if callable(out):
out = out()
if not out:
return 0
self.trace('>cmd> %s' % hexlify(out).decode())
self.dev.write(1, out)
resp = self.dev.read(129, 100*1024)
resp = bytes(resp)
self.trace('<cmd< %s' % hexlify(resp).decode())
return resp
def read_82(self):
try:
resp = self.dev.read(130, 1024*1024, timeout=10000)
resp = bytes(resp)
self.trace('<130< %s' % hexlify(resp).decode())
return resp
except Exception as e:
self.trace('<130< Error: %s' % repr(e))
return None
def int_thread(self):
try:
while True:
resp = self.dev.read(131, 1024, timeout=0)
resp = bytes(resp)
self.trace('<int< %s' % hexlify(resp).decode())
cb=self.interrupt_cb
if cb is None:
print('Ignoring spurious interrupt: %s' % hexlify(resp).decode())
else:
try:
cb(resp)
except Exception as e:
print('Exception on the interrupt thread: %s' % e)
except USBError as e:
self.trace('<int< Exception on interrupt thread: %s' % repr(e))
if self.quit != None:
self.quit(e)
finally:
self.trace('<int< Interrupt thread is dead')
def trace(self, s):
if self.trace_enabled:
print(s)
usb=Usb()