# SPDX-License-Identifier: GPL-2.0-or-later import datetime import struct import time import threading from PyQt5.QtCore import pyqtSignal from PyQt5.QtGui import QFontDatabase from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QLineEdit, QToolButton, QPlainTextEdit, QProgressBar,\ QFileDialog, QDialog from util import tr, chunks from vial_device import VialBootloader def send_retries(dev, data, retries=20): """ Sends usb packet up to 'retries' times, returns True if success, False if failed """ for x in range(retries): ret = dev.send(data) if ret == len(data) + 1: return True elif ret < 0: time.sleep(0.1) else: return False return False CHUNK = 64 def cmd_flash(device, firmware, log): # Check bootloader is correct version device.send(b"VC\x00") data = device.recv(8) log("* Bootloader version: {}".format(data[0])) if data[0] != 0: log("Error: Unsupported bootloader version") return # TODO: Check vial ID against firmware package device.send(b"VC\x01") data = device.recv(8) log("* Vial ID: {}".format(data.hex())) # Flash firmware_size = len(firmware) if firmware_size % CHUNK != 0: firmware_size += CHUNK - firmware_size % CHUNK log(device.send(b"VC\x02" + struct.pack(" 10 * 1024 * 1024: self.log("Error: Firmware is too large. Check you've selected the correct file") return self.log("Preparing to flash...") threading.Thread(target=lambda: cmd_flash(self.device, firmware, self.on_log)).start() def on_log(self, line): self.log_signal.emit(line) def _on_log(self, line): self.log(line) def log(self, line): self.txt_logger.appendPlainText("[{}] {}".format(datetime.datetime.now(), line))