Post

Replies

Boosts

Views

Activity

Reply to DriverKit issue with TestFlight
We were able to resolve the build issues, and the driver is now working correctly on TestFlight. Here are some details: It turns out that the xcodebuild -exportArchive step was overwriting our dext’s build number to match the app build number (e.g., 3433099.287482533). We set the manageAppVersionAndBuildNumber flag to false in our ExportOptions.plist to prevent Xcode from syncing the driver’s build number, and that resolved the issue. For the provisioning profile mismatch between development and App Store builds, we followed the recommendation to use separate entitlement configurations for normal and ipa (distribution) builds. That change made automatic signing work as expected. Really appreciate your help!
Topic: App & System Services SubTopic: Drivers Tags:
Jul ’25
Reply to DriverKit issue with TestFlight
I extracted and inspected the entitlements from both the built app and the embedded DriverKit extension (dext) in the .ipa. Below are the details: App Entitlements <?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>application-identifier</key> <string>ABC123456.abc.def</string> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>get-task-allow</key> <false/> </dict> </plist> Driver Extension (dext) Entitlements <?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>application-identifier</key> <string>ABC123456.abc.def.ABCDriver</string> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>get-task-allow</key> <false/> </dict> </plist> Let me know if anything looks incorrect or if further clarification is needed. Thanks!
Topic: App & System Services SubTopic: Drivers Tags:
Jul ’25
Reply to DriverKit issue with TestFlight
Thanks for the response. No, but iPadOS apps should not include "com.apple.developer.driverkit.userclient-access". Note that your construction of that entitlement is also invalid (it's a list of bundle IDs and requires approval to use), We realized this was for MacOS only and since our app is for iOS, we plan to remove this. The actual bundleId was approved and we just use a censored bundle ID here Assuming the contents you've posted are accurate, then this mismatch is the problem: Those dictionaries must match in order for your DEXT to load. Yes, we also noticed the missing idVendor in our driver entitlement and updated it to match the provisioning profile. However, the issue still persists—our DriverKit is realized but does not start in the TestFlight build. Local Build (works): After enabling the driver and connecting the hardware, the system logs show the driver is both realized and started successfully. TestFlight Build (broken): On the same hardware and sequence, the system only logs the realization of the driver, but none of the usual logs from init() or Start() appear. driverkitd Realize dext ABC123456.abc.def.ABCDriver //Missing logs below showing our driver is initialized and started in TestFlight build kernel Driver ABC123456.abc.def.ABCDriver has crashed 0 time(s) kernel DK: ABCDriver-0x100001b68 waiting for server ABC123456.abc.def.ABCDriver-100001b68 driverkitd Figuring out dext launch context: ABC123456.abc.def.ABCDriver ............ driverkitd Launching dext ABC123456.abc.def.ABCDriver ABC123456.abc.def.ABCDriver 0x100001b68 .... driverkitd Launching driver extension via running board: Dext ABC123456.abc.def.ABCDriver v1 ..... ....... kernel ABCDriver - init() kernel ABCDriver - Start() Below are the info plist, entitlements and app store profiles for our driver and client app. Driver info.plist <plist version="1.0"> <dict> <key>CFBundleDisplayName</key> <string>ABDC Driver</string> <key>OSBundleUsageDescription</key> <string>abdcef</string> <key>IOKitPersonalities</key> <dict> <key>ABCDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>IOClass</key> <string>IOUserService</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOUSBHostDevice</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClass</key> <string>ABCDriver</string> <key>IOUserServerName</key> <string>abc.def.ABCDriver</string> <key>ABCDriverUserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>ABCDriverClient</string> </dict> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>idProduct</key> <integer>5678</integer> <key>idVendor</key> <integer>1234</integer> </dict> </dict> </dict> </plist> Driver entitlements <plist version="1.0"> <dict> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.security.app-sandbox</key> <true/> </dict> </plist> Driver app store profile <key>Entitlements</key> <dict> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>application-identifier</key> <string>ABC123456.abc.def.ABCDriver</string> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <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> </dict> Client app entitlements <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/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> </dict> </plist> Client app store profile <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> Please let us know if anything in our configuration appears to be missing or incorrect. We also have a couple of questions: Our driver’s Info.plist specifies both idVendor and idProduct, but our entitlements and provisioning profiles currently include only the idVendor. Do we need to request approval or entitlement inclusion for the idProduct as well? We’ve noticed that our development provisioning profiles use wildcard matching for idVendor: <key>idVendor</key> <string>*</string> whereas the App Store profiles use an explicit integer value: <key>idVendor</key> <integer>1234</integer> Is there a way to update our development profiles to match the App Store versions? Thanks!
Topic: App & System Services SubTopic: Drivers Tags:
Jul ’25
Reply to DriverKit issue with TestFlight
Please ignore the IOServiceOpen errors above. We've observed that after uploading our build to TestFlight, the driver is no longer being detected. Specifically, we’re unable to find the matching driver service, and the expected "Service name: ..." log does not appear—even after connecting the hardware and enabling the driver in the iOS App settings. The same code works reliably in local (non-TestFlight) builds, where we're able to successfully detect the driver and establish a connection. Here's the relevant snippet for reference: func isDriverMatched() -> Bool { var bDriverMatched = false var serviceMatchItr: io_iterator_t = 0 if #available(iOS 15.0, *) { guard let matchingDict = IOServiceMatching("IOUserService") else { Log.e(with: "TAG", with: "Failed to create matching dictionary") return false } let key = "IOUserServerName" as CFString let serverName = "abc.def.ABCDriver" as CFString CFDictionarySetValue(matchingDict, Unmanaged.passUnretained(key).toOpaque(), Unmanaged.passUnretained(serverName).toOpaque()) let serviceMatchedError = IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &serviceMatchItr) guard serviceMatchedError == kIOReturnSuccess else { PCOPiLog.e(with: "TAG", with: "Failed to find matching service") IOObjectRelease(serviceMatchItr) return false } var service: io_object_t repeat { service = IOIteratorNext(serviceMatchItr) if service != 0 { var serviceNameCString = [CChar](repeating: 0, count: 128) var serviceName = "Service name: <Unknown>" if IORegistryEntryGetName(service, &serviceNameCString) == KERN_SUCCESS { serviceName = String(cString: serviceNameCString) PCOPiLog.i(with: "TAG", with: "Service name: \(serviceName)") } else { PCOPiLog.i(with: "TAG", with: "Service name: <Unknown>") } // ........................... } } while service != 0 if !bDriverMatched { PCOPiLog.e(with: "TAG", with: "No matching driver service found or not responsive.") } } else { return false } IOObjectRelease(serviceMatchItr) return bDriverMatched } We investigated further by unzipping both the TestFlight .ipa and the archive from Xcode. The dext is present in both builds, but the .dext inside the .ipa is noticeably smaller (~150 KB) compared to the one in the archive (~350 KB). We also extracted the entitlements from the signed app bundle in the .ipa. Here's what was included: <?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>application-identifier</key> <string>ABC123456.abc.def</string> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>get-task-allow</key> <false/> </dict> </plist> This set is missing some key entitlements compared to our app's original entitlements file. It’s unclear why the packaging or signing process is dropping these during TestFlight submission. We also checked the entitlements embedded in the .dext itself (inside the .ipa) <?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>application-identifier</key> <string>ABC123456.abc.def.ABCDriver</string> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict/> </array> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>get-task-allow</key> <false/> </dict> </plist> Question: Could the missing entitlements in the main app bundle from the .ipa—prevent the system from detecting or loading the driver at runtime? Also, could the smaller .dext size in the .ipa suggest it is being stripped or excluded in some way? We would appreciate any insights or recommendations. Thanks!
Topic: App & System Services SubTopic: Drivers Tags:
Jul ’25
Reply to DriverKit issue with TestFlight
In addition to the main app's entitlements and provisioning profile described above, here are the entitlements and provisioning profile details for our DriverKit extension: Driver Entitlements <?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</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict/> </array> <key>com.apple.security.app-sandbox</key> <true/> </dict> </plist> Entitlements section in the Driver's Provisioning Profile <key>Entitlements</key> <dict> <key>beta-reports-active</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>application-identifier</key> <string>ABC123456.abc.def.ABCDriver</string> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.developer.driverkit.allow-third-party-userclients</key> <true/> <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> </dict>
Topic: App & System Services SubTopic: Drivers Tags:
Jul ’25
Reply to IOServiceNameMatching can't find dext service
thanks a lot for the detailed answer! I found a bug in our driver client free() function (double releasing a reference to a callback Action) that caused the driver to crash when the app was closed. Since the driver wasn't cleaned up properly, when I tried to relaunch the app with the usbc device still connected, my driver couldn’t reload. Fixing this bug helped fix the issue we were seeing with the workflow in case #1. Case #3 depends on exactly what drivers are actually loading when your DEXT isn't present. My guess is that this is either a variant of #1 (so fixing #1 will also resolve #3) or that the system driver can't unload (in which case, the user would need to hot plug the device before you DEXT will match). If you managed to unload correctly, then it's possible that the system driver (which replace your DEXT) isn't unloading when you reenable your DEXT. with the fix for case#1, case #3 still doesn't work properly. I tried to walk up the registry and noticed when I disabled my driver with the device still connected, AppleUSBHostCompositeDevice ended up matching with the device, and it didn't get unloaded when I reenabled my driver. We display a message asking the user to disconnect and reconnect the device but just wondering if anything else can be done for this particular case. Thanks a lot!
Topic: App & System Services SubTopic: Drivers Tags:
Oct ’24
Reply to IOServiceNameMatching can't find dext service
Thank you for your comment. This is an app we develop for iPadOS so I guess the IORegistryExplorer.app doesn't work in this case. Just a bit more info on the problem we are facing. When the USB device is connected before launching the app (with driver already enabled in iOS Settings), I notice my Driver Start() doesn't get called, which results in "MyDriver" not showing up when I try to get matching service with IOServiceMatching("IOUserService"). Others such as AppleBCMWLANBusInterfacePCIe, IO80211ReporterProxy, AppleBCMWLANCore are available but MyDriver. I tried using match notifications but got the same result as IOServiceGetMatchingServices. If I launch the app first and then connect my USB device, MyDriver Start() is called and MyDriver is available. This allows me to find the driver and call IOServiceOpen on it. Everything then works as expected. With the driver up and running, if I disabled and reenabled the driver in iOS settings without disconnecting/reconnecting the device, MyDriver Start() wouldn't get called, and get matching service with IOServiceMatching("IOUserService") wouldn't find it again. I have no problem matching on the device using IOServiceMatching("IOUSBDevice") and idVendor + idProduct as keys. It doesn’t matter if the device is connected before or after launching the app, matching on the device always returns the correct value. It is the matching of the driver that I'm having problems with. In the driver info.plist file we use IOUSBHostDevice for IOProviderClass since our device is a non-HID USB device. From what I’m seeing, looks like the device would need to be physically connected after launching the app for the driver to start and the matching to happen properly. I’m wondering if anything can be done to get it to work for the workflows I mentioned in #1 and #3 above. Thanks! MyDriver Info.plist file <plist version="1.0"> <dict> <key>IOKitPersonalities</key> <dict> <key>MyDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>IOClass</key> <string>IOUserService</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOUserResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClass</key> <string>MyDriver</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>MyDriverUserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>MyDriverClient</string> </dict> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>idProduct</key> <integer>1234</integer> <key>idVendor</key> <integer>5678</integer> </dict> </dict> </dict> </plist> MyDriver.entitlements <?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</key> <true/> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict/> </array> <key>com.apple.security.app-sandbox</key> <true/> </dict> </plist> code to get matching service and open service io_service_t mService = IO_OBJECT_NULL; kern_return_t ret = kIOReturnSuccess; io_iterator_t iterator = IO_OBJECT_NULL; //temporary checking for all services //I refined it further using other keys CFMutableDictionaryRef matchingDict = IOServiceMatching("IOUserService"); if (__builtin_available(iOS 15.0, *)) { ret = IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &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 "MyDriver" if launching the app first and then connecting the device ret = IOServiceOpen(mService, mach_task_self_, 0, &mConnection); .......... }
Topic: App & System Services SubTopic: Drivers Tags:
Sep ’24