I’m creating my first DriverKit extension and I ran into an entitlement issue when trying to load my driver.
Error 0x0 8397 7 taskgated-helper: (ConfigurationProfiles) [com.apple.ManagedClient:ProvisioningProfiles] App.Dext: Unsatisfied entitlements: com.apple.developer.driverkit.transport.usb
I have already registered the entitlement com.apple.developer.driverkit.transport.usb with my vendor ID in the Apple Developer portal.
However, when I download the provisioning profile, it doesn’t include the idVendor value.
Screenshot from the developer portal (provisioning profile without idVendor) ?
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>1356</integer> <!-- Sony -->
<!-- Có thể bổ sung:
<key>idProduct</key>
<integer>XXXXX</integer>
-->
</dict>
</array>
Drivers
RSS for tagUnderstand the role of drivers in bridging the gap between software and hardware, ensuring smooth hardware functionality.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello, dear Apple engineers.
We have recently tried to pair our Android phones and iPhones via BLE SMP, but have encountered a very high probability of pairing failures. Through PacketLogger and Android phone HCI, we have determined that the issue is caused by the iOS side sending an SMP Pairing Failed message during the SMP process. Please help us analyze the reason for this.
Hi,
We were planning on using DriverKit to develop a USB Driver on IOS for iPhone. Within the DriverKit website, it say 'IOS16.0+' which lead us to believe it was compatible with iPhones running IOS16.0+.
However, it appears DriverKit is only available for iPads running iPadOS, and computers running macOS.
Are there any alternatives that would allow us to create a device specific USB driver for an iPhone running IOS?
Hi everyone,
We are experiencing an issue with SMS messages sent from our banking app (iOS) to our customers. The SMS are being delivered by the carrier, but on iOS devices some of them appear to be filtered or blocked, and users don’t see them in the Messages app.
This seems to be related to new SMS filtering rules on iOS (possibly affecting financial institutions and transactional SMS).
• Has anyone faced a similar situation?
• Are there specific Apple guidelines or best practices for SMS sender IDs / content to avoid being filtered?
• Is there any official documentation from Apple regarding these new SMS filtering mechanisms?
Any guidance or experiences would be greatly appreciated.
Thanks in advance!
We have a management application which manages security enable and disable for an external PCIe based storage device using Kernel Extension(SCSI Architecture Model Family for External USB Mass Storage devices which deals with IOSCSIBlockCommandsDevice, IOSCSIPeripheralDeviceType00 and IOBlockStorageService)
Now the issue we are facing is when we try to unlock the device using security code (already being set) , we will relink the device using VU command (RelinkBridge). Even-though both the commands are successful , the device is not getting relinked due to which we are not able to use the device for storage.
If someone have faced similar issue or any pointer on how to resolve this issue , it would be helpful.
Thanks in advance.
Hello,
We have developed a hardware product that embeds an FTDI USB-serial converter, and an application on MacOS that communicates with this device. We would like to port our application to iPadOS. I can see that when I plug the device into the iPad, it is recognized as a serial port, based on its console logs. When I attempt to enumerate serial ports on iPadOS using IOKit, I can see matching IOSerialBSDClient services, but the properties are sandboxed, including the IOCalloutDevice property, for example:
0 error 16:36:10.922450-0700 kernel Sandbox: ***(662) deny(1) iokit-get-properties iokit-class:IOUserSerial property:IOTTYSuffix
Is there an entitlement that can be applied that allows access to the serial port properties of an attached USB device? Or do I need to implement my own USBDriverKit driver for this device, as seems to be implied in these forum threads:
https://developer.apple.com/forums/thread/795202
https://developer.apple.com/forums/thread/655527
Hi,
Is it possible for a macOS (or iOS/ipadOS) app to communicate with a CCID-compliant reader using the CCID interface (i.e., directly sending the PC_TO_RDR_* messages) instead of using the CryptoTokenKit API?
Apple's CCID driver (/System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd) seems to support all the PC_TO_RDR and RDR_TO_PC messages: https://blog.apdu.fr/posts/2023/11/apple-own-ccid-driver-in-sonoma/#enable-my-ccid-driver
The background for this question is that we develop smartcard products and we'd like to use the finer grained settings provided by the CCID specification for testing/demo purposes.
Thank you.
While developing our driver, we've noticed that the *.ips report that contains the stacktrace of the crash is not always generated. I'm wondering why this report may not get generated, or if there's anything specific to do to guarantee it gets generated.
We've developed a PCIDriverKit driver for the capture card on macOS and have identified an issue: CreateMemoryDescriptorFromClient can only read data from the user space to the driver, but cannot write data back to the user.
typedef struct _MWCAP_EDID_DATA {
uint64_t size;
uint64_t uaddr;
} MWCAP_EDID_DATA;
// App
size_t xxx::GetEdid(void *buff, size_t size)
{
MWCAP_EDID_DATA edid;
edid.size = size;
edid.uaddr = (uint64_t)buff;
kr = IOConnectCallStructMethod(
connect,
kUserGetEdid,
&edid,
sizeof(MWCAP_EDID_DATA),
NULL,
NULL
);
// kr is 0. But However, the data in the buffer remains unchanged;
// it does not reflect the EDID copied from the DEXT.
return size;
}
// Driver
MWCAP_EDID_DATA *edid = (MWCAP_EDID_DATA *)input;
IOMemoryDescriptor *user_buf_mem = NULL;
IOAddressSegment segment;
segment.address = edid->uaddr;
segment.length = edid->size;
// We have verified that the values in edid->uaddr and edid->size are consistent with what was set by the application.
ret = CreateMemoryDescriptorFromClient(kIOMemoryDirectionOutIn, 1, &segment, &user_buf_mem);
if (ret != kIOReturnSuccess) {
os_log(OS_LOG_DEFAULT, "Failed to create memdesc with error: 0x%08x", ret);
break;
}
IOMemoryMap* user_buf_map = nullptr;
ret = user_buf_mem->CreateMapping(0, 0, 0, 0, 0, &user_buf_map);
if (ret != kIOReturnSuccess) {
os_log(OS_LOG_DEFAULT, "Failed to create mapping with error: 0x%08x", ret);
OSSafeReleaseNULL(user_buf_mem);
break;
}
// ... fill the user_buf_map with edid data ...
// For example:
// memcpy(user_buf_map->GetAddress(), source_edid_data, edid->size);
// At this point we have also verified the data in user_buf_map->GetAddress(), which matches our expectations.
OSSafeReleaseNULL(user_buf_map);
OSSafeReleaseNULL(user_buf_mem);
Please help take a look, thank you!
I want to turn off this effect and maintain the style before iOS18. Do I need to add content about iOS26 to the info.plist? Specifically, which content is it? I want to turn off the glass effect on the button
Topic:
App & System Services
SubTopic:
Drivers
Hi everyone,
We are in the process of migrating a legacy KEXT for our external multi-disk RAID enclosure to the modern DriverKit framework. During the performance validation of our KEXT, we observed a large and consistent maximum throughput difference between Intel-based Macs and Apple Silicon-based Macs. We would like to share our findings and hope to discuss with others in the community to see if you have had similar experiences that could confirm or correct our understanding.
The Observation: A Consistent Performance Gap
When using the exact same external RAID hardware (an 8-HDD RAID 5 array), driven by our mature KEXT, we see the following results in high-throughput benchmarks (AJA System Test, large sequential writes):
On a 2020 Intel-based Mac: We consistently achieve a throughput of ~2500 MB/s.
On modern M-series Macs (from M1 to M4): The throughput is consistently capped at ~1500 MB/s.
This performance difference of nearly 40% is significant and is present across the entire Apple Silicon product line.
Our Hypothesis: A Shift in Architectural Design Philosophy
Since the KEXT and external hardware are identical in both tests, we believe this performance difference is not a bug but a fundamental platform architecture distinction. Our hypothesis is as follows:
1. The Intel Mac Era ("Dedicated Throughput")
The Intel-based Macs we tested use a dedicated, discrete Intel Thunderbolt controller chip. This chip has its own dedicated PCIe lanes and resources, and its design appears to be singularly focused on maximizing raw, sustained data throughput for external peripherals.
2. The Apple Silicon Era ("Integrated Efficiency")
In contrast, M-series Macs use a deeply integrated I/O controller inside the SoC. This controller must share resources, such as the total unified memory bandwidth and the chip's overall power budget, with all other functional units (CPU, GPU, etc.).
We speculate that the design priority for this integrated I/O controller has shifted from "maximizing single-task raw throughput" to "maximizing overall system efficiency, multi-task responsiveness, and low latency." As a result, in a pure, single-task storage benchmark, its performance ceiling may be lower than that of the older, dedicated-chip architecture.
Our Question to the Community:
Is our understanding correct? Have other developers of high-performance storage drivers or peripherals also observed a similar performance ceiling for external storage on Apple Silicon Macs, when compared to high-end Intel Macs?
We believe that understanding this as a deliberate architectural trade-off is crucial for setting realistic performance targets for our DEXT. Our current goal has been adjusted to have our DEXT match the KEXT's ~1500 MB/s on the M-series platform.
Any insights, confirmations, or corrections from the community or Apple engineers would be greatly appreciated.
Thank you very much!
Charles
Hello everyone,
We are in the process of migrating a high-performance storage KEXT to DriverKit. During our initial validation phase, we noticed a performance gap between the DEXT and the KEXT, which prompted us to try and optimize our I/O handling process.
Background and Motivation:
Our test hardware is a RAID 0 array of two HDDs. According to AJA System Test, our legacy KEXT achieves a write speed of about 645 MB/s on this hardware, whereas the new DEXT reaches about 565 MB/s. We suspect the primary reason for this performance gap might be that the DEXT, by default, uses a serial work-loop to submit I/O commands, which fails to fully leverage the parallelism of the hardware array.
Therefore, to eliminate this bottleneck and improve performance, we configured a dedicated parallel dispatch queue (MyParallelIOQueue) for the UserProcessParallelTask method.
However, during our implementation attempt, we encountered a critical issue that caused a system-wide crash.
The Operation Causing the Panic:
We configured MyParallelIOQueue using the following combination of methods:
In the .iig file: We appended the QUEUENAME(MyParallelIOQueue) macro after the override keyword of the UserProcessParallelTask method declaration.
In the .cpp file: We manually created a queue with the same name by calling the IODispatchQueue::Create() function within our UserInitializeController method.
The Result:
This results in a macOS kernel panic during the DEXT loading process, forcing the user to perform a hard reboot.
After the reboot, checking with the systemextensionsctl list command reveals the DEXT's status as [activated waiting for user], which indicates that it encountered an unrecoverable, fatal error during its initialization.
Key Code Snippets to Reproduce the Panic:
In .iig file - this was our exact implementation:
class DRV_MAIN_CLASS_NAME: public IOUserSCSIParallelInterfaceController
{
public:
virtual kern_return_t UserProcessParallelTask(...) override
QUEUENAME(MyParallelIOQueue);
};
In .h file:
struct DRV_MAIN_CLASS_NAME_IVars {
// ...
IODispatchQueue* MyParallelIOQueue;
};
In UserInitializeController implementation:
kern_return_t
IMPL(DRV_MAIN_CLASS_NAME, UserInitializeController)
{
// ...
// We also included code to manually create the queue.
kern_return_t ret = IODispatchQueue::Create("MyParallelIOQueue",
kIODispatchQueueReentrant,
0,
&ivars->MyParallelIOQueue);
if (ret != kIOReturnSuccess) {
// ... error handling ...
}
// ...
return kIOReturnSuccess;
}
Our Question:
What is the officially recommended and most stable method for configuring UserProcessParallelTask_Impl() to use a parallel I/O queue?
Clarifying this is crucial for all developers pursuing high-performance storage solutions with DriverKit. Any explanation or guidance would be greatly appreciated.
Best Regards,
Charles
Hello everyone,
We are migrating a KEXT storage driver to DriverKit. In our KEXT, we use a "one LUN = one Target" model and successfully create multiple targets in a loop during initialization. We are now trying to replicate this architecture in our DEXT.
The issue is that only Target 0 is fully probed and mounted. For Target 1, the lifecycle silently stops after the first TEST UNIT READY command is successfully acknowledged. The macOS SCSI layer never sends any subsequent probe commands (like INQUIRY) to this target.
The failure sequence for Target 1, observed from our logs (regardless of whether Target 0 is created), is as follows:
AsyncCreateTargetForID(1) -> UserInitializeTargetForID(1) (Succeeds)
UserProcessParallelTask(Target: 1, Opcode: TUR) (Succeeds)
The DEXT correctly acknowledges the TUR command for Target 1 by returning kSCSITaskStatus_CHECK_CONDITION with UNIT ATTENTION in the Sense Data (Succeeds)
<-- Breakpoint -->
UserProcessParallelTask(Target: 1, Opcode: INQUIRY) (Never happens)
Through log comparison, we have confirmed that the DEXT's response to the TUR command for Target 1 is identical to the successful KEXT's response.
We have tried creating only Target 1 (skipping Target 0 entirely), but the behavior is exactly the same -> the probe still stalls after the TUR.
We initially suspected a race condition caused by consecutive calls to AsyncCreateTargetForID(). We attempted several methods to ensure that targets are created sequentially, such as trying to build a "creation chain" using OSAction completion handlers. However, these attempts were unsuccessful due to various compilation errors and API misunderstandings.
In any case, this "race condition" theory was ultimately disproven by our experiment where creating only Target 1 still resulted in failure.
We would like to ask two questions:
Is our inability to have a Target ID greater than 0 fully probed by macOS a bug in our own code, or could there be another reason we are unaware of?
If we do indeed need a "one-after-another" creation mechanism for AsyncCreateTargetForID, what is the correct way to implement a "chained creation" using OSAction completion handlers in DriverKit?
Thank you for any help or guidance.
Best Regards,
Charles
I am developing a DriverKit driver with the goal of sending vendor-specific commands to a USB storage device.
I have successfully created the DriverKit driver, and when I connect the USB storage device, it appears correctly in IORegistryExplorer.
My driver class inherits from IOUserSCSIPeripheralDeviceType00 in the SCSIPeripheralsDriverKit framework.
I also created a UserClient class that inherits from IOUserClient, and from its ExternalMethod I tried sending an INQUIRY command as a basic test to confirm that command transmission works.
However, the device returns an ILLEGAL REQUEST (Sense Key 0x5 / ASC 0x20).
Could someone advise what I might be doing wrong?
Below are the logs output from the driver:
2025-11-14 21:00:43.573730+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] Driver - NewUserClient() - Finished.
2025-11-14 21:00:43.573733+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start()
2025-11-14 21:00:43.573807+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start() - Finished.
2025-11-14 21:00:43.574249+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ExternalMethod() called
2025-11-14 21:00:43.574258+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ----- SCSICmdINQUIRY -----
2025-11-14 21:00:43.574268+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - command.fRequestedByteCountOfTransfer = 512
2025-11-14 21:00:43.575980+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x0
2025-11-14 21:00:43.575988+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x2
2025-11-14 21:00:43.575990+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x1
2025-11-14 21:00:43.575992+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x70
2025-11-14 21:00:43.575994+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x5
2025-11-14 21:00:43.575996+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x20
2025-11-14 21:00:43.575998+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x0
Here is the UserClient class:
class SampleDriverKitUserClient: public IOUserClient
{
public:
virtual bool init(void) override;
virtual kern_return_t Start(IOService* provider) override;
virtual kern_return_t Stop(IOService* provider) override;
virtual void free(void) override;
virtual kern_return_t ExternalMethod(
uint64_t selector,
IOUserClientMethodArguments* arguments,
const IOUserClientMethodDispatch* dispatch,
OSObject* target,
void* reference) override;
void SCSICmdINQUIRY(SampleDriverKitDriver *driver) LOCALONLY;
};
Here is the part that sends the INQUIRY command:
void SampleDriverKitUserClient::SCSICmdINQUIRY(SampleDriverKitDriver *driver)
{
kern_return_t kr = KERN_SUCCESS;
SCSIType00OutParameters command = {};
UInt8 dataBuffer[512] = {0};
SCSI_Sense_Data senseData = {0};
Log("----- SCSICmdINQUIRY -----");
SetCommandCDB(&command.fCommandDescriptorBlock, 0x12, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
command.fLogicalUnitNumber = 0;
command.fTimeoutDuration = 10000; // milliseconds
command.fRequestedByteCountOfTransfer = sizeof(dataBuffer);
Log("command.fRequestedByteCountOfTransfer = %lld", command.fRequestedByteCountOfTransfer);
command.fBufferDirection = kIOMemoryDirectionIn;
command.fDataTransferDirection = kSCSIDataTransfer_FromTargetToInitiator;
command.fDataBufferAddr = reinterpret_cast<uint64_t>(dataBuffer);
command.fSenseBufferAddr = reinterpret_cast<uint64_t>(&senseData);
command.fSenseLengthRequested = sizeof(senseData);
if( driver ) {
SCSIType00InParameters response = {};
kr = driver->UserSendCDB(command, &response);
if( kr != KERN_SUCCESS ) {
Log("SCSICmdINQUIRY() UserSendCDB failed (0x%x)", kr);
return;
}
Log("SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x%x", response.fCompletionStatus);
Log("SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x%x", response.fServiceResponse);
Log("SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x%x", response.fSenseDataValid);
Log("SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x%x", senseData.VALID_RESPONSE_CODE);
Log("SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x%x", senseData.SENSE_KEY);
Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x%x", senseData.ADDITIONAL_SENSE_CODE);
Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x%x", senseData.ADDITIONAL_SENSE_CODE_QUALIFIER);
if( response.fServiceResponse == kSCSIServiceResponse_TASK_COMPLETE ) {
Log("SCSICmdINQUIRY() UserSendCDB complete success!!");
}
for( int i=0; i < 5; i++ ) {
Log("data [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x",
i*8+0, dataBuffer[i*8+0],
i*8+1, dataBuffer[i*8+1],
i*8+2, dataBuffer[i*8+2],
i*8+3, dataBuffer[i*8+3],
i*8+4, dataBuffer[i*8+4],
i*8+5, dataBuffer[i*8+5],
i*8+6, dataBuffer[i*8+6],
i*8+7, dataBuffer[i*8+7] );
}
char vendorID[9] = {0};
memcpy(vendorID, &dataBuffer[8], 8);
Log("vendorID = %s",vendorID);
char productID[17] = {0};
memcpy(productID, &dataBuffer[16], 16);
Log("productID = %s",productID);
}
}
My environment is:
MacBook Pro (M2), macOS 15.6
If anyone has insight into what causes the ILLEGAL REQUEST, or what I am missing when using IOUserSCSIPeripheralDeviceType00 and UserSendCDB, I would greatly appreciate your help.
Thank you.
Topic:
App & System Services
SubTopic:
Drivers
Tags:
SCSIControllerDriverKit
DriverKit
BlockStorageDeviceDriverKit
I created a custom class that inherits from IOUserSCSIPeripheralDeviceType00 in the DriverKit SCSIPeripheralsDriverKit framework.
When I attempted to send a vendor-specific command to a USB storage device using the UserSendCDB function of this class instance, the function returned the error:
kIOReturnNotPrivileged (iokit_common_err(0x2c1)) // privilege violation
However, when using UserSendCDB in the same way to issue standard SCSI commands such as INQUIRY or Test Unit Ready, no error occurred and the returned sense data was valid.
Why is UserSendCDB able to send standard SCSI commands successfully, but vendor-specific commands return kIOReturnNotPrivileged?
Is there any required entitlement, DriverKit capability, or implementation detail needed to allow vendor-specific CDBs?
Below are the entitlements of my DriverKit extension:
<dict>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>[number of vendorid]</integer>
</dict>
</array>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.allow-any-userclient-access</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.driverkit.family.scsicontroller</key>
<true/>
</dict>
If there is any additional configuration or requirement to enable vendor-specific SCSI commands, I would appreciate your guidance.
Environment: macOS15.6 M2 MacBook Pro
Hello
I'm testing an 'age range sharing' feature using the AgeRangeService API in an app we service.
I approved 'Age Sharing' during testing.
(For your information, my account is an adult account.)
For repeat testing, I would like to delete the our app from 'Apps that requested user age information' or cancel the sharing status.
However, there doesn't seem to be such a feature.
Is there a way I can't find, or is this a feature that Apple doesn't offer?
We are developing a DriverKit driver on Apple M1. We use the following code to prepare DMA buffer:
IODMACommandSpecification dmaSpecification;
bzero(&dmaSpecification, sizeof(dmaSpecification));
dmaSpecification.options = kIODMACommandSpecificationNoOptions;
dmaSpecification.maxAddressBits = p_dma_mgr->maxAddressBits;
kret = IODMACommand::Create(p_dma_mgr->device,
kIODMACommandCreateNoOptions,
&dmaSpecification,
&impl->dma_cmd
);
if (kret != kIOReturnSuccess) {
os_log(OS_LOG_DEFAULT, "Error: IODMACommand::Create failed! ret=0x%x\n", kret);
impl->user_mem.reset();
IOFree(impl, sizeof(*impl));
return ret;
}
uint64_t flags = 0;
uint32_t segmentsCount = 32;
IOAddressSegment segments[32];
kret = impl->dma_cmd->PrepareForDMA(kIODMACommandPrepareForDMANoOptions,
impl->user_mem.get(),
0,
0, // 0 for entire memory
&flags,
&segmentsCount,
segments
);
if (kret != kIOReturnSuccess) {
OSSafeReleaseNULL(impl->dma_cmd);
impl->user_mem.reset();
IOFree(impl, sizeof(*impl));
os_log(OS_LOG_DEFAULT, "Error: PrepareForDMA failed! ret=0x%x\n", kret);
return kret;
}
I allocated several 8K BGRA video frames, each with a size of 141557760 bytes, and prepared the DMA according to the method mentioned above. The process was successful when the number of frames was 15 or fewer. However, issues arose when allocating 16 frames:
Error: PrepareForDMA failed! ret=0xe00002bd
By calculating, I found that the total size of 16 video frames exceeds 2GB. Is there such a limitation in DriverKit that the total DMA size cannot exceed 2GB? Are there any methods that would allow me to bypass this restriction so I can use more video frame buffers?
Kevin's Guide to DEXT Signing
The question of "How do I sign a DEXT" comes up a lot, so this post is my attempt to describe both what the issue are and the best current solutions are. So...
The Problems:
When DEXTs were originally introduced, the recommended development signing process required disabling SIP and local signing. There is a newer, much simpler process that's built on Xcode's integrated code-signing support; however, that newer process has not yet been integrated into the documentation library. In addition, while the older flow still works, many of the details it describes are no longer correct due to changes to Xcode and the developer portal.
DriverKit's use of individually customized entitlements is different than the other entitlements on our platform, and Xcode's support for it is somewhat incomplete and buggy. The situation has improved considerably over time, particularly from Xcode 15 and Xcode 16, but there are still issues that are not fully resolved.
To address #1, we introduced "development" entitlement variants of all DriverKit entitlements. These entitlement variants are ONLY available in development-signed builds, but they're available on all paid developer accounts without any special approval. They also allow a DEXT to match against any hardware, greatly simplifying working with development or prototype hardware which may not match the configuration of a final product.
Unfortunately, this also means that DEXT developers will always have at least two entitlement variants (the public development variant and the "private" approved entitlement), which is what then causes the problem I mentioned in #2.
The Automatic Solution:
If you're using Xcode 16 or above, then Xcode's Automatic code sign support will work all DEXT Families, with the exception of distribution signing the PCI and USB Families.
For completeness, here is how that Automatic flow should work:
Change the code signing configuration to "Automatic".
Add the capability using Xcode.
If you've been approved for one of these entitlements, the one oddity you'll see is that adding your approved capability will add both the approved AND the development variant, while deleting either will delete both. This is a visual side effect of #2 above; however, aside from the exception described below, it can be ignored.
Similarly, you can sign distribution builds by creating a build archive and then exporting the build using the standard Xcode flow.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware
Have a 2019 Ford Edge w/ Sync 3.4, wired carplay. Worked fine w/ iPhone 16 Pro on iOS 18. Upgraded to iPhone 17 Pro, came w/ iOS 26, carplay hasn't worked since.
I've kept trying throughout new iOS 26 releases, lately with iOS 26.3 Public Beta 1, still not working.
Have a long running issue with updates and system diagnostics as I've tried over the last few months: FB20739050
There is also a Apple support community thread with issues like this (and a ton of others) - my first post there was https://discussions.apple.com/thread/256138283?answerId=261613103022&sortBy=oldest_first#261613103022
I'm hoping here in the developer forums someone can maybe take a look at the feedback item and various system diagnostics to pin-point the issue. I'm a little concerned it's still not fixed this far into the follow-up point releases of iOS 26.
Appreciate any help, thanks!
--Chuck
Run on Xcode
Unchecked Scheme -> Run -> 'Debug excitable' is fine.
But, I need the debug log, how to fix?