Dear Apple Developer Support,
We develop a Mac Catalyst app that has the com.apple.vm.device-access entitlement. We are now able to redirect USB devices to a remote virtual machine using the SPICE remote desktop protocol.
We have run into a case where the only working solution we have found depends on an API that the SDK marks as unavailable for Mac Catalyst. We would like to understand the supported approach before submitting a build for review.
The app uses libusb's Darwin backend to capture a USB device before redirecting it. The capture sequence is the standard one:
- IOServiceAuthorize(service, kIOServiceInteractionAllowed)
- USBDeviceReEnumerate(device, kUSBReEnumerateCaptureDeviceMask)
- USBDeviceOpenSeize, then USBInterfaceOpen on the captured device
A) Behaviour without step 1
IOKitLib.h annotates IOServiceAuthorize with __API_UNAVAILABLE(ios, macCatalyst), so our first implementation skipped it on Catalyst and went straight to the capture re-enumeration. In that configuration:
- The entitlement is present and readable via SecTaskCopyValueForEntitlement.
- USBDeviceReEnumerate with kUSBReEnumerateCaptureDeviceMask returns kIOReturnSuccess.
- The device does re-enumerate — it disappears and reappears on the host, and its volumes are unmounted.
- The kernel drivers then re-attach, and the following USBInterfaceOpen fails with kIOReturnExclusiveAccess ("another process has device opened for exclusive access").
The capture reports success but does not actually take the device away from the system's drivers. This is reproducible with a USB mass-storage device (a flash drive with a mounted volume).
B) Behaviour with step 1
If IOServiceAuthorize is called before the re-enumeration, capture works correctly and USB redirection functions as expected.
To call it from a Catalyst target we had to work around the availability annotation by binding the symbol directly:
extern kern_return_t my_service_authorize(io_service_t service, uint32_t options) asm("_IOServiceAuthorize");
This compiles, links and runs. We note that IOKit.tbd in the macOS SDK exports _IOServiceAuthorize for the arm64-maccatalyst and x86_64-maccatalyst targets, which is why it links.
Our questions are as follows:
- With com.apple.vm.device-access granted, what is the supported way to authorize USB device capture from a Mac Catalyst app?
- If IOServiceAuthorize is the intended mechanism, is calling it from Catalyst as shown above acceptable for App Store review, given the __API_UNAVAILABLE(macCatalyst) annotation on its declaration?
- If it is not acceptable, is there a Catalyst-available equivalent? Or is the entitlement expected to make USBDeviceReEnumerate(kUSBReEnumerateCaptureDeviceMask) sufficient on its own? If the latter is the intent, the behaviour described above suggests it is not currently sufficient, and we would be glad to file a bug report with a reproducible case.
We would rather not ship an API usage that could be read as circumventing a platform availability annotation, which is why we are asking before submitting.
Thank you, Morpheusly Inc. development team