From a945f6cf4348b7cb83ad1896aaf7ccd7ca8afb92 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Thu, 3 Oct 2024 09:17:39 +0100 Subject: [PATCH] Avoid taking an exclusive lock on Litra devices on macOS Currently, when a Litra handle device is opened with `open()`, on macOS we take an exclusive lock on the device, which stops it being managed by other applications. This isn't a problem if the device handle is quickly closed again (e.g. if the application exits), but it can be annoying if you have a long-running application that holds onto the device handle for a long time (e.g. `litra auto-toggle`). As an example, if you run `litra auto-toggle` and then try to turn the device on or off with `litra on` or `litra off` in another shell, it would fail with an error: > HID error occurred: hidapi error: hid_open_path: failed to open IOHIDDevice from mach entry: (0xE00002C5) (iokit/common) exclusive access and device already open This switches to taking a non-exclusive lock on macOS, affecting use of this code as a Rust library and our long-running `auto-toggle` command. --- src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 63c3652..c98d701 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,10 @@ impl fmt::Debug for Litra { impl Litra { /// Initialize a new Litra context. pub fn new() -> DeviceResult { - Ok(HidApi::new().map(Litra)?) + let hidapi = HidApi::new()?; + #[cfg(target_os = "macos")] + hidapi.set_open_exclusive(false); + Ok(Litra(hidapi)) } /// Returns an [`Iterator`] of connected devices supported by this library. @@ -177,7 +180,7 @@ impl Device<'_> { } /// Opens the device and returns a [`DeviceHandle`] that can be used for getting and setting the - /// device status. + /// device status. On macOS, this will open the device in non-exclusive mode. pub fn open(&self, context: &Litra) -> DeviceResult { let hid_device = self.device_info.open_device(context.hidapi())?; Ok(DeviceHandle {