DriverKit

RSS for tag

Develop device drivers that run in user space using DriverKit.

Posts under DriverKit tag

74 Posts

Post

Replies

Boosts

Views

Activity

DriverKit driver doesn't appear in Settings when installed with iPad app
I'm working on a DriverKit driver. I have it running on macOS, including a very simple client app written in SwiftUI. Everything is working fine there. I've added iPadOS as a destination for the app as demonstrated in the WWDC video on DriverKit for iPadOS. The app builds and runs on my iPad, as expected (after a little work to conditionalize out my use of SystemExtensions.framework for installation on macOS). However, after installing and running the app on an iPad, the driver does not show up in Settings->General, nor in the app-specific settings pane triggered by the inclusion of a settings bundle in the app. I've confirmed that the dext is indeed being included in the app bundle when built for iPadOS (in MyApp.app/SystemExtensions/com.me.MyApp.MyDriver.dext). I also can see in the build log that there's a validation step for the dext, and that seems to be succeeding. I don't know why the app isn't being discovered -- or in any case surfaced to the user -- when the app is installed on the iPad. Has anyone faced this problem and solved it? Are there ways to troubleshoot installation/discovery of an embedded DriverKit extensions on iOS? Unlike on macOS, I don't really see any relevant console messages.
6
2
2.1k
Apr ’25
Can't enable an iOS Driverkit driver when using an older app ID
Hi there, We've discovered a problem with our iOS app. We've been attempting to add a Driverkit driver to it, but any time we run the app through Testflight, the driver installs fine, but when we go to enable the driver toggle in the app's settings, the toggle stays on, but in the device logs I can see: could not insert bundle at <private> into manager: <private> As you would expect - this means the driver is not actually enabled and does not respond to a device being connected to the iPad. This does not happen when building & running the app locally, nor does it happen when installing an Ad Hoc build. We also have a different app, not yet shipped. We are able to add the driver to that app without issue. It works after going through Testflight. What we have discovered now is that everything works fine even if we just create an entirely new app with it's own bundle IDs. I should point out that in all cases, we're keeping the capabilities the same for each of these apps/IDs - including the managed capabilities. The bundle IDs that have this problem are older (5 years old or more). It seems like any newer ID will work, but trying to add the driver (and the associated managed capabilities) to an older app/ID results in this vague error message, with no further details. If we inspect the resulting dexts, we can also see that the "Internal requirements code size" is different on the ones that fail. The failing ones have a size of 204 bytes, whereas the working ones all have a size of 220 bytes. Not sure if that's related but it's strikingly consistent. Does this mean there is an issue with older app IDs, and we need Apple to manually refresh them in some way before the driverkit capabilities will work after going through Testflight? We have two apps in this state, both are of the same vintage (~5 years+). We've been battling this issue for months on and off, so would appreciate some help.
3
0
272
Apr ’25
Waiting for HID Entitlements for MONTHS
Hi Apple support, We requested the 4 HID-related Entitlements back in December 2024. Similarly to another post here in the forums that was completely ignored, our request has NOT been processed for months. Mailing the support staff results in boilerplate email responses with no content, calling them results in a chat with very nice people who are unable to help since they can't seem to reach the entitlement team directly. Having to wait for MONTHS when dealing with one of the biggest and supposedly best companies in the world is beyond disappointing. Can anyone help? Is there anyone else that has had this same issue and that has found a work-around? I can share all necessary details. Thanks, Matteo
1
0
146
Apr ’25
How to setup DriverKit Timer Event with OSAction Callback Binding
Hello Everyone, I'm encountering an issue while setting up a timer event in DriverKit and would appreciate any guidance. Here's my current implementation: void DRV_MAIN_CLASS_NAME::SetupEventTimer() { // 1. Create dispatch queue kern_return_t ret = IODispatchQueue::Create("TimerQueue", 0, 0, &ivars->dispatchQueue); if (ret != kIOReturnSuccess) { LogErr("Failed to create dispatch queue: 0x%x", ret); return; } // 2. Create timer source ret = IOTimerDispatchSource::Create(ivars->dispatchQueue, &ivars->dispatchSource); if (ret != kIOReturnSuccess) { LogErr("Failed to create timer: 0x%x", ret); OSSafeReleaseNULL(ivars->dispatchQueue); return; } /*! * @brief Create an instance of OSAction. * @discussion Methods to allocate an OSAction instance are generated for each method defined in a class with * a TYPE attribute, so there should not be any need to directly call OSAction::Create(). * @param target OSObject to receive the callback. This object will be retained until the OSAction is * canceled or freed. * @param targetmsgid Generated message ID for the target method. * @param msgid Generated message ID for the method invoked by the receiver of the OSAction * to generate the callback. * @param referenceSize Size of additional state structure available to the creator of the OSAction * with GetReference. * @param action Created OSAction with +1 retain count to be released by the caller. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ // 3: Create an OSAction for the TimerOccurred method // THIS IS WHERE I NEED HELP OSAction* timerAction = nullptr; ret = OSAction::Create(this, 0, 0, 0, &timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to create OSAction: 0x%x", ret); goto cleanup; } // 4. Set handler ret = ivars->dispatchSource->SetHandler(timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to set handler: 0x%x", ret); goto cleanup; } // 5. Schedule timer (1 second) uint64_t deadline = mach_absolute_time() + NSEC_PER_SEC; ivars->dispatchSource->WakeAtTime(0, deadline, 0); cleanup: if (ret != kIOReturnSuccess) { OSSafeReleaseNULL(timerAction); OSSafeReleaseNULL(ivars->dispatchSource); OSSafeReleaseNULL(ivars->dispatchQueue); } } Problem: The code runs but the OSAction callback binding seems incorrect (Step 3). According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method. But I try to use TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; TYPE(TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; kern_return_t TimerOccurred() TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) LOCALONLY; All results in Out-of-line definition of 'TimerOccurred' does not match any declaration in 'DRV_MAIN_CLASS_NAME' Questions: What is the correct way to declare a timer callback method using TYPE? How to get the values targetmsgid & msgid generated by Xcode? Any help would be greatly appreciated! Best Regards, Charles
6
0
398
Apr ’25
Issue Writing to BAR1 After BAR0 is Unavailable
Hello Everyone, I encountered an issue with PCI memory access in DriverKit. In my case, BAR0 is not available, but BAR1 is ready for use. Here’s the log output: !!! ERROR : Failed to get BAR0 info (error: 0xe00002f0). !!! BAR1 - MemoryIndex: 0x00000000, Size: 0x00040000, Type: 0 Issue Description When I initially wrote to BAR0 using memoryIndex = 0, it worked successfully: AME_Address_Write_32(pAMEData, pAMEData->memoryIndex, AME_HOST_INT_MASK_REGISTER, 0x0F); However, I mistakenly forgot to update memoryIndex to 1 for BAR1. Surprisingly, the write operation still succeeded. When I fixed memoryIndex = 1 for BAR1, the write operation no longer had any effect. There was no error, but the expected behavior did not occur. Relevant API (From IOPCIDevice.iig) /*! /*! * @brief Writes a 32-bit value to the PCI device's aperture at a given memory index. * @discussion This method writes a 32-bit register on the device and returns its value. * @param memoryIndex An index into the array of ranges assigned to the device. * @param offset An offset into the device's memory specified by the index. * @param data A 32-bit value to be written in host byte order. */ void MemoryWrite32(uint8_t memoryIndex, uint64_t offset, uint32_t data) LOCALONLY; Log Output: Writes to BAR0 (memoryIndex = 0) AME_Address_Write_32() called memoryIndex: 0, offset: 0x34, data: 0xf Wrote data 0xF to offset 52 AME_Address_Write_32() called memoryIndex: 0, offset: 0xa0, data: 0x1 Wrote data 0x1 to offset 160 AME_Address_Write_32() called memoryIndex: 0, offset: 0x20, data: 0xffffffff Wrote data 0xFFFFFFFF to offset 32 Writes to BAR1 (memoryIndex = 1) – No Response AME_Address_Write_32() called memoryIndex: 1, offset: 0x34, data: 0xf No confirmation log, no visible effect. Questions What should memoryIndex be set to for BAR1? The log shows "BAR1 - MemoryIndex: 0x00000000", but should I be using 1 instead? How can I verify if a write operation to BAR1 is successful? Is there a way to check if the memory region is actually writable? Should I use MemoryRead32() to confirm the written value? Any guidance would be greatly appreciated! Best Regards, Charles
3
1
151
Mar ’25
Dext not initializing with a log "Failed to write extension load report plist"
When plugging in my matched USB device I see the logs below. It seems the kernelmanagerd process is sandboxed and can't write out the reason my Dext failed to load. Is there somewhere else I can look for this info? default 11:03:22.175152-0700 kernelmanagerd Received kext load notification: me.keithg.MyUserUSBInterfaceDriver default 11:03:22.177637-0700 kernel 1 duplicate report for Sandbox: icdd(2124) allow file-read-data /Library/Image Capture/Devices error 11:03:22.177681-0700 kernel Sandbox: kernelmanagerd(545) deny(1) file-write-create /private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/com.apple.kernelmanagerd/TemporaryItems com.apple.libcoreservices error 11:03:22.177711-0700 kernelmanagerd mkdir: path=/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/com.apple.kernelmanagerd/TemporaryItems/ mode= -rwx------: [1: Operation not permitted] error 11:03:22.179361-0700 kernel Sandbox: kernelmanagerd(545) deny(1) file-write-create /private/var/db/loadedkextmt.plist.sb-5a00fc77-LNttZF com.apple.libcoreservices error 11:03:22.177755-0700 kernelmanagerd _dirhelper_relative_internal: error for path <private>: [1: Operation not permitted] com.apple.accessories default 11:03:22.177674-0700 WindowServer Sending analytics event... (eventName: com.apple.ioport.transport.USB.published) error 11:03:22.179913-0700 kernelmanagerd Failed to write extension load report plist.
1
0
208
Mar ’25
Which IOUserClient entitlements are really required?
Hello @all I'm develop a DriverKit driver extension and without entitlement checks by OS everything runs fine. But if the entitlements check is enabled in the NVRAM then I get an error due connecting my IOUserClient instance. Which entitlements are really and exactly required for my driver? My driver contains: one IOUserClient instance and multiple IOUserSerial instances The bundle identifier of the driver ist: org.eof.tools.VSPDriver The bundle identifier of the client app org.eof.tools.VSPInstall My entire source code is available on GitHub if any one want to dive deep in :) kernel[0:5107] () [VSPDriver]: NewUserClient called. kernel[0:5107] () [VSPDriver]: CreateUserClient: create VSP user client from Info.plist. kernel[0:5107] () [VSPUserClient]: init called. kernel[0:5107] () [VSPUserClient]: init finished. kernel[0:5107] () [VSPDriver]: CreateUserClient: check VSPUserClient type. kernel[0:5107] () [VSPDriver]: CreateUserClient: success. kernel[0:5107] () [VSPDriver]: NewUserClient finished. kernel[0:5107] () [VSPUserClient]: Start: called. kernel[0:5107] () [VSPUserClient]: User client successfully started. kernel[0:389f] DK: VSPUserClient-0x100001127:UC failed userclient-access check, needed bundle ID org.eof.tools.VSPDriver kernel[0:389f] DK: VSPUserClient-0x100001127:UC entitlements check failed kernel[0:5107] () [VSPUserClient]: Stop called. kernel[0:5107] () [VSPUserClient]: User client successfully removed. kernel[0:5107] () [VSPUserClient]: free called. Here my drivers entitlement file: <?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.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.family.serial</key> <true/> </dict> </plist> Here my drivers Info.plist file <?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>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>NSHumanReadableCopyright</key> <string>Copyright © 2025 by EoF Software Labs</string> <key>OSBundleUsageDescription</key> <string>Provide virtual serial port</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-any-userclient-access</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.system-extension.redistributable</key> <true/> <key>OSBundleLibraries</key> <dict> <key>com.apple.iokit.IOSerialFamily</key> <string>1.0</string> </dict> <key>IOKitPersonalities</key> <dict> <key>VSPDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOUserResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOProbeScore</key> <integer>0</integer> <key>IOClass</key> <string>IOUserService</string> <key>IOUserClass</key> <string>VSPDriver</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>UserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>VSPUserClient</string> </dict> <key>SerialPortProperties</key> <dict> <key>CFBundleIdentifierKernel</key> <string>com.apple.driver.driverkit.serial</string> <key>IOProviderClass</key> <string>IOSerialStreamSync</string> <key>IOClass</key> <string>IOUserSerial</string> <key>IOUserClass</key> <string>VSPSerialPort</string> <key>HiddenPort</key> <false/> <key>IOTTYBaseName</key> <string>vsp</string> <key>IOTTYSuffix</key> <string>0</string> </dict> </dict> </dict> </dict> </plist> Here the entitlements of the client app <?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.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.shared-with-you</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>$(TeamIdentifierPrefix).org.eof.apps</string> </array> </dict> </plist> Here the Info.plist of the client app: <?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>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>LSMinimumSystemVersion</key> <string>$(MACOSX_DEPLOYMENT_TARGET)</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.install</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.developer.system-extension.uninstall</key> <true/> <key>com.apple.developer.driverkit.userclient-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.private.driverkit.driver-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.security.temporary-exception.iokit-user-client-class</key> <array> <string>IOUserUserClient</string> </array> </dict> </plist>
2
0
595
Mar ’25
DriverKit IOUSBHostInterface iterator always empty
I'm trying to iterate through a USB device but the iterator is always empty or contains only the matched interface: Single interface in Iterator This happens when my driver matches against the interface. Because I need to use 2 interfaces (control and cdc), I try to open the IOUSBHostDevice (copied from the interface) and iterate through the rest, but I only get the interface my dext matched with. Empty Iterator I decided to match against USB communication devices, thinking things would be different. However, this time the interface iterator is completely empty (provider is IOUSBHostDevice). Here's a snippet of my code before iterating with IOUSBHostDevice->CopyInterface(): // teardown the configured interfaces. result = device->SetConfiguration(ivars->Config, true); __Require_noErr_Action(result, _failure_Out, ELOG("IOUSBHostDevice::SetConfiguration failed 0x%x", result)); // open usb device result = device->Open(this, 0, 0); __Require_noErr_Action(result, _failure_Out, ELOG("Failed to open IOUSBHostDevice")); // Get interface iterator result = device->CreateInterfaceIterator(&iterRef); __Require_noErr_Action(result, _failure_Out, ELOG("IOUSBHostDevice::CreateInterfaceIterator failed failed: 0x%x", result));
1
0
296
Mar ’25
Why UserInitializeTargetForID() not be invoked after UserCreateTargetForID() successfully?
Hello Everyone, I am trying to create a Fake SCSI target based on SCSIControllerDriverKit.framework and inherent from IOUserSCSIParallelInterfaceController, here is the code kern_return_t IMPL(DRV_MAIN_CLASS_NAME, Start) { ... // Programmatically create a null SCSI Target SCSIDeviceIdentifier nullTargetID = 0; // Example target ID, adjust as needed ret = UserCreateTargetForID(nullTargetID, nullptr); if (ret != kIOReturnSuccess) { Log("Failed to create Null SCSI Target for ID %llu", nullTargetID); return ret; } ... } According the document UserCreateTargetForID, after creating a TargetID successfully, the framework will call the UserInitializeTargetForID() The document said: As part of the UserCreateTargetForID call, the kernel calls several APIs like UserInitializeTargetForID which run on the default dispatch queue of the dext. But after UserCreateTargetForID created, why the UserInitializeTargetForID() not be invoked automatically? Here is the part of log show init() - Start init() - End Start() - Start Start() - try 1 times UserCreateTargetForID() - Start Allocating resources for Target ID 0 UserCreateTargetForID() - End Start() - Finished. UserInitializeController() - Start - PCI vendorID: 0x14d6, deviceID: 0x626f. - BAR0: 0x1, BAR1: 0x200004. - GetBARInfo() - BAR1 - MemoryIndex: 0, Size: 262144, Type: 0. UserInitializeController() - End UserStartController() - Start - msiInterruptIndex : 0x00000000 - interruptType info is 0x00010000 - PCI Dext interrupt final value, return status info is 0x00000000 UserStartController() - End Any assistance would be greatly appreciated! Thank you in advance for your support. Best regards, Charles
1
0
434
Mar ’25
Assistance Needed for Migrating KEXT Delay Code to DriverKit
Hello Everyone, I am working on migrating a KEXT to DriverKit but am struggling to resolve a specific issue. The code in question is simple, but I haven't been able to find a solution. void AME_IO_milliseconds_Delay(AME_U32 Delay) { Log("AME_IO_milliseconds_Delay()"); IOSleep(Delay); return; } //delay for a number of microseconds void AME_IO_microseconds_Delay(AME_U32 Delay) { Log("AME_IO_microseconds_Delay()"); IODelay(Delay); return; } I've sought help from Copilot and ChatGPT, but their suggestions haven't worked. Any guidance on how to implement this functionality in DriverKit would be greatly appreciated. Thank you for your time and assistance. Best regards, Charles
1
0
274
Mar ’25
Local DriverKit development blocked by provisioning profile requirement
Hi, I am working on a personal HIDDriverKit project. The documentation suggests that you do not need the entitlements from Apple to do local development - that all you need to do is turn of SIP, enable developer mode, and turn signing to "Sign to Run Locally". However, I have followed all of these steps, and am still running into the error that to build, I need to have a provisioning profile with the DriverKit (development) feature (MacOS 15.2 Xcode 16.2). Am I missing something here regarding the steps for local development? Does one need to request a development version of the entitlements even for local development? Do I need a paid developer account to do this? Thank-you in advance.
3
0
619
Mar ’25
Is DEXT Driver supporting these Networking Features?
I would like to know if macOS DEXT supports the following networking features: Tx/Rx Multiqueue, RSS, RSC, NS/ARP offload, PTP or packet timestamping and TSN. I couldn't find relevant documentation for these features in the Apple Developer Documentation. If they are supported, could you let me know which features are supported and how to find the corresponding official Apple documentation? Thanks
9
0
767
Mar ’25
The Map() of IOBufferMemoryDescriptor failure and cause the DriverKit Start() repeat
Hello Everyone, I am trying to develop a DriverKit for RAID system, using PCIDriverKit & SCSIControllerDriverKit framework. The driver can detect the Vendor ID and Device ID. But before communicating to the RAID system, I would like to simulate a virtual Volume using a memory block to talk with macOS. In the UserInitializeController(), I allocated a 512K memory for a IOBufferMemoryDescriptor* volumeBuffer, but fail to use Map() to map memory for volumeBuffer. result = ivars->volumeBuffer->Map( 0, // Options: Use default 0, // Offset: Start of the buffer ivars->volumeSize, // Length: Must not exceed buffer size 0, // Flags: Use default nullptr, // Address space: Default address space &mappedAddress // Output parameter ); Log("Memory mapped completed at address: 0x%llx", mappedAddress); // this line never run The Log for Map completed never run, just restart to run the Start() and makes this Driver re-run again and again, in the end, the driver eat out macOS's memory and system halt. Are the parameters for Map() error? or I should not put this code in UserInitializeController()? Any help is appreciated! Thanks in advance. Charles
0
0
408
Mar ’25