From a7bdd08c44aa9ef48e1efbebe0c182d88823bffb Mon Sep 17 00:00:00 2001 From: MattHag <16444067+MattHag@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:03:20 +0100 Subject: [PATCH] macOS: Add support for Bluetooth devices Use hidapi on macOS to communicate and configure Logitech peripherals connected via Bluetooth. This brings macOS device support on the same level as Linux. However, some rules might not be supported yet on macOS. Tested with MX Keys and MX Master 3S. Fixes #2729 --- lib/hidapi/hidapi_impl.py | 30 ++++++++++++++---------------- lib/logitech_receiver/diversion.py | 2 +- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/hidapi/hidapi_impl.py b/lib/hidapi/hidapi_impl.py index 09bb3ab182..2b55974f96 100644 --- a/lib/hidapi/hidapi_impl.py +++ b/lib/hidapi/hidapi_impl.py @@ -181,15 +181,8 @@ def _enumerate_devices(): p = p.contents.next _hidapi.hid_free_enumeration(c_devices) - keyboard_or_mouse = {d["path"] for d in devices if d["usage_page"] == 1 and d["usage"] in (6, 2)} unique_devices = {} for device in devices: - # On macOS we cannot access keyboard or mouse devices without special permissions. Since - # we don't need them anyway we remove them so opening them doesn't cause errors later. - if device["path"] in keyboard_or_mouse: - # print(f"Ignoring keyboard or mouse device: {device}") - continue - # hidapi returns separate entries for each usage page of a device. # Deduplicate by path to only keep one device entry. if device["path"] not in unique_devices: @@ -255,15 +248,20 @@ def _match( device_handle = None try: device_handle = open_path(device["path"]) - report = _get_input_report(device_handle, 0x10, 32) - if len(report) == 1 + 6 and report[0] == 0x10: - device["hidpp_short"] = True - report = _get_input_report(device_handle, 0x11, 32) - if len(report) == 1 + 19 and report[0] == 0x11: - device["hidpp_long"] = True - except HIDError as e: # noqa: F841 - if logger.isEnabledFor(logging.INFO): - logger.info(f"Error opening device {device['path']} ({bus_id}/{vid:04X}/{pid:04X}) for hidpp check: {e}") # noqa + try: + report = _get_input_report(device_handle, 0x10, 32) + if len(report) == 1 + 6 and report[0] == 0x10: + device["hidpp_short"] = True + except HIDError as e: + if logger.isEnabledFor(logging.INFO): + logger.info(f"Error opening device {device['path']} ({bus_id}/{vid:04X}/{pid:04X}) for hidpp check: {e}") + try: + report = _get_input_report(device_handle, 0x11, 32) + if len(report) == 1 + 19 and report[0] == 0x11: + device["hidpp_long"] = True + except HIDError as e: + if logger.isEnabledFor(logging.INFO): + logger.info(f"Error opening device {device['path']} ({bus_id}/{vid:04X}/{pid:04X}) for hidpp check: {e}") finally: if device_handle: close(device_handle) diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py index 9ad6ccd8d4..bc71bd0285 100644 --- a/lib/logitech_receiver/diversion.py +++ b/lib/logitech_receiver/diversion.py @@ -364,7 +364,7 @@ def simulate_uinput(what, code, arg): def simulate_key(code, event): # X11 keycode but Solaar event code if not wayland and simulate_xtest(code, event): return True - if simulate_uinput(evdev.ecodes.EV_KEY, code - 8, event): + if evdev and simulate_uinput(evdev.ecodes.EV_KEY, code - 8, event): return True logger.warning("no way to simulate key input")