Understand the role of drivers in bridging the gap between software and hardware, ensuring smooth hardware functionality.

Drivers Documentation

Posts under Drivers subtopic

Post

Replies

Boosts

Views

Activity

System Panic with IOUserSCSIParallelInterfaceController during Dispatch Queue Configuration
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
1
0
83
3w
INQUIRY command is ILLEGAL REQUEST
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.
1
0
35
3w
The total DMA size in DriverKit cannot exceed 2G?
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?
1
0
21
3d
Implementing a virtual serial port using DriverKit/SerialDriverKit
I'm trying to implement a virtual serial port driver for my ham radio projects which require emulating some serial port devices and I need to have a "backend" to translate the commands received by the virtual serial port into some network-based communications. I think the best way to do that is to subclass IOUserSerial? Based on the available docs on this class (https://developer.apple.com/documentation/serialdriverkit/iouserserial), I've done the basic implementation below. When the driver gets loaded, I can see sth like tty.serial-1000008DD in /dev and I can use picocom to do I/O on the virtual serial port. And I see TxDataAvailable() gets called every time I type a character in picocom. The problems are however, firstly, when TxDataAvailable() is called, the TX buffer is all-zero so although the driver knows there is some incoming data received from picocom, it cannot actually see the data in neither Tx/Rx buffers. Secondly, I couldn't figure out how to notify the system that there are data available for sending back to picocom. I call RxDataAvailable(), but nothing appears on picocom, and RxFreeSpaceAvailable() never gets called back. So I think I must be doing something wrong somewhere. Really appreciate it if anyone could point out how should I fix it, many thanks! VirtualSerialPortDriver.cpp: constexpr int bufferSize = 2048; using SerialPortInterface = driverkit::serial::SerialPortInterface; struct VirtualSerialPortDriver_IVars {     IOBufferMemoryDescriptor *ifmd, *rxq, *txq;     SerialPortInterface *interface;     uint64_t rx_buf, tx_buf;     bool dtr, rts; }; bool VirtualSerialPortDriver::init() {     bool result = false;     result = super::init();     if (result != true)     {         goto Exit;     }     ivars = IONewZero(VirtualSerialPortDriver_IVars, 1);     if (ivars == nullptr)     {         goto Exit;     }     kern_return_t ret;     ret = ivars->rxq->Create(kIOMemoryDirectionInOut, bufferSize, 0, &ivars->rxq);     if (ret != kIOReturnSuccess) {         goto Exit;     }     ret = ivars->txq->Create(kIOMemoryDirectionInOut, bufferSize, 0, &ivars->txq);     if (ret != kIOReturnSuccess) {         goto Exit;     }     IOAddressSegment ioaddrseg;     ivars->rxq->GetAddressRange(&ioaddrseg);     ivars->rx_buf = ioaddrseg.address;     ivars->txq->GetAddressRange(&ioaddrseg);     ivars->tx_buf = ioaddrseg.address;     return true; Exit:     return false; } kern_return_t IMPL(VirtualSerialPortDriver, HwActivate) {     kern_return_t ret;     ret = HwActivate(SUPERDISPATCH);     if (ret != kIOReturnSuccess) {         goto Exit;     }     // Loopback, set CTS to RTS, set DSR and DCD to DTR     ret = SetModemStatus(ivars->rts, ivars->dtr, false, ivars->dtr);     if (ret != kIOReturnSuccess) {         goto Exit;     } Exit:     return ret; } kern_return_t IMPL(VirtualSerialPortDriver, HwDeactivate) {     kern_return_t ret;     ret = HwDeactivate(SUPERDISPATCH);     if (ret != kIOReturnSuccess) {         goto Exit;     } Exit:     return ret; } kern_return_t IMPL(VirtualSerialPortDriver, Start) {     kern_return_t ret;   ret = Start(provider, SUPERDISPATCH);     if (ret != kIOReturnSuccess) {         return ret;     }     IOMemoryDescriptor *rxq_, *txq_;     ret = ConnectQueues(&ivars->ifmd, &rxq_, &txq_, ivars->rxq, ivars->txq, 0, 0, 11, 11);     if (ret != kIOReturnSuccess) {         return ret;     }     IOAddressSegment ioaddrseg;     ivars->ifmd->GetAddressRange(&ioaddrseg);     ivars->interface = reinterpret_cast<SerialPortInterface*>(ioaddrseg.address);     SerialPortInterface &intf = *ivars->interface;     ret = RegisterService();     if (ret != kIOReturnSuccess) {         goto Exit;     }     TxFreeSpaceAvailable(); Exit:     return ret; } void IMPL(VirtualSerialPortDriver, TxDataAvailable) {     SerialPortInterface &intf = *ivars->interface;     // Loopback     // FIXME consider wrapped case     size_t tx_buf_sz = intf.txPI - intf.txCI;     void *src = reinterpret_cast<void *>(ivars->tx_buf + intf.txCI); //    char src[] = "Hello, World!";     void *dest = reinterpret_cast<void *>(ivars->rx_buf + intf.rxPI);     memcpy(dest, src, tx_buf_sz);     intf.rxPI += tx_buf_sz;     RxDataAvailable();     intf.txCI = intf.txPI;     TxFreeSpaceAvailable();     Log("[TX Buf]: %{public}s", reinterpret_cast<char *>(ivars->tx_buf));     Log("[RX Buf]: %{public}s", reinterpret_cast<char *>(ivars->rx_buf)); // dmesg confirms both buffers are all-zero     Log("[TX] txPI: %d, txCI: %d, rxPI: %d, rxCI: %d, txqoffset: %d, rxqoffset: %d, txlogsz: %d, rxlogsz: %d",         intf.txPI, intf.txCI, intf.rxPI, intf.rxCI, intf.txqoffset, intf.rxqoffset, intf.txqlogsz, intf.rxqlogsz); } void IMPL(VirtualSerialPortDriver, RxFreeSpaceAvailable) {     Log("RxFreeSpaceAvailable() called!"); } kern_return_t   IMPL(VirtualSerialPortDriver,HwResetFIFO){     Log("HwResetFIFO() called with tx: %d, rx: %d!", tx, rx);     kern_return_t ret = kIOReturnSuccess;     return ret; } kern_return_t   IMPL(VirtualSerialPortDriver,HwSendBreak){     Log("HwSendBreak() called!");     kern_return_t ret = kIOReturnSuccess;     return ret; } kern_return_t   IMPL(VirtualSerialPortDriver,HwProgramUART){     Log("HwProgramUART() called, BaudRate: %u, nD: %d, nS: %d, P: %d!", baudRate, nDataBits, nHalfStopBits, parity);     kern_return_t ret = kIOReturnSuccess;     return ret; }      kern_return_t   IMPL(VirtualSerialPortDriver,HwProgramBaudRate){     Log("HwProgramBaudRate() called, BaudRate = %d!", baudRate);     kern_return_t ret = kIOReturnSuccess;     return ret; } kern_return_t   IMPL(VirtualSerialPortDriver,HwProgramMCR){     Log("HwProgramMCR() called, DTR: %d, RTS: %d!", dtr, rts);     ivars->dtr = dtr;     ivars->rts = rts;     kern_return_t ret = kIOReturnSuccess; Exit:     return ret; } kern_return_t  IMPL(VirtualSerialPortDriver, HwGetModemStatus){     *cts = ivars->rts;     *dsr = ivars->dtr;     *ri = false;     *dcd = ivars->dtr;     Log("HwGetModemStatus() called, returning CTS=%d, DSR=%d, RI=%d, DCD=%d!", *cts, *dsr, *ri, *dcd);     kern_return_t ret = kIOReturnSuccess;     return ret; } kern_return_t   IMPL(VirtualSerialPortDriver,HwProgramLatencyTimer){     Log("HwProgramLatencyTimer() called!");     kern_return_t ret = kIOReturnSuccess;     return ret; } kern_return_t   IMPL(VirtualSerialPortDriver,HwProgramFlowControl){     Log("HwProgramFlowControl() called! arg: %u, xon: %d, xoff: %d", arg, xon, xoff);     kern_return_t ret = kIOReturnSuccess; Exit:     return ret; }
1
0
2.1k
Feb ’25
Looking for USBSerialDriver sample code
I would like to write a driver that supports our custom USB-C connected device, which provides a serial port interface. USBSerialDriverKit looks like the solution I need. Unfortunately, without a decent sample, I'm not sure how to accomplish this. The DriverKit documentation does a good job of telling me what APIs exist but it is very light on semantic information and details about how to use all of these API elements. A function call with five unexplained parameters just is that useful to me. Does anyone have or know of a resource that can help me figure out how to get started?
1
0
696
Feb ’25
IOServiceOpen fails with -308 Error (smUnExBusError)
I have a driver project where I'm opening and closing a connection to a custom driver. If I do what I think I need to be doing to unmap the memory, when I try to open the service again, it fails. If I skip the step where I do that unmapping, the service opens successfully. If I call unmap() before trying to call openConnection() again, it will fail with a -308 error return code. If I skip that call to unmap(), it works and I'm able to communicate with my device. Here's the code where I open the service: public func openConnection() throws { guard !isOpen else { return } // Open device var connection: io_connect_t = IO_OBJECT_NULL var result = IOServiceOpen(device, mach_task_self_, 0, &connection) if result != kIOReturnSuccess { NSLog("Failed opening device with error: 0x%08x.\n", result); throw NSError.cdc_kernelReturnErrorWithError(result) } defer { IOConnectRelease(connection) } if device == IO_OBJECT_NULL || connection == IO_OBJECT_NULL { throw NSError.cdc_kernelReturnErrorWithError(result) } let receiveDataMappedMemory = ClientDriverMappedMemory(connection: connection, memoryType: MappedMemoryType_ReceiveDataBuffer) try receiveDataMappedMemory.map() let transmitDataMappedMemory = ClientDriverMappedMemory(connection: connection, memoryType: MappedMemoryType_TransmitDataBuffer) try transmitDataMappedMemory.map() // Setup async notification IONotificationPortSetDispatchQueue(dataReceivedPort, dataReceivedQueue) let callbackPort = IONotificationPortGetMachPort(dataReceivedPort) let input = DataStruct(foo: 0, bar: 0) var output = DataStruct(foo: 0, bar: 0) var outputSize = MemoryLayout<DataStruct>.size // Trampoline to C function because I don't quite know how to make this work in Swift result = setupCallback(self, connection, callbackPort, input, &output, &outputSize) if result != kIOReturnSuccess { NSLog("Error registering async callback with driver: \(result)"); throw NSError.cdc_kernelReturnErrorWithError(result) } self.connection = connection self.receivedDataMappedMemory = receiveDataMappedMemory self.transmitDataMappedMemory = transmitDataMappedMemory } map() and unmap() functions: - (BOOL)mapWithError:(NSError **)error { error = error ?: &(NSError * __autoreleasing){ nil }; kern_return_t result = IOConnectMapMemory64(self.connection, self.memoryType, mach_task_self(), &_address, &_size, kIOMapAnywhere); if (result != kIOReturnSuccess) { *error = [NSError cdc_kernelReturnErrorWithError:result]; return NO; } self.mapped = YES; return YES; } - (BOOL)unmapWithError:(NSError **)error { error = error ?: &(NSError * __autoreleasing){ nil }; kern_return_t result = IOConnectUnmapMemory64(self.connection, self.memoryType, mach_task_self(), _address); if (result != kIOReturnSuccess) { *error = [NSError cdc_kernelReturnErrorWithError:result]; return NO; } self.mapped = NO; return YES; } Any insights? What all should I be doing to close the service? Why would the unmapping create this issue or what else could the -308 error be indicated has gone wrong?
3
0
669
Dec ’24
NSInternalInconsistencyException Call must be made on main thread
#4 Thread NSInternalInconsistencyException Call must be made on main thread CoreFoundation ___exceptionPreprocess + 164 libsystem_pthread.dylib _start_wqthread + 8 #0 Thread semaphore_wait_trap libsystem_kernel.dylib semaphore_wait_trap + 8 libdispatch.dylib 0x00000001b96ed000 + 457547470247841612 UnityFramework Staticburst_initialize + 17597401577822386088 UnityFramework DllCanUnloadNow + 52172 UnityFramework. DllCanUnloadNow + 51292 UnityFramework DllCanUnloadNow + 421068 UnityFramework. Unityplcrash_async_mach_exception_get_siginfo + 5073080 UnityFramework. GlobalizationNative_GetTimeZoneDisplayName + 1585284 UnityFramework. GlobalizationNative_GetTimeZoneDisplayName + 926212 UnityFramework. 0x000000010ce18000 + 77478852 UnityFramework. GlobalizationNative_GetTimeZoneDisplayName + 124804 UnityFramework. GlobalizationNative_GetTimeZoneDisplayName + 124592 UnityFramework. _ZdaPvRKSt9nothrow_t + 2445400 UnityFramework. _ZdaPvRKSt9nothrow_t + 2502608 UnityFramework. _ZdaPvRKSt9nothrow_t + 2556896 UnityFramework. _ZdaPvRKSt9nothrow_t + 2555820 UnityFramework. _ZdaPvRKSt9nothrow_t + 211836 UnityFramework. _ZdaPvRKSt9nothrow_t + 1216980 UnityFramework. _ZdaPvRKSt9nothrow_t + 1145620 UnityFramework. _ZdaPvRKSt9nothrow_t + 1145684 UnityFramework. _ZdaPvRKSt9nothrow_t + 1146408 UnityFramework. UnitySendMessage + 6940844 UnityFramework. _Z12DecodeBase64PKhPhi + 138076 QuartzCore. 0x00000001b2d06000 + 193228 UIKitCore. UIApplicationMain + 1589427071078105428 UnityFramework. _Z12DecodeBase64PKhPhi + 11056988545834161928
1
0
571
Dec ’24
iphone mirroring
Hi Team , I want to create a system where i can mirror the iPhone screen connected through USB and control it from the web browser. can anyone help me ? Thanks , Mukta
0
0
366
Jan ’25
NFC Communication Issues on iPhone 12–15 with NXP NTAG 5 (ISO15693 Pass-Through Mode)
We are developing an iOS app that communicates with a device using an NXP NTAG 5 chip in ISO15693 pass-through mode. While the app works flawlessly on older iPhone models (iPhone 8, SE, X) and most Android devices, we are experiencing severe reliability issues on iPhone 12, 13, 14, and 15. Issue Summary On newer iPhones (12–15), 90% of communication attempts fail. Retry strategies do not work, as the NFC session is unexpectedly canceled while handling CoreNFC custom commands. The issue is not consistent—sometimes all requests fail immediately, while other times, a batch of reads might succeed unexpectedly before failing again. Technical Details The failure occurs while executing the following request, which should return 256 bytes: tag.customCommand(requestFlags: .highDataRate, customCommandCode: commandCode, customRequestParameters: Data(byteArray)) { (responseData, error) in } The returned error is: -[NFCTagReaderSession transceive:tagUpdate:error:]:897 Error Domain=NFCError Code=100 "Tag connection lost" UserInfo={NSLocalizedDescription=Tag connection lost} For reference, we tested a comparable STM ST25 chip in ISO15693 and NDEF mode, and the exact same issue occurs. Observations and Debugging Attempts Positioning of the NFC antenna has been tested extensively. Disabling Bluetooth and Wi-Fi does not improve reliability. Rebooting the device or waiting between attempts sometimes improves success rates but does not provide a structural fix. When reading multiple blocks (e.g., 15 blocks of 256 bytes each): The process often fails within the first three blocks. After multiple failures, it may suddenly succeed in reading all blocks in one go before returning to a series of failures. The nfcd logs suggest issues at the low-level NFC and SPMI layers, indicating potential hardware or firmware-related problems: error 17:36:18.289099+0100 nfcd phOsalNfc_LogStr:65 NCI DATA RSP : Timer expired before data is received! error 17:36:18.292936+0100 nfcd NFHardwareSerialQuerySPMIError:1339 "Invalid argument" errno=22 setsockopt: SYSPROTO_CONTROL:IO_STOCKHOLM_SPMIERRORS error 17:36:18.293036+0100 nfcd phTmlNfc_SpmiDrvErrorStatus:1157 "Invalid argument" errno=22 Failed to query SPMI error registers error 17:36:18.293235+0100 nfcd phOsalNfc_LogStr:65 phLibNfc_SpmiStsRegInfoNtfHandler: Read Spmi Status Failed - pInfo set to NULL error 17:36:18.293313+0100 nfcd _Callback_NFDriverNotifyGeneral:2353 Unknown notification: 0x5b error 17:36:18.294163+0100 nfcd phOsalNfc_LogStr:65 Target Lost!! error 17:36:18.294678+0100 nfcd -[_NFReaderSession handleSecureElementTransactionData:appletIdentifier:]:164 Unimplemented error 17:36:18.294760+0100 nfcd -[_NFReaderSession handleSecureElementTransactionData:appletIdentifier:]:164 Unimplemented error 17:36:18.320132+0100 nfcd phOsalNfc_LogStr:65 ISO15693 XchgData,PH_NCINFC_STATUS_RF_FRAME_CORRUPTED Detected by NFCC during Data Exchange error 17:36:18.320291+0100 nfcd phOsalNfc_LogU32:74 phNciNfc_ChkDataRetransmission: Re-transmitting Data pkt Attempt..=1 error 17:36:18.622050+0100 nfcd phOsalNfc_LogStr:65 NCI DATA RSP : Timer expired before data is received! error 17:36:18.625857+0100 nfcd NFHardwareSerialQuerySPMIError:1339 "Invalid argument" errno=22 setsockopt: SYSPROTO_CONTROL:IO_STOCKHOLM_SPMIERRORS error 17:36:18.625919+0100 nfcd phTmlNfc_SpmiDrvErrorStatus:1157 "Invalid argument" errno=22 Failed to query SPMI error registers error 17:36:18.626132+0100 nfcd phOsalNfc_LogStr:65 phLibNfc_SpmiStsRegInfoNtfHandler: Read Spmi Status Failed - pInfo set to NULL error 17:36:18.626182+0100 nfcd _Callback_NFDriverNotifyGeneral:2353 Unknown notification: 0x5b error 17:36:18.626899+0100 nfcd phOsalNfc_LogStr:65 Target Lost!! error 17:36:18.627482+0100 nfcd -[_NFReaderSession handleSecureElementTransactionData:appletIdentifier:]:164 Unimplemented error 17:36:18.627568+0100 nfcd -[_NFReaderSession handleSecureElementTransactionData:appletIdentifier:]:164 Unimplemented error 17:36:18.833174+0100 nfcd -[_NFReaderSession handleSecureElementTransactionData:appletIdentifier:]:164 Unimplemented error 17:36:19.145289+0100 nfcd phOsalNfc_LogStr:65 NCI DATA RSP : Timer expired before data is received! error 17:36:19.149233+0100 nfcd NFHardwareSerialQuerySPMIError:1339 "Invalid argument" errno=22 setsockopt: SYSPROTO_CONTROL:IO_STOCKHOLM_SPMIERRORS error 17:36:19.149353+0100 nfcd phTmlNfc_SpmiDrvErrorStatus:1157 "Invalid argument" errno=22 Failed to query SPMI error registers error 17:36:19.149730+0100 nfcd phOsalNfc_LogStr:65 phLibNfc_SpmiStsRegInfoNtfHandler: Read Spmi Status Failed - pInfo set to NULL error 17:36:19.149797+0100 nfcd _Callback_NFDriverNotifyGeneral:2353 Unknown notification: 0x5b error 17:36:19.150463+0100 nfcd phOsalNfc_LogStr:65 Target Lost!! Any solutions? Has anyone else encountered similar behavior with CoreNFC on iPhone 12–15? Could this be related to changes in NFC hardware or power management in newer iPhone models? Any suggestions on possible workarounds or alternative approaches would be greatly appreciated.
2
0
465
Feb ’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
358
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
254
Mar ’25
USB Accessory Device Charging Behavior Changed with iOS18
Hello, We are experiencing some issues with our USB accessory unexpectedly charging the iOS device it is connected with only when the iOS device supports USB-C and is on iOS 18+ The following is a description of the discrepancy we note between iOS versions: After performing a USB Role switch, our Accessory becomes a typical USB Device and the Apple device becomes the USB host. with iOS 17: 
 The Accessory then sends a PowerSourceUpdate message to the iOS 17 device via iAP2 protocol. Apple device has a USB Type C Connector. * We are specifying: AvailableCurrentForDevice = 0 mA  DeviceBatteryShouldChargeIfPowerIsPresent = 1. Three observations: iPad Battery Settings page -  we observe  'Last charged to…' (indicating no charging) On the Lumify App running (iOS 17), we observe that UIKit.current.batteryState indicated 'Not charging' Battery icon on top right of the screen indicates 'No Charging' with iOS 18: The same Accessory sends the same PowerSourceUpdate message to the iOS 18 device via iAP2 protocol using USB Type C Connector. We are specifying the same: AvailableCurrentForDevice = 0 mA DeviceBatteryShouldChargeIfPowerIsPresent = 1. We observe: iPad Battery Settings page -  we observe  'Charging'  On the Lumify App running (iOS 18), we observe that UIKit.current.batteryState indicated 'Charging' Battery icon on top right of the screen indicates 'No Charging' Please could you help us understand why the Battery status is showing as 'Charging' in the Settings page and with the 'UIKit.current.batteryState' even though we have specified 'AvailableCurrentForDevice = 0 mA'?
 Since our accessory is heavily reliant on the Battery status / Charging state, is there potentially another way we get an accurate battery charging status that we are missing? Or are there other suggestions outside of what we do currently to ensure our accessory does not place the iOS18 device into a charging state?
