From fe55e39560ba493e21f94dfeedcaf38687a554ae Mon Sep 17 00:00:00 2001 From: effective-light Date: Tue, 11 Aug 2020 17:00:14 -0400 Subject: [PATCH] udev: use HID_PHYS instead of HID_UNIQ to look for relevant child nodes --- lib/hidapi/__init__.py | 1 + lib/hidapi/udev.py | 12 ++++++++++++ lib/logitech_receiver/device.py | 10 ++-------- lib/logitech_receiver/receiver.py | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/hidapi/__init__.py b/lib/hidapi/__init__.py index 8e55b436..4202b676 100644 --- a/lib/hidapi/__init__.py +++ b/lib/hidapi/__init__.py @@ -22,6 +22,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera from hidapi.udev import close # noqa: F401 from hidapi.udev import enumerate # noqa: F401 +from hidapi.udev import find_paired_node # noqa: F401 from hidapi.udev import get_manufacturer # noqa: F401 from hidapi.udev import get_product # noqa: F401 from hidapi.udev import get_serial # noqa: F401 diff --git a/lib/hidapi/udev.py b/lib/hidapi/udev.py index 1d8c86ed..cef9d6ea 100644 --- a/lib/hidapi/udev.py +++ b/lib/hidapi/udev.py @@ -48,6 +48,7 @@ DeviceInfo = namedtuple( 'vendor_id', 'product_id', 'serial', + 'phys', 'release', 'manufacturer', 'product', @@ -127,6 +128,7 @@ def _match(action, device, filter): path=device.device_node, vendor_id=vid[-4:], product_id=pid[-4:], + phys=hid_device.get('HID_PHYS'), serial=hid_device.get('HID_UNIQ'), release=attrs.get('bcdDevice'), manufacturer=attrs.get('manufacturer'), @@ -143,6 +145,7 @@ def _match(action, device, filter): path=device.device_node, vendor_id=vid[-4:], product_id=pid[-4:], + phys=None, serial=None, release=None, manufacturer=None, @@ -153,6 +156,15 @@ def _match(action, device, filter): return d_info +def find_paired_node(receiver_phys, index): + for dev in _Context().list_devices(subsystem='hidraw'): + phys = dev.find_parent('hid').get('HID_PHYS') + if phys and '{}:{}'.format(receiver_phys, index) == phys: + return dev.device_node + + return None + + def monitor_glib(callback, *device_filters): from gi.repository import GLib diff --git a/lib/logitech_receiver/device.py b/lib/logitech_receiver/device.py index 8abe76da..b1cd0d21 100644 --- a/lib/logitech_receiver/device.py +++ b/lib/logitech_receiver/device.py @@ -128,14 +128,8 @@ class Device(object): # device is unpaired assert self.wpid is not None, 'failed to read wpid: device %d of %s' % (number, receiver) - for dev in _hid.enumerate({'vendor_id': 0x046d, 'product_id': int(self.receiver.product_id, 16)}): - if dev.serial: - split = dev.serial.split('-') - hidraw_serial = ''.join(split[1:]).upper() - if self.serial == hidraw_serial and split[0] == self.wpid: - self.path = dev.path - self.handle = _hid.open_path(dev.path) - break + self.path = _hid.find_paired_node(receiver.phys, number) + self.handle = _hid.open_path(self.path) if self.path else None self.descriptor = _DESCRIPTORS.get(self.wpid) if self.descriptor is None: diff --git a/lib/logitech_receiver/receiver.py b/lib/logitech_receiver/receiver.py index 4db61af2..daa950ae 100644 --- a/lib/logitech_receiver/receiver.py +++ b/lib/logitech_receiver/receiver.py @@ -53,6 +53,7 @@ class Receiver(object): self.handle = handle assert device_info self.path = device_info.path + self.phys = device_info.phys # USB product id, used for some Nano receivers self.product_id = device_info.product_id product_info = _product_information(self.product_id)