Unable to connect to any HID device using Core HID

Hello,

I am currently working on a USB HID-class device and I wanted to test communications between various OSes and the device.

I was able to communicate through standard USB with the device on other OSes such as Windows and Linux, through their integrated kernel modules and generic HID drivers. As a last test, I wanted to test macOS as well.

This is my code, running in a Swift-based command line utility:

import Foundation
import CoreHID

let matchingCriteria = HIDDeviceManager.DeviceMatchingCriteria(vendorID: 0x1234, productID: 0x0006) // This is the VID/PID combination that the device is actually listed under

let manager = HIDDeviceManager()

for try await notification in await manager.monitorNotifications(matchingCriteria: [matchingCriteria]) {
    switch notification {
        case .deviceMatched(let deviceReference):
            print("Device Matched!")

            guard let client = HIDDeviceClient(deviceReference: deviceReference) else {
                fatalError("Unable to create client. Exiting.") // crash on purpose
            }

            let report = try await client.dispatchGetReportRequest(type: .input)
            print("Get report data: [\(report.map { String(format: "%02x", $0) }.joined(separator: " "))]")

    case .deviceRemoved(_):
        print("A device was removed.")

    default:
        continue
    }
}

The client.dispatchGetReportRequest(...) line always fails, and if I turn the try expression into a force-unwrapped one (try!) then the code, unsurprisingly, crashes.

The line raises a CoreHID.HIDDeviceError.unknown() exception with a seemingly meaningless IOReturn code (last time I tried I got an IOReturn code with the value of -536870211).

The first instinct is to blame my own custom USB device for not working properly, but it doesn't cooperate with with ANY USB device currently connected: not a keyboard (with permissions granted), not a controller, nothing.

I did make sure to enable USB device access in the entitlements (when I tried to run this code in a simple Cocoa app) as well.

...What am I doing wrong here? What does the IOReturn code mean?

Thanks in advance for anybody willing to help out!

What does the IOReturn code mean?

IOKit (and the kernel more broadly) uses a structured error code format which is documented in "IOReturn.h". As you've discovered, that format looks crazy as a signed integer. That's because it needs to be interpreted as a hexadecimal value:

-536870211 -> 0xE00002BD

From IOReturn.h:

#define kIOReturnNoMemory        iokit_common_err(0x2bd) // can't allocate memory

...What am I doing wrong here?

So, in terms of the error itself, internally dispatchGetReportRequest eventually calls into IOHIDLibUserClient._getReport (in the kernel) where kIOReturnNoMemory is the default return value. In terms of what's happening in your case I'm not sure, but my guess is that you've got multiple input reports and the empty report is failing because of that.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Unable to connect to any HID device using Core HID
 
 
Q