I am new to USB usage in my application on Mac. When I log the result of IOHIDManagerOpen(x,y) function call on my application I get error code -536870201. I have found in the following post (Keystrokes are not blocked when using kIOHIDOptionsTypeSeizeDevice and are still passed to the OS) that -536870207 is translated to kIOReturnNotPrivileged. How can I translate my error code and understand the cause of an error?
Code that I am running:
manager = std::make_unique<CoreFoundationReference<IOHIDManagerRef>>(
IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone));
IOHIDManagerSetDeviceMatching(manager->Get(), nullptr);
IOHIDManagerRegisterDeviceMatchingCallback(
manager->Get(), &MacHidDeviceManager::OnDeviceMatched, this);
IOHIDManagerRegisterDeviceRemovalCallback(
manager->Get(), &MacHidDeviceManager::OnDeviceRemoved, this);
IOHIDManagerScheduleWithRunLoop(
manager->Get(), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
auto ioResult = IOHIDManagerOpen(manager->Get(), kIOHIDOptionsTypeNone);
if (ioResult != kIOReturnSuccess) {
throw UsbInterfaceException("DeviceManager::DeviceManager", "Cannot open IO device manager, error: {}", ioResult);
}
For IOKit return values (IOReturn
) it's typically much more helpful to print them as hexadecimal, ("0x%x") as that's how the constants are defined in <IOKit/IOReturn.h>
.
So for example, -536870201 is represented in hexadecimal as 0xE00002C7
. The 0xE0000000
part means it's an IOKit constant, the last few digits of 2C7
identify it as kIOReturnUnsupported
.
You haven't posted any code or other details about the run-up or arguments to your IOHIDManagerOpen()
call, so I can't really say why it should return kIOReturnUnsupported
without more details.
Based on the code you added to your question, I tried to come up with the minimum reproducible sample:
#include <IOKit/hid/IOHIDManager.h>
struct MacHidDeviceManager
{
static void OnDeviceMatched(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {}
static void OnDeviceRemoved(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {}
void Start()
{
IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
IOHIDManagerSetDeviceMatching(manager, nullptr);
IOHIDManagerRegisterDeviceMatchingCallback(
manager, &MacHidDeviceManager::OnDeviceMatched, this);
IOHIDManagerRegisterDeviceRemovalCallback(
manager, &MacHidDeviceManager::OnDeviceRemoved, this);
IOHIDManagerScheduleWithRunLoop(
manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
auto ioResult = IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
if (ioResult != kIOReturnSuccess) {
fprintf(stderr, "MacHidDeviceManager -> 0x%x\n", ioResult);
}
}
};
int main()
{
MacHidDeviceManager m;
m.Start();
}
This initially fails (0xe00002e2
, kIOReturnNotPermitted
) due to missing consent from Security & Privacy, but succeeds once I've granted that permission in System Preferences. I've tested this on macOS 11 and 13 with the same result. I suspect some of the code you haven't posted (CoreFoundationReference
?) might be where the problem lies. Or perhaps some sandboxing issue?
Incidentally, I maintain a small library of IOKit helper utilities, and one of those things is a function djt_ioreturn_string
which converts IOReturn
values into string representations of those constants. (You just need to include the ioreturn_strings.cpp and ioreturn_strings.h files in your project, the ioreturn_strings.h can be #include
/#import
ed from pure C or Objective-C, just the .cpp uses C++.)