1
0
mirror of https://github.com/AG7GN/nexus-utilities.git synced 2025-05-15 22:20:09 -07:00

Improved error handling & reporting

This commit is contained in:
Steve Magnuson 2021-01-01 13:32:56 -08:00
parent 61026979fb
commit 1b2f0d5e47

View File

@ -12,7 +12,7 @@ __author__ = "Steve Magnuson AG7GN"
__copyright__ = "Copyright 2020, Steve Magnuson" __copyright__ = "Copyright 2020, Steve Magnuson"
__credits__ = ["Steve Magnuson"] __credits__ = ["Steve Magnuson"]
__license__ = "GPL" __license__ = "GPL"
__version__ = "1.0.2" __version__ = "1.0.3"
__maintainer__ = "Steve Magnuson" __maintainer__ = "Steve Magnuson"
__email__ = "ag7gn@arrl.net" __email__ = "ag7gn@arrl.net"
__status__ = "Production" __status__ = "Production"
@ -28,7 +28,8 @@ class UsbWindow(object):
label_font = (None, 11, 'bold') label_font = (None, 11, 'bold')
button_font = (None, 12, 'bold') button_font = (None, 12, 'bold')
max_label_width = 350 max_label_width = 350
min_window_width = max_label_width + 35 window_padding = 35
min_window_width = max_label_width + window_padding
max_window_height = 380 max_window_height = 380
def __init__(self, master): def __init__(self, master):
@ -44,7 +45,8 @@ class UsbWindow(object):
self.header = ["ID", "Tag", "Device", "State"] self.header = ["ID", "Tag", "Device", "State"]
self.label_frame = tk.Frame(master=master, borderwidth=5) self.label_frame = tk.Frame(master=master, borderwidth=5)
self.label_frame.pack(side='top', fill='both', padx=5, pady=5, expand=True) self.label_frame.pack(side='top', fill='both', padx=5, pady=5, expand=True)
s = """Click on a USB device to toggle enable/disable state. s = """Click on a device to toggle state.
Empty list means no devices found.
(Enabled = bound, Disabled = unbound)""" (Enabled = bound, Disabled = unbound)"""
msg = tk.Label(master=self.label_frame, msg = tk.Label(master=self.label_frame,
wraplength=self.max_label_width, wraplength=self.max_label_width,
@ -149,7 +151,8 @@ class UsbWindow(object):
self.master.update() self.master.update()
x = self.master.winfo_width() x = self.master.winfo_width()
y = self.master.winfo_height() y = self.master.winfo_height()
window_width = max([tree_width + 35, self.min_window_width]) window_width = max([tree_width + self.window_padding,
self.min_window_width])
if x != window_width: if x != window_width:
self.master.geometry(f"{window_width}x{y}") self.master.geometry(f"{window_width}x{y}")
@ -217,26 +220,42 @@ def get_usb_devices() -> list:
device_re = re.compile("Bus\\s+(?P<bus>\\d+)\\s+" device_re = re.compile("Bus\\s+(?P<bus>\\d+)\\s+"
"Device\\s+(?P<device>\\d+).+" "Device\\s+(?P<device>\\d+).+"
"ID\\s(?P<id>\\w+:\\w+)\\s(?P<tag>.+)$", re.I) "ID\\s(?P<id>\\w+:\\w+)\\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb").decode('utf-8')
devices = [] devices = []
try:
df = subprocess.check_output("lsusb").decode('utf-8')
except subprocess.CalledProcessError as e:
print(f"ERROR: {e}", file=sys.stderr)
return devices
for i in df.split('\n'): for i in df.split('\n'):
hub = True # Assume device is a hub
if i: if i:
info = device_re.match(i) info = device_re.match(i)
if info: if info:
dinfo = info.groupdict() dinfo = info.groupdict()
if " hub" not in dinfo['tag'].casefold(): _bus = dinfo.pop('bus')
_bus = dinfo.pop('bus') _device = dinfo.pop('device')
_device = dinfo.pop('device') # See if the device is a hub. Ignore it if it is
cmd = f"grep -l {_bus}/{_device} /sys/bus/usb/devices/*/uevent 2>/dev/null | tail -1" cmd = f"sudo lsusb -D /dev/bus/usb/{_bus}/{_device} 2>/dev/null | grep -qi 'bDeviceClass.*Hub'"
try:
subprocess.check_output(cmd, shell=True).decode('utf-8')
except subprocess.CalledProcessError:
hub = False # Did not find 'Hub' in 'nDeviceClass'
if hub: # Device is a hub, so skip it.
continue
cmd = f"grep -l {_bus}/{_device} /sys/bus/usb/devices/*/uevent 2>/dev/null | tail -1"
try:
product = subprocess.check_output(cmd, shell=True).decode('utf-8') product = subprocess.check_output(cmd, shell=True).decode('utf-8')
if product: except subprocess.CalledProcessError as e:
_p = product.split('/')[5] print(f"ERROR: {e}", file=sys.stderr)
if os.path.islink(f"/sys/bus/usb/drivers/usb/{_p}"): continue
status = "Enabled" if product:
else: _p = product.split('/')[5]
status = 'Disabled' if os.path.islink(f"/sys/bus/usb/drivers/usb/{_p}"):
devices.append((dinfo['id'], dinfo['tag'], status = "Enabled"
_p, status)) else:
status = 'Disabled'
devices.append((dinfo['id'], dinfo['tag'],
_p, status))
return devices return devices
@ -274,7 +293,7 @@ def find_usb_device(_device_string: str, _action: str) -> bool:
devices = get_usb_devices() devices = get_usb_devices()
if devices: if devices:
for d in devices: for d in devices:
if _device_string in d[0] or \ if _device_string.casefold() in d[0].casefold() or \
_device_string.casefold() in d[1].casefold(): _device_string.casefold() in d[1].casefold():
if (_action == "bind" and d[3] == "Enabled") or \ if (_action == "bind" and d[3] == "Enabled") or \
(_action == "unbind" and d[3] == "Disabled"): (_action == "unbind" and d[3] == "Disabled"):
@ -301,7 +320,7 @@ if __name__ == "__main__":
parser.add_argument('-v', '--version', action='version', parser.add_argument('-v', '--version', action='version',
version=f"Version: {__version__}") version=f"Version: {__version__}")
parser.add_argument("-l", "--list", action='store_true', parser.add_argument("-l", "--list", action='store_true',
help="List available USB devices") help="list available non-hub USB devices")
parser.add_argument("-b", "--bind", parser.add_argument("-b", "--bind",
type=str, metavar="STRING", type=str, metavar="STRING",
help="bind (enable) a usb device containing " help="bind (enable) a usb device containing "
@ -314,7 +333,7 @@ if __name__ == "__main__":
"output ID or Tag fields") "output ID or Tag fields")
arg_info = parser.parse_args() arg_info = parser.parse_args()
if not sys.platform.startswith('linux'): if not sys.platform.startswith('linux'):
print(f"This application only works on Linux", file=sys.stderr) print(f"ERROR: This application only works on Linux", file=sys.stderr)
sys.exit(1) sys.exit(1)
if arg_info.list: if arg_info.list:
dev_list = get_usb_devices() dev_list = get_usb_devices()
@ -322,7 +341,7 @@ if __name__ == "__main__":
try: try:
from tabulate import tabulate from tabulate import tabulate
except ModuleNotFoundError: except ModuleNotFoundError:
print("Python 'tabulate' module required. Run 'sudo " print("ERROR: Python3 'tabulate' module required. Run 'sudo "
"apt update && sudo apt install python3-tabulate' " "apt update && sudo apt install python3-tabulate' "
"to install it.", file=sys.stderr) "to install it.", file=sys.stderr)
sys.exit(1) sys.exit(1)
@ -330,7 +349,7 @@ if __name__ == "__main__":
print(tabulate(dev_list, headers=["ID", "Tag", "Device", "State"])) print(tabulate(dev_list, headers=["ID", "Tag", "Device", "State"]))
sys.exit(0) sys.exit(0)
else: else:
print("No USB devices found", file=sys.stderr) print("No non-hub USB devices found", file=sys.stderr)
sys.exit(0) sys.exit(0)
if arg_info.bind: if arg_info.bind:
answer = find_usb_device(arg_info.bind, "bind") answer = find_usb_device(arg_info.bind, "bind")