155 lines
5.0 KiB
Python
155 lines
5.0 KiB
Python
|
# NOTE: This script is test under Python 3.x
|
||
|
|
||
|
__copyright__ = "Copyright (C) 2020~2021 Nuvoton Technology Corp. All rights reserved"
|
||
|
|
||
|
import sys
|
||
|
import usb.core
|
||
|
import usb.util
|
||
|
import json
|
||
|
import typing
|
||
|
|
||
|
XFER_LEN_CMD = 0x0012
|
||
|
GET_INFO_CMD = 0x0005
|
||
|
|
||
|
|
||
|
class XUsbCom:
|
||
|
|
||
|
def __init__(self, _dev):
|
||
|
self.dev = _dev
|
||
|
self.write_addr = 0x1
|
||
|
self.read_addr = 0x81
|
||
|
self.attach = False
|
||
|
self.id = 0
|
||
|
self.info = b''
|
||
|
|
||
|
def write(self, data) -> None:
|
||
|
try:
|
||
|
# Vendor command set transfer length
|
||
|
self.dev.ctrl_transfer(0x40, 0xA0, wValue=XFER_LEN_CMD, wIndex=len(data), data_or_wLength='')
|
||
|
# Actual data
|
||
|
self.dev.write(self.write_addr, data, timeout=1000)
|
||
|
except usb.core.USBError as err:
|
||
|
sys.exit(err)
|
||
|
|
||
|
def read(self, size) -> bytes:
|
||
|
try:
|
||
|
buf = self.dev.read(self.read_addr, size, timeout=1000)
|
||
|
except usb.core.USBError as err:
|
||
|
sys.exit(err)
|
||
|
return buf
|
||
|
|
||
|
def set_media(self, media) -> None:
|
||
|
try:
|
||
|
# Vendor command set type
|
||
|
self.dev.ctrl_transfer(0x40, 0xB0, wValue=media, wIndex=0, data_or_wLength='')
|
||
|
except usb.core.USBError as err:
|
||
|
sys.exit(err)
|
||
|
return
|
||
|
|
||
|
def get_info(self, data) -> bytes:
|
||
|
try:
|
||
|
self.dev.ctrl_transfer(0x40, 0xB0, wValue=GET_INFO_CMD, wIndex=0, data_or_wLength='')
|
||
|
self.dev.ctrl_transfer(0x40, 0xA0, wValue=XFER_LEN_CMD, wIndex=76, data_or_wLength='')
|
||
|
self.dev.write(0x01, data, timeout=1000)
|
||
|
self.info = self.dev.read(0x81, 76, timeout=1000)
|
||
|
# not used
|
||
|
self.dev.read(0x81, 4, timeout=5000)
|
||
|
|
||
|
except usb.core.USBError as err:
|
||
|
sys.exit(err)
|
||
|
return self.info
|
||
|
|
||
|
def set_id(self, i) -> None:
|
||
|
self.id = i
|
||
|
|
||
|
def get_id(self) -> int:
|
||
|
return self.id
|
||
|
|
||
|
@staticmethod
|
||
|
def set_align(nand, spinand) -> None:
|
||
|
# See if we need to overwrite existing json file.
|
||
|
overwrite = False
|
||
|
try:
|
||
|
with open(".config", "r") as json_file:
|
||
|
cfg = json.load(json_file)
|
||
|
for key in cfg.keys():
|
||
|
if key == 'nand_align':
|
||
|
if nand != int(cfg['nand_align']):
|
||
|
overwrite = True
|
||
|
elif key == 'spinand_align':
|
||
|
if spinand != int(cfg['spinand_align']):
|
||
|
overwrite = True
|
||
|
except (IOError, OSError, json.decoder.JSONDecodeError) as err:
|
||
|
overwrite = True
|
||
|
|
||
|
if overwrite is True:
|
||
|
try:
|
||
|
with open(".config", "w+") as json_file:
|
||
|
new_key = {'nand_align': nand, 'spinand_align': spinand}
|
||
|
json.dump(new_key, json_file)
|
||
|
except (IOError, OSError) as err:
|
||
|
print("Write .config failed. Please re-attach")
|
||
|
sys.exit(err)
|
||
|
|
||
|
@staticmethod
|
||
|
def get_align() -> typing.Tuple[int, int]:
|
||
|
try:
|
||
|
with open(".config", "r") as json_file:
|
||
|
cfg = json.load(json_file)
|
||
|
except (IOError, OSError, json.decoder.JSONDecodeError) as err:
|
||
|
print("Open/parsing .config failed. Please re-attach")
|
||
|
sys.exit(err)
|
||
|
nand_align = spinand_align = 0
|
||
|
for key in cfg.keys():
|
||
|
if key == 'nand_align':
|
||
|
nand_align = int(cfg['nand_align'])
|
||
|
elif key == 'spinand_align':
|
||
|
spinand_align = int(cfg['spinand_align'])
|
||
|
return nand_align, spinand_align
|
||
|
|
||
|
|
||
|
class XUsbComList:
|
||
|
|
||
|
def __init__(self, attach_all=False):
|
||
|
vid = 0x0416
|
||
|
pid = 0x5963
|
||
|
try:
|
||
|
self.devices = list(usb.core.find(idVendor=vid, idProduct=pid,
|
||
|
find_all=True if attach_all is True else False))
|
||
|
except TypeError:
|
||
|
# list will raise exception if there's no device
|
||
|
self.devices = []
|
||
|
return
|
||
|
except usb.core.NoBackendError as err:
|
||
|
sys.exit(err)
|
||
|
|
||
|
if len(self.devices) != 0 and attach_all is False:
|
||
|
# Object type return on attach_all == False is different
|
||
|
self.devices[0] = self.devices[0].device
|
||
|
|
||
|
for dev in self.devices:
|
||
|
try:
|
||
|
dev.set_configuration()
|
||
|
except (usb.core.USBError, NotImplementedError) as err:
|
||
|
sys.exit(err)
|
||
|
|
||
|
for i in range(0, len(self.devices)):
|
||
|
self.devices[i] = XUsbCom(self.devices[i])
|
||
|
self.devices[i].set_id(i)
|
||
|
|
||
|
def __del__(self):
|
||
|
if len(self.devices) != 0:
|
||
|
for dev in self.devices:
|
||
|
try:
|
||
|
usb.util.dispose_resources(dev.dev)
|
||
|
# dev.dev.reset()
|
||
|
dev = None
|
||
|
#except (usb.core.USBError, NotImplementedError) as err:
|
||
|
except usb.core.USBError as err:
|
||
|
sys.exit(err)
|
||
|
|
||
|
self.devices = None
|
||
|
|
||
|
def get_dev(self):
|
||
|
return self.devices
|