IOCreatePlugInInterfaceForService returns mysterious error
Asked Answered
P

3

6

I am trying to use some old IOKit functionality in a new Swift 4.0 Mac app (not iOS). I have created a bridging header to use an existing Objective C third party framework, DDHidLib, and I am current working in Xcode 9.

The code that attempts to create a plug in interface for a usb gamepad falls over on IOCreatePlugInInterfaceForService, returning a non-zero error.

The truly bizarre thing is I have an older app created in a previous version of Xcode that uses the same framework and works correctly after opening in the new Xcode 9. This previous project is still Swift using a bridging header for the same Obj-C framework. I have checked the build settings and tried to make everything match, but I get the same result; the old app works but any new apps do not.

Is there a way to either: find out the exact differences in build settings/compilers to see what the elusive difference may be, OR to step into the IOCreatePlugInInterfaceForService IOKit method to see what may be causing the error to be returned in one project but not another?

EDIT: Here is the method that is failing:

- (BOOL) createDeviceInterfaceWithError: (NSError **) error_; {
io_name_t className;
IOCFPlugInInterface ** plugInInterface = NULL;
SInt32 score = 0;
NSError * error = nil;
BOOL result = NO;

mDeviceInterface = NULL;

NSXReturnError(IOObjectGetClass(mHidDevice, className));
if (error)
    goto done;

NSXReturnError(IOCreatePlugInInterfaceForService(mHidDevice, kIOHIDDeviceUserClientTypeID,kIOCFPlugInInterfaceID,&plugInInterface,&score));
if (error)
    goto done;

//Call a method of the intermediate plug-in to create the device interface
NSXReturnError((*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID) &mDeviceInterface));
if (error)
    goto done;

result = YES;

done:
    if (plugInInterface != NULL)
    {
        (*plugInInterface)->Release(plugInInterface);
    }
    if (error_)
        *error_ = error;
    return result;
}

In the old version that works, IOCreatePlugInInterfaceForService always returns a value of 0. In all the versions that don't work, the return value appears to always be -536870210. The mHidDevice in this function is the io_object_t handle for the device.

EDIT2: Here is the IORegistryExplorer page for the device

Here is the IORegistryExplorer page for the device

Pharisaic answered 16/2, 2018 at 17:34 Comment(5)
What's the error? Source code is available for that function (IOKitUser source bundle) so you may be able to find that specific error in there. However, the error could just as well be coming from the kernel side. In either case, the specific error (post the hex value if you don't know its symbolic equivalent) may give us all more of a clue. Plus: post your code!Grapheme
i found a list of IOReturn error codes here, but the value I am having returned doesn't appear to convert to one of these hex codes? Am i missing something?Pharisaic
That's 0xe00002be, which is kIOReturnNoResources. What does the className from IOObjectGetClass work out to?Grapheme
className returns "IOUSBHostHIDDevice"Pharisaic
Regarding the IORegistryExplorer screenshot: 1. I'd be mostly interested in knowing where in the object hierarchy it is located, specifically any client objects below it. It's not in view in the left pane of the screenshot, however. 2. The object you've selected is the IOUSBDevice, not the IOUSBHostHIDDevice, so that's not the one for which you're trying to create an IOCFPlugin user client.Grapheme
P
9

Finally managed to resolve this after weeks of head scratching. The new Xcode 9 uses app sandboxing to basically prevent access to USB, bluetooth, camera and microphone etc. by default in a new app. Once I switched this off it reverted to it's expected behaviour.

Glad it was such a simple answer in the end but disappointed Xcode does not provide more descriptive error messages or responses to let a user know they are essentially preventing themselves from accessing the parts of the system they need.

Pharisaic answered 21/2, 2018 at 10:15 Comment(1)
Oh my goodness! You saved my day. Although it is so obvious, I would never have thought of it!Adulterant
G
0

Looks like kIOReturnNoResources is returned if the loop at the end of IOCreatePlugInInterfaceForService completes with haveOne == false for whatever reason. Perhaps Start() is returning false because another process or driver already has exclusive access? I'd check what clients the device has in IORegistryExplorer.

Grapheme answered 18/2, 2018 at 12:25 Comment(0)
P
0

This error also happens when an application is trying to access the camera or bluetooth on MacOS 10.14 and higher. Permission shall be granted either explicitly by user (pop-up window), or through the Security & Privacy. The application should check for permission as shown here.

Picoline answered 4/6, 2020 at 23:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.