5
0
459
May ’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
101
Mar ’25
AirPods Max USB-C Lossless mode not working on any device (iOS 18.5 beta + macOS 15.5 Beta)
I’m experiencing a persistent issue with the new USB-C lossless audio feature on AirPods Max (firmware 7E101). I’m using original Apple USB-C to USB-C cable and have tested this setup across multiple Apple devices, including: • iPhone (running iOS 18.5 beta) • iPad Pro with USB-C • MacBook Pro (15.5 Beta) ❗️Problem: Despite Apple’s announcement that AirPods Max now support wired lossless audio over USB-C, I’m unable to get any audio output via USB-C on any device. • On iPhone: I disabled Bluetooth, connected via USB-C — no sound. • On MacBook: The device is shown as “AirPods Max USB Audio” in System Information > USB, but it does not appear in Sound settings or Audio MIDI Setup as an available output. • On iPad Pro: Same behavior — no audio output. Other details: • I performed a factory reset of the headphones, but the LED flashes red instead of the expected amber → white sequence. (Apple’s documentation does not mention red flash behavior during reset — might indicate an error state.) • The issue is not isolated to the iOS 18.5 beta — since the same behavior occurs on macOS and iPadOS. What works: • Bluetooth audio still works fine. • The cable and USB-C ports function with other audio devices. ⸻ Summary: It looks like: • USB audio is being detected on a hardware level (at least on Mac), • but software support for output (especially on macOS/iPadOS) is either not implemented, disabled, or bugged — possibly connected to iOS 18.5 beta or broader OS-level limitations.
2
0
171
Apr ’25