修改关联文件,双击打开安装崩溃。
This commit is contained in:
parent
995e01e759
commit
9df31a7b37
197
src/pydfu.py
197
src/pydfu.py
@ -16,6 +16,8 @@ from __future__ import print_function
|
|||||||
import argparse
|
import argparse
|
||||||
import collections
|
import collections
|
||||||
import inspect
|
import inspect
|
||||||
|
import json
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
@ -24,6 +26,17 @@ import zlib
|
|||||||
|
|
||||||
import usb.core
|
import usb.core
|
||||||
import usb.util
|
import usb.util
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import usb.backend.libusb1 as libusb1
|
||||||
|
import usb.backend.libusb0 as libusb0
|
||||||
|
import usb.backend.openusb as openusb
|
||||||
|
|
||||||
|
from usb.libloader import *
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
# USB request __TIMEOUT
|
# USB request __TIMEOUT
|
||||||
__TIMEOUT = 4000
|
__TIMEOUT = 4000
|
||||||
@ -116,11 +129,23 @@ def init(**kwargs):
|
|||||||
devices = get_dfu_devices(**kwargs)
|
devices = get_dfu_devices(**kwargs)
|
||||||
if not devices:
|
if not devices:
|
||||||
raise ValueError("No DFU device found")
|
raise ValueError("No DFU device found")
|
||||||
if len(devices) > 1:
|
# if len(devices) > 1:
|
||||||
raise ValueError("Multiple DFU devices found")
|
# raise ValueError("Multiple DFU devices found")
|
||||||
__dev = devices[0]
|
|
||||||
__dev.set_configuration()
|
|
||||||
|
|
||||||
|
for dev in devices:
|
||||||
|
try:
|
||||||
|
__dev = dev
|
||||||
|
dev.set_configuration()
|
||||||
|
break
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# __dev = devices[1]
|
||||||
|
# print("__dev", __dev)
|
||||||
|
# __dev.set_configuration()
|
||||||
|
# __dev.get_active_configuration()
|
||||||
|
# print("__dev.set_configuration", __dev)
|
||||||
# Claim DFU interface
|
# Claim DFU interface
|
||||||
usb.util.claim_interface(__dev, __DFU_INTERFACE)
|
usb.util.claim_interface(__dev, __DFU_INTERFACE)
|
||||||
|
|
||||||
@ -437,14 +462,99 @@ class FilterDFU(object):
|
|||||||
return intf.bInterfaceClass == 0xFE and intf.bInterfaceSubClass == 1
|
return intf.bInterfaceClass == 0xFE and intf.bInterfaceSubClass == 1
|
||||||
|
|
||||||
|
|
||||||
|
def _load_locate_library_ex(candidates, cygwin_lib, name,
|
||||||
|
win_cls=None, cygwin_cls=None, others_cls=None,
|
||||||
|
find_library=None):
|
||||||
|
"""Locates and loads a library.
|
||||||
|
Returns: the loaded library
|
||||||
|
arguments:
|
||||||
|
* candidates -- candidates list for locate_library()
|
||||||
|
* cygwin_lib -- name of the cygwin library
|
||||||
|
* name -- lib identifier (for logging). Defaults to None.
|
||||||
|
* win_cls -- class that is used to instantiate the library on
|
||||||
|
win32 platforms. Defaults to None (-> ctypes.CDLL).
|
||||||
|
* cygwin_cls -- library class for cygwin platforms.
|
||||||
|
Defaults to None (-> ctypes.CDLL).
|
||||||
|
* others_cls -- library class for all other platforms.
|
||||||
|
Defaults to None (-> ctypes.CDLL).
|
||||||
|
* find_library -- see locate_library(). Defaults to None.
|
||||||
|
raises:
|
||||||
|
* NoLibraryCandidatesException
|
||||||
|
* LibraryNotFoundException
|
||||||
|
* LibraryNotLoadedException
|
||||||
|
* LibraryMissingSymbolsException
|
||||||
|
"""
|
||||||
|
if sys.platform == 'cygwin':
|
||||||
|
if cygwin_lib:
|
||||||
|
loaded_lib = load_library(cygwin_lib, name, cygwin_cls)
|
||||||
|
else:
|
||||||
|
raise NoLibraryCandidatesException(name)
|
||||||
|
elif candidates:
|
||||||
|
lib = locate_library(candidates, find_library)
|
||||||
|
if lib:
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
loaded_lib = load_library(lib, name, win_cls)
|
||||||
|
else:
|
||||||
|
loaded_lib = load_library(lib, name, others_cls)
|
||||||
|
_LOGGER.info('{}'.format(loaded_lib))
|
||||||
|
else:
|
||||||
|
_LOGGER.info('%r could not be found', (name or candidates))
|
||||||
|
raise LibraryNotFoundException(name)
|
||||||
|
else:
|
||||||
|
raise NoLibraryCandidatesException(name)
|
||||||
|
|
||||||
|
if loaded_lib is None:
|
||||||
|
raise LibraryNotLoadedException(name)
|
||||||
|
else:
|
||||||
|
return loaded_lib
|
||||||
|
|
||||||
|
|
||||||
|
def _load_library_ex(find_library=None):
|
||||||
|
return _load_locate_library_ex(
|
||||||
|
('usb-0.1', 'usb', 'libusb0'),
|
||||||
|
'cygusb0.dll', 'Libusb 0',
|
||||||
|
find_library=find_library
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_backend_ex():
|
||||||
|
try:
|
||||||
|
if libusb0._lib is None:
|
||||||
|
_LOGGER.info('_get_backend_ex(): using backend "%s"' % libusb0.__name__)
|
||||||
|
libusb0._lib = _load_library_ex()#find_library
|
||||||
|
libusb0._setup_prototypes(libusb0._lib)
|
||||||
|
libusb0._lib.usb_init()
|
||||||
|
return libusb0._LibUSB()
|
||||||
|
except usb.libloader.LibraryException:
|
||||||
|
# exception already logged (if any)
|
||||||
|
_LOGGER.error('Error loading libusb 0.1 backend')
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
_LOGGER.error('Error loading libusb 0.1 backend')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def my_get_backend_ex():
|
||||||
|
for m in (libusb1, openusb, libusb0):
|
||||||
|
backend = m.get_backend()
|
||||||
|
if backend is not None:
|
||||||
|
_LOGGER.info('my_get_backend_ex(): using backend "%s"' % m.__name__)
|
||||||
|
break
|
||||||
|
elif m == libusb0:
|
||||||
|
backend = _get_backend_ex()
|
||||||
|
if backend is not None: break
|
||||||
|
else:
|
||||||
|
raise ('No backend available')
|
||||||
|
|
||||||
|
return backend
|
||||||
|
|
||||||
def get_dfu_devices(*args, **kwargs):
|
def get_dfu_devices(*args, **kwargs):
|
||||||
"""Returns a list of USB devices which are currently in DFU mode.
|
"""Returns a list of USB devices which are currently in DFU mode.
|
||||||
Additional filters (like idProduct and idVendor) can be passed in
|
Additional filters (like idProduct and idVendor) can be passed in
|
||||||
to refine the search.
|
to refine the search.
|
||||||
"""
|
"""
|
||||||
|
backend = my_get_backend_ex()
|
||||||
# Convert to list for compatibility with newer PyUSB
|
# Convert to list for compatibility with newer PyUSB
|
||||||
return list(usb.core.find(*args, find_all=True, custom_match=FilterDFU(), **kwargs))
|
return list(usb.core.find(*args, find_all=True, backend=backend, custom_match=FilterDFU(), **kwargs))
|
||||||
|
|
||||||
|
|
||||||
def get_memory_layout(device):
|
def get_memory_layout(device):
|
||||||
@ -568,12 +678,12 @@ def main():
|
|||||||
# Parse CMD args
|
# Parse CMD args
|
||||||
parser = argparse.ArgumentParser(description="DFU Python Util")
|
parser = argparse.ArgumentParser(description="DFU Python Util")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-l", "--list", help="list available DFU devices", action="store_true", default=False
|
"-l", "--list", help="list available DFU devices", action="store", default=False
|
||||||
)
|
)
|
||||||
# parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
|
# parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
|
||||||
# parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
|
# parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-m", "--mass-erase", help="mass erase device", action="store_true", default=False
|
"-m", "--mass-erase", help="mass erase device", action="store", default=False
|
||||||
)
|
)
|
||||||
# parser.add_argument(
|
# parser.add_argument(
|
||||||
# "-u", "--upload", help="read file from DFU device", dest="path", default=False
|
# "-u", "--upload", help="read file from DFU device", dest="path", default=False
|
||||||
@ -589,9 +699,9 @@ def main():
|
|||||||
default="C:\\Users\\User\\Downloads\\stm32loader-master\\max.dfu"
|
default="C:\\Users\\User\\Downloads\\stm32loader-master\\max.dfu"
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument("-x", "--exit", help="Exit DFU", action="store_true", default=False)
|
parser.add_argument("-x", "--exit", help="Exit DFU", action="store", default=False)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v", "--verbose", help="increase output verbosity", action="store_true", default=False
|
"-v", "--verbose", help="increase output verbosity", action="store", default=False
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -842,11 +952,17 @@ class STM32Dev(ispBase.IspBase, QSerialPort):
|
|||||||
|
|
||||||
|
|
||||||
class DFUTool(QThread):
|
class DFUTool(QThread):
|
||||||
print("DFUTool(QThread)")
|
|
||||||
stateCallback = pyqtSignal([str], [Exception])
|
stateCallback = pyqtSignal([str], [Exception])
|
||||||
|
|
||||||
progressCallback = pyqtSignal(int, int)
|
progressCallback = pyqtSignal(int, int)
|
||||||
|
|
||||||
|
def is_valid_file(self, parser, arg):
|
||||||
|
|
||||||
|
if not os.path.exists(arg):
|
||||||
|
parser.error("The file %s does not exist!" % arg)
|
||||||
|
else:
|
||||||
|
return open(arg, 'r') # return an open file handle
|
||||||
|
|
||||||
def __init__(self, parent, port, speed, filename, callback=None):
|
def __init__(self, parent, port, speed, filename, callback=None):
|
||||||
super(DFUTool, self).__init__()
|
super(DFUTool, self).__init__()
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
@ -856,65 +972,26 @@ class DFUTool(QThread):
|
|||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.isWork = False
|
self.isWork = False
|
||||||
self.finished.connect(self.done)
|
self.finished.connect(self.done)
|
||||||
print("__init__")
|
|
||||||
|
|
||||||
global __verbose
|
global __verbose
|
||||||
# Parse CMD args
|
|
||||||
parser = argparse.ArgumentParser(description="DFU Python Util")
|
|
||||||
parser.add_argument(
|
|
||||||
"-l", "--list", help="list available DFU devices", action="store_true", default=False
|
|
||||||
)
|
|
||||||
# parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
|
|
||||||
# parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
|
|
||||||
parser.add_argument(
|
|
||||||
"-m", "--mass-erase", help="mass erase device", action="store_true", default=False
|
|
||||||
)
|
|
||||||
# parser.add_argument(
|
|
||||||
# "-u", "--upload", help="read file from DFU device", dest="path", default=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=0x0483)
|
__verbose = False
|
||||||
parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=0xdf11)
|
|
||||||
# parser.add_argument(
|
|
||||||
# "-u", "--upload", help="read file from DFU device", dest="path", default="C:\\Users\\User\\Documents\\stm32-test\\board-STM32F103-Mini\\usbdfu.bin"
|
|
||||||
# )
|
|
||||||
parser.add_argument(
|
|
||||||
"-u", "--upload", help="read file from DFU device", dest="path",
|
|
||||||
default=self.filename
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument("-x", "--exit", help="Exit DFU", action="store_true", default=False)
|
kwargs = {"idVendor": 0x0483, "idProduct": 0xdf11}
|
||||||
parser.add_argument(
|
|
||||||
"-v", "--verbose", help="increase output verbosity", action="store_true", default=False
|
|
||||||
)
|
|
||||||
self.args = parser.parse_args()
|
|
||||||
|
|
||||||
__verbose = self.args.verbose
|
|
||||||
|
|
||||||
kwargs = {}
|
|
||||||
if self.args.vid:
|
|
||||||
kwargs["idVendor"] = self.args.vid
|
|
||||||
|
|
||||||
if self.args.pid:
|
|
||||||
kwargs["idProduct"] = self.args.pid
|
|
||||||
|
|
||||||
def w(state):
|
def w(state):
|
||||||
if state is False:
|
if state is False:
|
||||||
print("未找到DFU")
|
|
||||||
self.stateCallback[Exception].emit(portError(portError.errorOpen, port))
|
self.stateCallback[Exception].emit(portError(portError.errorOpen, port))
|
||||||
self.stateCallback[str].emit("Done!")
|
self.stateCallback[str].emit("Done!")
|
||||||
self.quit()
|
self.quit()
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print("找到DFU")
|
|
||||||
self.thread.exit()
|
self.thread.exit()
|
||||||
init(**kwargs)
|
init(**kwargs)
|
||||||
self.start()
|
self.start()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("----------------------------======================")
|
|
||||||
print(err)
|
print(err)
|
||||||
print(1)
|
|
||||||
|
|
||||||
self.thread = DFUSearch(self, kwargs=kwargs)
|
self.thread = DFUSearch(self, kwargs=kwargs)
|
||||||
self.thread.searchResults.connect(w) # 异步完成后执行函数w
|
self.thread.searchResults.connect(w) # 异步完成后执行函数w
|
||||||
@ -930,15 +1007,14 @@ class DFUTool(QThread):
|
|||||||
print("QMetaObject_Connection")
|
print("QMetaObject_Connection")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
print("run")
|
|
||||||
self.isWork = True
|
self.isWork = True
|
||||||
try:
|
try:
|
||||||
print("try")
|
|
||||||
with open(self.args.path, "rb") as fin:
|
with open(self.filename, "rb") as fin:
|
||||||
dfu_file = fin.read()
|
dfu_file = fin.read()
|
||||||
|
|
||||||
if dfu_file is None:
|
if dfu_file is None:
|
||||||
print("file is None")
|
|
||||||
return
|
return
|
||||||
elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file}
|
elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file}
|
||||||
|
|
||||||
@ -950,10 +1026,11 @@ class DFUTool(QThread):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
self.stateCallback[str].emit(self.tr("Programming..."))
|
self.stateCallback[str].emit(self.tr("Programming..."))
|
||||||
write_elements([elem], self.args.mass_erase, progress=self.cl_progress)
|
write_elements([elem], False, progress=self.cl_progress)
|
||||||
exit_dfu() # 退出DFU模式
|
exit_dfu() # 退出DFU模式
|
||||||
print("exit_dfu")
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
if self.isInterruptionRequested():
|
if self.isInterruptionRequested():
|
||||||
print("int")
|
print("int")
|
||||||
else:
|
else:
|
||||||
@ -971,7 +1048,7 @@ class DFUTool(QThread):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
print("结束烧录程序")
|
|
||||||
if self.parent is not None:
|
if self.parent is not None:
|
||||||
if self.isWork:
|
if self.isWork:
|
||||||
self.isWork = False
|
self.isWork = False
|
||||||
@ -1001,14 +1078,12 @@ class DFUSearch(QThread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# 耗时内容
|
# 耗时内容
|
||||||
print("self.kwargs", self.kwargs)
|
|
||||||
devices = get_dfu_devices(**self.kwargs)
|
devices = get_dfu_devices(**self.kwargs)
|
||||||
# Waiting 2 seconds before trying again..."
|
# Waiting 2 seconds before trying again..."
|
||||||
attempts = 0
|
attempts = 0
|
||||||
while not devices:
|
while not devices:
|
||||||
devices = get_dfu_devices(**self.kwargs)
|
devices = get_dfu_devices(**self.kwargs)
|
||||||
attempts += 1
|
attempts += 1
|
||||||
print("搜索DFU设备", attempts)
|
|
||||||
if attempts > 20:
|
if attempts > 20:
|
||||||
self.searchResults.emit(False)
|
self.searchResults.emit(False)
|
||||||
self.quit()
|
self.quit()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user