From ca10d70ec7d80b0e5dbcff2139335ad7075a4725 Mon Sep 17 00:00:00 2001 From: sillymotives Date: Mon, 14 Sep 2026 18:17:53 +0100 Subject: [PATCH] Reacquire USB device on resume --- dbus_service/dbus-service | 4 +-- validitysensor/init.py | 5 ++++ validitysensor/usb.py | 54 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/dbus_service/dbus-service b/dbus_service/dbus-service index 1c63e8d..0ad6e2e 100755 --- a/dbus_service/dbus-service +++ b/dbus_service/dbus-service @@ -73,9 +73,9 @@ class Device(dbus.service.Object): logging.debug('In Resume') tls.reset() try: - init.open_common() + init.reopen() except: - init.open_common() + init.reopen() @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature="s", out_signature="as") def ListEnrolledFingers(self, user): diff --git a/validitysensor/init.py b/validitysensor/init.py index 1153cf7..4194ca7 100644 --- a/validitysensor/init.py +++ b/validitysensor/init.py @@ -53,3 +53,8 @@ def open(): def open_devpath(busnum: int, address: int): usb.open_devpath(busnum, address) open_common() + + +def reopen(): + usb.reopen() + open_common() diff --git a/validitysensor/usb.py b/validitysensor/usb.py index 464b092..bdeb4ee 100644 --- a/validitysensor/usb.py +++ b/validitysensor/usb.py @@ -36,8 +36,26 @@ def __init__(self): self.trace_enabled = False self.dev: typing.Optional[ucore.Device] = None self.cancel = False + self.identity = None + self.reopen_strict = False + + @staticmethod + def device_identity(dev: ucore.Device): + try: + bus = dev.bus + except Exception: + bus = None + + try: + ports = tuple(dev.port_numbers or ()) + except Exception: + ports = () + + return dev.idVendor, dev.idProduct, bus, ports def open(self, vendor=None, product=None): + self.reopen_strict = False + if vendor is not None and product is not None: dev = ucore.find(idVendor=vendor, idProduct=product) else: @@ -50,6 +68,8 @@ def match(d): self.open_dev(dev) def open_devpath(self, busnum: int, address: int): + self.reopen_strict = True + def match(d): return d.bus == busnum and d.address == address @@ -57,11 +77,45 @@ def match(d): self.open_dev(dev) + def reopen(self): + if self.identity is None: + if self.reopen_strict: + raise Exception('Cannot safely reopen explicitly selected device without USB identity') + self.open() + return + + vendor, product, bus, ports = self.identity + + if bus is not None and ports: + def match(d): + if d.idVendor != vendor or d.idProduct != product: + return False + if d.bus != bus: + return False + try: + return tuple(d.port_numbers or ()) == ports + except Exception: + return False + + dev = ucore.find(custom_match=match) + + if dev is None: + raise Exception('Previously opened fingerprint device not found at the same USB topology') + + self.open_dev(dev) + return + + if self.reopen_strict: + raise Exception('Cannot safely reopen explicitly selected device without USB topology') + + self.open(vendor, product) + def open_dev(self, dev: ucore.Device): if dev is None: raise Exception('No matching devices found') self.dev = dev + self.identity = self.device_identity(dev) self.dev.default_timeout = 15000 dev.set_configuration()