Skip to content

Commit

Permalink
macOS: Add support for Bluetooth devices
Browse files Browse the repository at this point in the history
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
  • Loading branch information
MattHag committed Jan 1, 2025
1 parent 96364d2 commit a7bdd08
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 17 deletions.
30 changes: 14 additions & 16 deletions lib/hidapi/hidapi_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion lib/logitech_receiver/diversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down

0 comments on commit a7bdd08

Please sign in to comment.