import logging from os.path import basename from time import ctime import typing from .flash import write_flash_all, write_fw_signature, get_fw_info from .sensor import reboot, write_hw_reg32, read_hw_reg32, identify_sensor from .usb import usb firmware_home = '/usr/share/python-validity' def default_fwext_name(): if usb.usb_dev().idVendor == 0x138a: if usb.usb_dev().idProduct == 0x0090: return '6_07f_Lenovo.xpfwext' # It looks like the firmware file must match DLL, not the hardware. # Both DLL and xpfwext are universal. # The device dependant code seems to be loaded dynamically (via encrypted blobs). # So, it is important that xpfwext file is matching the blobs contents. return '6_07f_lenovo_mis_qm.xpfwext' def upload_fwext(fw_path: typing.Optional[str]=None): fwi = get_fw_info(2) if fwi is not None: logging.info('Detected firmware version %d.%d (%s))' % (fwi.major, fwi.minor, ctime(fwi.buildtime))) return else: logging.info('No firmware detected. Uploading...') # no idea what this is: write_hw_reg32(0x8000205c, 7) if read_hw_reg32(0x80002080) not in [2, 3]: raise Exception('Unexpected register value') dev = identify_sensor() logging.debug('Sensor: %s' % dev.name) # ^ TODO -- what is the real reason to detect HW at this stage? # just a guess: perhaps it is used to construct fwext filename default_name = firmware_home + '/' + default_fwext_name() if not fw_path: fw_path = default_name elif basename(fw_path) != default_name: logging.warning('WARNING: Your device fw is supposed to be called {}'.format(default_name)) with open(fw_path, 'rb') as f: fwext = f.read() fwext = fwext[fwext.index(b'\x1a') + 1:] fwext, signature = fwext[:-0x100], fwext[-0x100:] write_flash_all(2, 0, fwext) write_fw_signature(2, signature) fwi = get_fw_info(2) if fwi is None: raise Exception('No firmware detected') logging.info('Loaded FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules))) # Reboot reboot() raise Exception('Reboot')