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

Drivers Documentation

Post

Replies

Boosts

Views

Activity

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.
1
0
55
13h
Trouble using IOLog from a dext
Trying to use IOLog to print out a message from a dext. When I try to use IOLog, I get , though I did not or thought I did not tag it as private. I have tried to update the info.plist file for the dext according to https://developer.apple.com/forums/thread/705810, but that has not helped, or perhaps I am not defining it correctly since it's a dext. Anyone else had this issue, and how did you fix it?
5
0
229
2w
Fails to capture IOUSBHostInterface with macOS 15.3 despite root privileges in app
I have an app that captures USB storage device and sends some commands to it. The app has a privilege helper tool which captures the USB device. Everything was working fine upto macOS 15.2 but it 15.3 update broke the functionality. When the helper tool tries to capture the USB device, it is able to capture IOUSBHostDevice but fails to capture IOUSBHostInterface. The error is Code: 3758097097; Domain: IOUSBHostErrorDomain; Description: Failed to create IOUSBHostInterface.; Reason: Failed [super init] I have verified the UID, EUID, GID, EGID = 0 for the helper process. So by IOUSBHost documentation it should have worked. The code that cause the error inside the helper tool is func captureUSBInterface(interface: io_service_t) -> IOUSBHostInterface? { let queue = DispatchQueue(label: "com.example.usbdevice.queue2") var capturedInterface: IOUSBHostInterface? do { capturedInterface = try IOUSBHostInterface(__ioService: interface, options: .deviceCapture, queue: queue, interestHandler: nil) } catch { NSLog("Failed to capture USB interface: \(error)") return nil } return capturedInterface } The app has sandbox=False and is distributed outside of the App Store. Please advise (long-term, short-term solutions) on how to make this work.
2
0
184
1w
howto measure time_interval since physical plugin of a USB-gadget ?
=1) The situation: 1A) I make both a "DExt" and a "SDK" for still-imaging-USB-gadgets and MACOS>=14 ,iPADOS>=17 1B) One of the USB-gadgets needs warm_up after PlugIn (i.e End-User-App must know "now-TheMomentOfPlugIn" with precision ~1sec). =2) The question is how to do "1B" rationally? =3) My speculative guess: in BSD-descendant I expect existence (somewhere) of a "normal file" through "macports etc", which has normal "file creation time". Such a "file creation time" (accessible better via IORegistryEntry... at SDK-level; possibly via IOUSBHostInterface at DExt-level) is cognitive target of mine. =4) Additional constraints: Technically absent. I freely modify code either DExt (descendant of IOUSBHostInterface) or SDK-level (IORegistryEntryGetRegistryEntryID, IORegistryEntry...)
11
0
296
2w
No logs from log stream | grep CompanyName
I have USB DriverKit driver. When I use the log command below to get log, there is logs from my driver on my own M-series MacBook where the driver is built using developer account. log stream | grep CompanyName But on other mac like (M-series) Mac Mini, there is no log captured from driver though the driver is communicating with the machine correctly. The only log captured are from MacOS regarding CompanyName driver status/unload/load. The MacOS is Sonoma 14.7.2 and 14.7.3. Please advise on how to get log from driver since writing to files is not allowed in DriverKit. I need logs to troubleshoot on Mac Mini. Thanks.
1
0
208
2w
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
1.9k
Dec ’22
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
451
Oct ’24
Crash in IOService::Create
I am getting an unexpected crash from IOService::Create() when attempting to create a new user-client. The crash is a nullptr exception in OSCopyInObjects(). The last call from my code was IOService::Create(). As far as I can tell, all the input parameters to Create() are correct, and the Info.plist is has the correct key and class information - indeed, if I corrupt these I get an error status return rather than a crash. Any suggestions as to what could be causing this? I suspect that the problem may be related from a change in the underlying application that is creating the user client. This was modified from a standard app to a daemon, following the advice here: https://developer.apple.com/documentation/xcode/signing-a-daemon-with-a-restricted-entitlement. However, it is the driver that crashes - not the host opening the user client.
1
0
298
Jan ’25
DriverKit CppUserClient Searching for dext service but Failed opening service with error: 0xe00002c7
Hi Everybody, Follow Communicating between a DriverKit extension and a client app to migrate our kext to dext. The dext might have been loaded successfully by using the command systemextensionsctl list, the dext is loaded and enabled. % sectl list 1 extension(s) --- com.apple.system_extension.driver_extension enabled active teamID bundleID (version) name [state] * * K3TDMD9Y6B com.accusys.scsidriver (1.0/1) com.accusys.scsidriver [activated enabled] We try to use the CppUserClient.cpp to communicate with the dext, but can not get the dext service. The debug message as below: Failed opening service with error: 0xe00002c7. Here is the part of CppUserClient.cpp static const char* dextIdentifier = "com.accusys.scsidriver"; kern_return_t ret = kIOReturnSuccess; io_iterator_t iterator = IO_OBJECT_NULL; io_service_t service = IO_OBJECT_NULL; ret = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOUserServer"), &iterator); printf("dextIdentifier = %s\n", dextIdentifier); printf("IOServiceNameMatching return = %d\n", ret); if (ret != kIOReturnSuccess) { printf("Unable to find service for identifier with error: 0x%08x.\n", ret); PrintErrorDetails(ret); } printf("Searching for dext service...\n"); while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) { // Open a connection to this user client as a server to that client, and store the instance in "service" ret = IOServiceOpen(service, mach_task_self_, kIOHIDServerConnectType, &connection); if (ret == kIOReturnSuccess) { printf("\tOpened service.\n"); break; } else { printf("\tFailed opening service with error: 0x%08x.\n", ret); } IOObjectRelease(service); } IOObjectRelease(iterator); if (service == IO_OBJECT_NULL) { printf("Failed to match to device.\n"); return EXIT_FAILURE; } The console output message is dextIdentifier = com.accusys.scsidriver IOServiceNameMatching return = 0 Searching for dext service... Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed to match to device. Here is the log show message fredapp start UserInitializeController pcitest: fredapp pci vendorID: 14d6 deviceID: 626f fredapp nnnnnew configuaration read32 0x10 info: 1 fredapp nnnnnew configuaration read32 0x14 info: 80100004 fredapp new 128 before enable busmaster ReqMSGport_info 0x00000040 : fffff pcitest: fredapp 131 pci ConfigurationRead16 busmaster value 0 pcitest: fredapp 134 Enable BusMaster and IO space done...... locate 139 fredapp MemoryWrite32 function done...... fredapp new 143 after enable busmaster ReqMSGport_info 0x00000040 : 0 fredapp newwww before GetBARInfo memoryIndex1 info is: 5 fredapp GetBARInfo 1 kernel return status is: 0 fredapp GetBARInfo memoryIndex1 info is: 0 fredapp GetBARInfo barSize1 info is: 262144 fredapp GetBARInfo barType1 info is: 0 fredapp GetBARInfo result0 info is: 3758097136 fredapp GetBARInfo memoryIndex0 info is: 0 fredapp GetBARInfo barSize0 info is: 0 fredapp GetBARInfo barType0 info is: 0 pcitest: newwww fredapp againnnn test ReqMSGport info: 8 fredapp Start MPIO_Init_Prepare fredapp end MPIO_Init_Prepare. fredapp call 741 Total_memory_size: 1bb900 fredapp Start MemoryAllocationForAME_Module. fredapp IOBufferMemoryDescriptor create return status info is kIOReturnSuc fredapp IOBufferMemoryDescriptor virtualAddressSegment address info: 0x1 fredapp virtualAddressSegment length info: 0x00080000 fredapp end IOBufferMemoryDescriptor Create. fredapp dmaSpecification maxAddressBits: 0x00000000 fredapp dmaSpecification maxAddressBits: 0x00000027 fredapp IODMACommand create return status info is kIOReturnSuccess fredapp end IODMACommand Create. fredapp PrepareForDMA return status info is kIOReturnSuccess fredapp PrepareForDMA return status info is 0x00000000 fredapp Allocate memory PrepareforDMA return flags info: 0x00000003 fredapp Allocate memory PrepareforDMA return segmentsCount info: 0x00000 fredapp Allocate memory PrepareforDMA return physicalAddressSegment info: fredapp IOBufferMemoryDescriptor virtualAddressSegment address info-2: 0 fredapp verify data success init() - Finished. fredapp start UserGetDMASpecification fredapp end UserGetDMASpecification fredapp start UserMapHBAData fredapp end UserMapHBAData fredapp start UserStartController fredapp interruptType info is 0x00010000 fredapp PCI Dext interrupt final value return status info is 0x00000000 Any suggestions? Best Regards, Charles
6
0
397
Jan ’25
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
347
Dec ’24
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
465
Nov ’24
IOUSBHostInterface::Open for interrupt interfaces works on iPad Air but not iPad Pro
I am trying to open the CommunicationControl class IOUSBHostInterface in my USB driver, but it only seems to open on iPad Airs and not iPad Pros. I'm calling ivars->interruptInterface->Open(this, 0, NULL); After retrieving the interruptInterface from the device's InterfaceIterator. I try and open this, but on iPad Pros it returns kIOReturnNotOpen. I've tried closing and reopening the IOUSBHostDevice, closing and reopening the Interface, AbortDeviceRequests before opening, etc. but it just seems to work on iPad Air and not iPad Pro. I've tried on both iPadOS 17.6.1 and 18.2 Has anyone else seen this?
1
0
422
Dec ’24
Driver build does not get updated during Development
Hey, I'currently working on a Driver (and its App) for iPadOS (USB Device). I think have the right entitlements, as my driver gets installed with the app properly (after accepting it in the settings). It also gets loaded once the device is plugged in and so on. However the Kernel is not using the updated Version after I install a new Version of App and Driver to the iPad (at least most of the times). I'm verifying this by reading out the Logs via Console and the Driver prints its Build number on Start(). Sometimes it works like it should but I found no pattern. As far as I understand the iPad should automatically install the new Version of the Driver with the new App if its Build is different from the current one. I'm incrementing the Build of App and Driver automatically post-build so each build the iPad gets has its own Build number (This also works). Steps to reproduce: Cleaning Xcode Build Folder Unplugging the USB Device from the iPad. Building and Installing a new Version of the Driver and the App via Xcode (making sure the build number has changed) Plugging the USB back into the iPad Reading Console output of the iPad However it works (each time if I: Uninstall the app from the iPad manually or via Devices in Xcode Build and install the App via Xcode Open the Settings App and activate the Driver But uninstalling the App each time is taking a lot of time and manual Steps so I would like to fix this issue. Do you have any Ideas? Thanks, Bjarne
1
0
414
Dec ’24
DriverKit USB Transport to support multiple devices with different Vendor IDs
I have two different USB devices with different vendor IDs I would like to connect to. I submitted two separate requests for the com.apple.developer.driverkit.transport.usb entitlement for each vendor ID. However I am noticing the provisioning profile only has one of the vendor IDs. How do I submit a request for the USB Transport entitlement to support more than one vendor ID? I'm new to writing a DriverKit driver, so is this even possible?
5
0
658
Oct ’24