Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Karabiner causes my app's IOKit call to fail with kIOReturnExclusiveAccess #2560

Open
chrispaynter opened this issue Dec 27, 2020 · 5 comments

Comments

@chrispaynter
Copy link

I'm building a MacOS app using IOKit.

I'm encountering an issue where if Karabiner is running before I run my app, opening a HIDManager fails with kIOReturnExclusiveAccess.

This is a snippet of where this is occurring.

let noreturn = IOHIDManagerOpen(manager, IOOptionBits(kIOHIDOptionsTypeNone));
if(noreturn == kIOReturnExclusiveAccess) {
   print("FAILED");
}

Something similar was mentioned here - #1038

If I close Karabiner and run my app, the HIDManager opens successfully. I can then reopen karabiner and both apps function as normal.

I don't yet understand why this might be. Any ideas if it's me or you?

I could guide my users to close karabiner, and then reopen once my app connects, but would obviously rather fix the root issue.

@chrispaynter
Copy link
Author

@tekezo
Copy link
Member

tekezo commented Dec 28, 2020

Karabiner-Elements open IOHIDDevice with kIOHIDOptionsTypeSeizeDevice in order to avoid hidd receives unmodified input events.
It causes kIOReturnExclusiveAccess if other apps will open the devices.

If your app is not related with specific hardware, you can open the virtual device (org_pqrs_Karabiner_DriverKit_VirtualHIDKeyboard) which Karabiner users to sends events.

But, if your app needs to communicate with the specific hardware such LED adjustment, writing firmware, the conflict is a headache.
If your app receives IOKit device matched notification and open the device immediately, increasing the wait before Karabiner-Elements open the device might help.

Screen Shot 2020-12-28 at 21 35 02

@tekezo
Copy link
Member

tekezo commented Dec 28, 2020

@chrispaynter
Copy link
Author

chrispaynter commented Dec 28, 2020

Thanks for the information @tekezo, I'll read through this a bit to try and understand. I unfortunately need to communicate with the device directly, however it's a plausible use case that the user is running Karabiner simultaneously.

I have a couple extra questions if you'd be kind enough to answer.

  1. Considering the fact that Karabiner seizes the devices, does this mean there's not really anything I can do for these users (other than the suggested timeouts)?
  2. Considering that opening Karabiner after my app solves the issues (albeit manually), is this an adequate work around or are there caveats I'm not seeing? Perhaps, for instance, Karabiner seizing access again at some point whilst they are both running?

@kambala-decapitator
Copy link
Contributor

kambala-decapitator commented Mar 20, 2024

if your app that wants to listen to HID events is meant to be run at login, then you can use the following kinda dumb workaround: disable Karabiner launch at login and in your app do

IOHIDManagerOpen() // should succeed
// run Karabiner after a small delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    NSWorkspace.shared.openApplication(at: .init(fileURLWithPath: "/Applications/Karabiner-Elements.app"), configuration: .init())
}
  1. Considering that opening Karabiner after my app solves the issues (albeit manually), is this an adequate work around or are there caveats I'm not seeing? Perhaps, for instance, Karabiner seizing access again at some point whilst they are both running?

so basically this. From my limited tests everything seems to work fine.

But the proper way to use Karabiner device is:

IOHIDManagerSetDeviceMatching(HIDManager, IOServiceNameMatching("org_pqrs_Karabiner_DriverKit_VirtualHIDKeyboard"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants