Hi,
We’re developing a DriverKit extension for iPadOS. In local Debug and Release builds, everything works as expected, but the same build uploaded to TestFlight fails at IOServiceOpen with the following errors:
-536870212 (0xE00002EC) kIOReturnUnsupported
-536870201 (0xE00002F7) kIOReturnNotPermitted
What we’ve verified so far
App entitlements
We checked our main app entitlements file, and it has the correct capabilities for the driverkit communication
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit.communicates-with-drivers</key>
<true/>
<key>com.apple.developer.driverkit.userclient-access</key>
<array>
<string>abc.def.ABCDriver</string>
</array>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
we also checked the Provisioning profile (as shown on the portal) and the “Enabled Capabilities” seems to have the correct DriverKit Capabilities enabled.
Enabled Capabilities
Access Wi-Fi Information, DriverKit, DriverKit (development), DriverKit Communicates with Drivers, DriverKit USB Transport (development), DriverKit USB Transport - VendorID, DriverKit UserClient Access, iCloud, In-App Purchase, Sign In with Apple, System Extension
When we download and inspect the provisioning profile as plain text, we notice that some expected DriverKit entitlements appear to be missing from the section.
<key>Entitlements</key>
<dict>
<key>beta-reports-active</key>
<true/>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.communicates-with-drivers</key>
<true/>
<key>application-identifier</key>
<string>ABC123456.abc.def</string>
<key>keychain-access-groups</key>
<array>
<string>ABC123456.*</string>
<string>com.apple.token</string>
</array>
<key>get-task-allow</key>
<false/>
<key>com.apple.developer.team-identifier</key>
<string>ABC123456</string>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>ABC123456.*</string>
<key>com.apple.developer.icloud-services</key>
<string>*</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array></array>
<key>com.apple.developer.icloud-container-development-container-identifiers</key>
<array></array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array></array>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>1234</integer>
</dict>
</array>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
We have a couple of questions:
Could the missing com.apple.developer.driverkit.userclient-access entitlement in the provisioning profile alone explain the kIOReturnUnsupported / kIOReturnNotPermitted failures from IOServiceOpen?
Why do some DriverKit capabilities appear in the Apple Developer portal UI but vanish from the actual profile we download? Is there an extra step we’re overlooking when regenerating profiles after toggling those capabilities?
Thanks
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
We’re looking for a reliable way to determine whether an iPad device supports DriverKit. Since there doesn't appear to be a direct public API for this, our current approach is as follows:
Retrieve the device’s model identifier (e.g., "iPad14,8") and the iOS/iPadOS version.
Map the model identifier to a known iPad model and its associated chip. If the device has an M-series chip, we assume it supports DriverKit.
For future-proofing, we plan to assume that any future iPad with a model identifier of iPad15,* or higher will contain an M-series chip and therefore support DriverKit.
We have a couple of questions:
Is there a more reliable or official API to determine the chip version or DriverKit support?
Is it reasonable to rely on the assumptions outlined in steps 2 and 3 for determining DriverKit compatibility?
Topic:
App & System Services
SubTopic:
Drivers
I'm using the following code to find the dext service. The driver is enabled in iOS settings prior to launching the app.
io_service_t mService = IO_OBJECT_NULL;
kern_return_t ret = kIOReturnSuccess;
io_iterator_t iterator = IO_OBJECT_NULL;
if (__builtin_available(iOS 15.0, *)) {
ret = IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceNameMatching("MyDriver"), &iterator);
} else {
// Fallback on earlier versions
}
if (ret != kIOReturnSuccess)
{
printf("Unable to find service");
}
while ((mService = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
//Only able to find service if launching the app first and then connecting the device
..........
}
I noticed the call IOServiceNameMatching doesn't return the same result for the following workflows:
Launch the app first and then connect the device, IOServiceGetMatchingServices can find the service.
Connect the device to USB-C port first, then launch the app, the same call can't find a matching service (iterator is null). I would need to disconnect and reconnect the device while the app is running in order to find the matching dext.
Any suggestion on how to find the matching dext service for workflow #2?
Thanks
I'm trying to build an XCode project that contains an app and another target for the DriverKit, and run into the following linker issue:
ld: file cannot be open()ed, errno=2 path=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.profile_driverkit.a in '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.profile_driverkit.a'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
My project has Code Coverage enabled. I noticed that if I disabled Code Coverage for all targets, I would be able to build successfully, and the driverKit would work as expected.
I wonder if it would be possible to build DriverKit without disabling code coverage.
Thanks
I'm trying to make an asynchronous bulk data read using IOUSBHostPipe AsyncIO/CompleteAsyncIO and send the data back to the user-space application using AsyncCompletion.
virtual void AsyncCompletion(OSAction *action, IOReturn status, const IOUserClientAsyncArgumentsArray asyncData, uint32_t asyncDataCount);
My understanding is that the IOUserClientAsyncArgumentsArray asyncData in AsyncCompletion method has a limited size of 128 bytes, and the data I need to send back is over 10k bytes.
Would it be possible to send such large data from the driver to the user-space application using async callback?
Thanks
Topic:
App & System Services
SubTopic:
Drivers
I'm trying to make an asynchronous bulk data read using AsyncIO/CompleteAsyncIO.
The problem I'm facing is that the AsyncIO succeeds but CompleteAsyncIO/ReadComplete doesn't get called when the AsyncIO's completion timeout is set to 0.
Changing the completion timeout to a non-zero would trigger ReadComplete but I keep getting the (0x2d6) "I/O Timeout" error
Any idea what I'm doing wrong?
Also, is there any limit for the maximum buffer length the callback can accept?
Thanks.
struct MyDriver_IVars {
OSAction* callbackAction = nullptr; // registered callback action by app
IOUSBHostInterface* interface;
IOUSBHostPipe* pipe;
IOBufferMemoryDescriptor* inDataBuffer;
OSAction* ioCompleteCallback = nullptr; // read complete callback action
uint32_t MAX_LENGTH = 1024;
};
kern_return_t IMPL(MyDriver, Start){
//...........
ret = ivars->interface->CopyPipe(endpoint->bEndpointAddress, &ivars->pipe);
ret = ivars->interface->CreateIOBuffer(kIOMemoryDirectionInOut, ivars->MAX_LENGTH, &ivars->inDataBuffer);
ret = CreateActionReadComplete(ivars->MAX_LENGTH, &ivars->ioCompleteCallback);
//...........
}
kern_return_t MyDriver::ReadData(int nbytes, int timeout)
{
//...........
kern_return_t ret = ivars->pipe->AsyncIO(ivars->inDataBuffer, ivars->MAX_LENGTH, ivars->ioCompleteCallback, 0);
//...........
}
void IMPL(MyDriver, ReadComplete)
{
Log("ReadComplete() - status - %d; bytes count - %d", status, actualByteCount);
//AsyncCompletion(ivars->callbackAction, ..................
}
virtual void ReadComplete(OSAction* action, IOReturn status, uint32_t actualByteCount, uint64_t completionTimestamp) TYPE(IOUSBHostPipe::CompleteAsyncIO);