HID Device Access / Mode Switch

I might be trying to achieve the impossible here, but if there's another way to go about it any advice would be appreciated.

I've got an older Linux application that reflashes firmware on a connected USB HID device that I'm trying to port to macOS.

Essentially the device starts as an HID interface (0x03/0x01/0x01) but to update firmware receives a simple control payload and then restarts and connects as a different (non-HID) device.

However I can't open the HID device at all, I'm guessing this is some sort of permission error (SIP?).

AppleUSBHostUserClient::openGated: failed to open IOUSBHostDevice... provider is already opened for exclusive access by AppleUSB20Hub
hid_open_path: failed to open IOHIDDevice from mach entry: (0xE00002E2) not permitted
AppleUSBXHCICommandRing::setAddress: completed with result code 4
AppleUSBHostPort::createDevice: failed to create device (0xe00002bc)
AppleUSBIORequest ... transaction error ... 0xe00002ed

Is there any way at all to do this on macOS? Interestingly if you run a Windows VM in VMWare or similar and connect the device to that VM it works, so there's obviously some way but I'd like to create a simple standalone tool.

Is there any way at all to do this on macOS?

I'm not sure exactly which APIs you're interacting with and how that translates to the specific failure you're seeing, so I'm going to outline what "should" work. Give it a try and then we can dig into the specifics of any issue you run into.

Getting into the details:

Interestingly, if you run a Windows VM in VMware or similar and connect the device to that VM, it works, so there's obviously some way, but I'd like to create a simple standalone tool.

  • As noted in the documentation, your code needs to be running as root. There's an entitlement that allows VM's to work, but that's not appropriate for what you're doing.

  • For initial development purposes, I'd also disable the Sandbox. I think the com.apple.security.device.usb entitlement should let this work in a Sandboxed process, but it's easier to get the code working right in a simple tool, then sort out entitlement and security issues.

  • On the security front, you'll eventually need to use the privileged helper tool architecture shown in "EvenBetterAuthorizationSample". Again, in my experience, it's generally better to start by getting the code working in a standalone tool you run directly as root, then shift that code into a helper tool your final app uses.

Essentially, the device starts as an HID interface (0x03/0x01/0x01) but to update firmware, receives a simple control payload and then restarts and connects as a different (non-HID) device.

Depending on exactly how your device works, this may mean you need to:

  • Capture the device in HID mode.

  • Send the relevant USB command.

  • Reset the device so that it can come up in its new "mode". Note that this will invalidate your existing IOUSBHostDevice.

  • Capture the device again and then complete the firmware update process.

Hopefully, that's enough to get this working for you, but please let me know if you have any questions or run into any problems.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

HID Device Access / Mode Switch
 
 
Q