SerialDriverKit

RSS for tag

Develop drivers for serial I/O devices connected to Mac.

Posts under SerialDriverKit tag

31 Posts

Post

Replies

Boosts

Views

Activity

USB communication with a pre-OS system
Hello everyone, We're working on an iOS app that needs to connect to a non-Apple pre-operating system using USB for serial communication. Our goal is to send and receive data between an iPhone and a UEFI-based system directly over USB. We've created a proof of concept using the USBMux protocol, which let us exchange basic messages. However, we're running into problems with the USB endpoint setup. In some cases, the USB communication doesn't start or stay connected. Since this is for a pre-boot environment, it might not fit into the usual iOS USB communication frameworks. We're looking for help with the following: Any guidance or documentation on setting up USB serial communication between an iPhone and a non-Apple pre-boot system Information on system APIs, frameworks, or protocols that iOS supports for direct USB communication in this scenario Access to official USBMux documentation or specs to understand its limitations and capabilities better Whether this communication requires MFi certification or if there are other Apple-supported interfaces we can use Thank you!
1
0
562
2w
Can't get USBSerialDriverKit driver loaded
I am writing a DriverKit driver for the first that uses the USBSerialDriverKit. The driver its purpose is to expose the device as serial interface (/dev/cu.tetra-pei0 or something like this). My problem: I don't see any logs from that driver in the console and I tried like 40 different approaches and checked everything. The last message I see is that the driver get successfully added to the system it is in the list of active and enabled system driver extensions but when I plug the device in none of my logs appear and it doesn't show up in ioreg. So without my driver the target device looks like this: +-o TETRA PEI interface@02120000 <class IOUSBHostDevice, id 0x10000297d, registered, matched, active, busy 0 (13 ms), retain 30> | { | "sessionID" = 268696051410 | "USBSpeed" = 3 | "UsbLinkSpeed" = 480000000 | "idProduct" = 36886 | "iManufacturer" = 1 | "bDeviceClass" = 0 | "IOPowerManagement" = {"PowerOverrideOn"=Yes,"DevicePowerState"=2,"CurrentPowerState"=2,"CapabilityFlags"=32768,"MaxPowerState"=2,"DriverPowerState"=0} | "bcdDevice" = 9238 | "bMaxPacketSize0" = 64 | "iProduct" = 2 | "iSerialNumber" = 0 | "bNumConfigurations" = 1 | "UsbDeviceSignature" = <ad0c16901624000000ff0000> | "USB Product Name" = "TETRA PEI interface" | "locationID" = 34734080 | "bDeviceSubClass" = 0 | "bcdUSB" = 512 | "USB Address" = 6 | "kUSBCurrentConfiguration" = 1 | "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "UsbPowerSinkAllocation" = 500 | "bDeviceProtocol" = 0 | "USBPortType" = 0 | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | "USB Vendor Name" = "Motorola Solutions, Inc." | "Device Speed" = 2 | "idVendor" = 3245 | "kUSBProductString" = "TETRA PEI interface" | "kUSBAddress" = 6 | "kUSBVendorString" = "Motorola Solutions, Inc." | } | +-o AppleUSBHostCompositeDevice <class AppleUSBHostCompositeDevice, id 0x100002982, !registered, !matched, active, busy 0, retain 5> | { | "IOProbeScore" = 50000 | "CFBundleIdentifier" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "IOProviderClass" = "IOUSBHostDevice" | "IOClass" = "AppleUSBHostCompositeDevice" | "IOPersonalityPublisher" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "bDeviceSubClass" = 0 | "CFBundleIdentifierKernel" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "IOMatchedAtBoot" = Yes | "IOMatchCategory" = "IODefaultMatchCategory" | "IOPrimaryDriverTerminateOptions" = Yes | "bDeviceClass" = 0 | } | +-o lghub_agent <class AppleUSBHostDeviceUserClient, id 0x100002983, !registered, !matched, active, busy 0, retain 7> | { | "IOUserClientCreator" = "pid 1438, lghub_agent" | "IOUserClientDefaultLocking" = Yes | } | +-o IOUSBHostInterface@0 <class IOUSBHostInterface, id 0x100002986, registered, matched, active, busy 0 (5 ms), retain 9> | | { | | "USBPortType" = 0 | | "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | | "USB Vendor Name" = "Motorola Solutions, Inc." | | "bcdDevice" = 9238 | | "USBSpeed" = 3 | | "idProduct" = 36886 | | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | | "bInterfaceSubClass" = 0 | | "bConfigurationValue" = 1 | | "locationID" = 34734080 | | "USB Product Name" = "TETRA PEI interface" | | "bInterfaceProtocol" = 0 | | "iInterface" = 0 | | "bAlternateSetting" = 0 | | "idVendor" = 3245 | | "bInterfaceNumber" = 0 | | "bInterfaceClass" = 255 | | "bNumEndpoints" = 2 | | } | | | +-o lghub_agent <class AppleUSBHostInterfaceUserClient, id 0x100002988, !registered, !matched, active, busy 0, retain 6> | { | "UsbUserClientBufferStatistics" = {"IOMemoryDescriptor"=0,"IOBufferMemoryDescriptor"=0,"IOSubMemoryDescriptor"=0} | "IOUserClientCreator" = "pid 1438, lghub_agent" | "UsbUserClientBufferAllocations" = {"Bytes"=0,"Descriptors"=0} | "IOUserClientDefaultLocking" = Yes | } | +-o IOUSBHostInterface@1 <class IOUSBHostInterface, id 0x100002987, registered, matched, active, busy 0 (5 ms), retain 9> | { | "USBPortType" = 0 | "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "USB Vendor Name" = "Motorola Solutions, Inc." | "bcdDevice" = 9238 | "USBSpeed" = 3 | "idProduct" = 36886 | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | "bInterfaceSubClass" = 0 | "bConfigurationValue" = 1 | "locationID" = 34734080 | "USB Product Name" = "TETRA PEI interface" | "bInterfaceProtocol" = 0 | "iInterface" = 0 | "bAlternateSetting" = 0 | "idVendor" = 3245 | "bInterfaceNumber" = 1 | "bInterfaceClass" = 255 | "bNumEndpoints" = 2 | } | +-o lghub_agent <class AppleUSBHostInterfaceUserClient, id 0x10000298a, !registered, !matched, active, busy 0, retain 6> { "UsbUserClientBufferStatistics" = {"IOMemoryDescriptor"=0,"IOBufferMemoryDescriptor"=0,"IOSubMemoryDescriptor"=0} "IOUserClientCreator" = "pid 1438, lghub_agent" "UsbUserClientBufferAllocations" = {"Bytes"=0,"Descriptors"=0} "IOUserClientDefaultLocking" = Yes } more details in my comment.
6
0
663
Mar ’26
DriverKit IOUserSerial Driver
Hello everyone. After a lot of research and some tests from various sources, I have actually built a small SerialDriverKit IOUserSerial driver. Unfortunately, the documentation on the official sites is tight-lipped and very thin. At least I have a running driver instance. Now my request and question: Can anyone give me a tip on how to get the data from the serial client? I have already called IOUserSerial::ConnectQueues(...) in the IOUserSerial::Start() method and I got the IOMemoryDescriptors for interrupt, RX and TX to my driver instance. I tried to get access to the memory in the method IOUserSerial::TxDataAvailable() with IOMemoryDescriptor::CreateMapping(...). Unfortunately, no data is coming in. It's always 0x00. Here is the OS log: kernel: (org.eof.tools.VSPDriver.dext) kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] init called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] constructor called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] start called. kernel: (org.eof.tools.VSPDriver.dext) IOUserSerial::: 40 0x600000da4058 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] Start called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] Connect INT/RX/TX buffer. kernel: (org.eof.tools.VSPDriver.dext) IOUserSerial::: 59 0x600000da4058 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] prepare TCP socket. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] driver started successfully. kernel: DK: VSPDriver-0x100000753::start(IOUserResources-0x100000116) ok ... ... some client serial setup stuff ... kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 ==&gt;0 kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 &lt;== kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 locklevel = 1 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] HwResetFIFO called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] HwResetFIFO called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] HwResetFIFO: tx=0 rx=1 kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 ==&gt;0 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] TxDataAvailable called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: address=0x104c22000 length=16384 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: debug TX buffer kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00
20
1
1.7k
Nov ’25
FTDI USB-serial driver on iPadOS
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
1
0
712
Oct ’25
USBSendSetLineCoding failing in DeviceRequest with error code 0xe0005000
Hi, This is the code snippet in my driver for an usb uart device. I am trying to call standard cdc-acm command to set the Line Coding in the device, but fails with this error: "USBSendSetLineCoding - Failed : 0xe0005000, bytes transferred: 0" I guess the USB device is returning this error due to incorrect buffer or format. There is no proper documentation on how to use IOMemoryDescriptor when the data has to be passed down in a buffer to the usb stack. (IOUSBHostInterface->DeviceRequest()) Can anyone please point out what is wrong with this code and suggest a right method? void MyDriver::USBSendSetLineCoding(uint32_t BaudRate, uint8_t StopBits, uint8_t TX_Parity, uint8_t CharLength) { kern_return_t ret = kIOReturnSuccess; LineCoding *lineParms; uint16_t lcLen = sizeof(LineCoding)-1; lineParms = (LineCoding *)IOMalloc(lcLen); if (!lineParms) { MyDebugLog("USBSendSetLineCoding - allocate lineParms failed"); return; } bzero(lineParms, lcLen); lineParms->bCharFormat = StopBits - 2; lineParms->bParityType = TX_Parity - 1; lineParms->bDataBits = CharLength; OSSwapBigToHostInt32(BaudRate); lineParms->dwDTERate = BaudRate; IOBufferMemoryDescriptor* bufferDescriptor = nullptr; _controlInterface->CreateIOBuffer(kIOMemoryDirectionOut, lcLen, &bufferDescriptor); IOMemoryMap *map = nullptr; bufferDescriptor->CreateMapping(kIOMemoryMapReadOnly, 0, 0, 0, 0, &map); if(map == nullptr) { MyDebugLog("USBSendSetLineCoding - Failed to map memory in CreateMapping\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); return; } uint64_t ptr = map->GetAddress(); if(!ptr) { MyDebugLog("USBSendSetLineCoding - Failed to get Memory Address\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); map->release(); return; } memcpy(&ptr, lineParms, lcLen); uint8_t bmRequestType = kIOUSBDeviceRequestDirectionOut | kIOUSBDeviceRequestTypeClass | kIOUSBDeviceRequestRecipientInterface; uint16_t wValue = 0; uint16_t wIndex = _bControlInterfaceNumber; uint16_t bytesTransferred = 0; ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000); IOFree(lineParms, lcLen); map->release(); bufferDescriptor->release(); if (ret != kIOReturnSuccess) { MyDebugLog("USBSendSetLineCoding - Failed : 0x%x, bytes transferred: %d\n", ret, bytesTransferred); return; } return; } I am able to call DeviceRequest() successfully on the same interface for any other setting that requires no data buffer, such as, "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSEND_BREAK, wValue, wIndex, 0, NULL, &bytesTransferred, 1000);" So I think the "bufferDescriptor" is not properly created or the data is not copied correctly in this function for the failure. "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000);" Any help is very much appreciated. Thanks in advance.
3
0
1.1k
Aug ’25
Which IOUserClient entitlements are really required?
Hello @all I'm develop a DriverKit driver extension and without entitlement checks by OS everything runs fine. But if the entitlements check is enabled in the NVRAM then I get an error due connecting my IOUserClient instance. Which entitlements are really and exactly required for my driver? My driver contains: one IOUserClient instance and multiple IOUserSerial instances The bundle identifier of the driver ist: org.eof.tools.VSPDriver The bundle identifier of the client app org.eof.tools.VSPInstall My entire source code is available on GitHub if any one want to dive deep in :) kernel[0:5107] () [VSPDriver]: NewUserClient called. kernel[0:5107] () [VSPDriver]: CreateUserClient: create VSP user client from Info.plist. kernel[0:5107] () [VSPUserClient]: init called. kernel[0:5107] () [VSPUserClient]: init finished. kernel[0:5107] () [VSPDriver]: CreateUserClient: check VSPUserClient type. kernel[0:5107] () [VSPDriver]: CreateUserClient: success. kernel[0:5107] () [VSPDriver]: NewUserClient finished. kernel[0:5107] () [VSPUserClient]: Start: called. kernel[0:5107] () [VSPUserClient]: User client successfully started. kernel[0:389f] DK: VSPUserClient-0x100001127:UC failed userclient-access check, needed bundle ID org.eof.tools.VSPDriver kernel[0:389f] DK: VSPUserClient-0x100001127:UC entitlements check failed kernel[0:5107] () [VSPUserClient]: Stop called. kernel[0:5107] () [VSPUserClient]: User client successfully removed. kernel[0:5107] () [VSPUserClient]: free called. Here my drivers entitlement file: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.family.serial</key> <true/> </dict> </plist> Here my drivers Info.plist file <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>NSHumanReadableCopyright</key> <string>Copyright © 2025 by EoF Software Labs</string> <key>OSBundleUsageDescription</key> <string>Provide virtual serial port</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-any-userclient-access</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.system-extension.redistributable</key> <true/> <key>OSBundleLibraries</key> <dict> <key>com.apple.iokit.IOSerialFamily</key> <string>1.0</string> </dict> <key>IOKitPersonalities</key> <dict> <key>VSPDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOUserResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOProbeScore</key> <integer>0</integer> <key>IOClass</key> <string>IOUserService</string> <key>IOUserClass</key> <string>VSPDriver</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>UserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>VSPUserClient</string> </dict> <key>SerialPortProperties</key> <dict> <key>CFBundleIdentifierKernel</key> <string>com.apple.driver.driverkit.serial</string> <key>IOProviderClass</key> <string>IOSerialStreamSync</string> <key>IOClass</key> <string>IOUserSerial</string> <key>IOUserClass</key> <string>VSPSerialPort</string> <key>HiddenPort</key> <false/> <key>IOTTYBaseName</key> <string>vsp</string> <key>IOTTYSuffix</key> <string>0</string> </dict> </dict> </dict> </dict> </plist> Here the entitlements of the client app <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.shared-with-you</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>$(TeamIdentifierPrefix).org.eof.apps</string> </array> </dict> </plist> Here the Info.plist of the client app: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>LSMinimumSystemVersion</key> <string>$(MACOSX_DEPLOYMENT_TARGET)</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.install</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.developer.system-extension.uninstall</key> <true/> <key>com.apple.developer.driverkit.userclient-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.private.driverkit.driver-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.security.temporary-exception.iokit-user-client-class</key> <array> <string>IOUserUserClient</string> </array> </dict> </plist>
2
0
781
Mar ’25
FTDI Serial Support on iOS18 with USB-C iPhones
I read that iPadOS supports driverkit, and, presumably, the same serial FTDI UARTs as macOS. Has this been migrated to USB-C iPhones on iOS 18? After some searching, the developer doc is not clear, and web responses are contradictory. We are currently using it for a wired sensor option of our BlueTooth HR sensor. When it is used in wired config, the radios are turned off. This is important to some of our customers. Since Lightning MFI sensors are being discontinued with Apple killing Lightning, we would love to have an alternative for iOS. -- Harald
2
1
804
Mar ’25
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.2k
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
845
Feb ’25
How to implement macOS sleep and wake for USB serial drivers using USBSerialDriverKit.
Development environment: Xcode Version 15.1 (15C65), macOS 14.2.1 (23C71) Run-time configuration: macOS 14.2.1 (23C71) DESCRIPTION OF PROBLEM 1.The device supports sleep and wake functionality, and sleep/wake can be achieved on both Linux and Windows. 2.Does macOS's USBSerialDriverKit support sleep and wake? If so, how can I implement it? 3.Is it necessary to modify system permissions on macOS to use a USB serial device for sleep and wake functionality? STEPS TO REPRODUCE I don't know how macOS performs power management for serial devices. The sleep wake function fails to pass the test on macOS
1
0
827
Sep ’24
DriverKit architecture for USB-C device and iPad dext
I am attempting to communicate over serial with a USB-C device and an M-Series iPad. I have proven the device to communicate as expected (baud rate, parity, etc) via a Swift app on Mac using a third party library (IOKit) that utilizes the "AppleUSBACM (v5.0.0)" driver on macOS. I am looking to recreate this communication via iPadOS and a custom DriverKit driver that provides this same interface. There is not an example from Apple for serial communication and DriverKit but there is a couple for communicating from an app to the dext, and for other networking examples. There are also other mentions in WWDC videos but they are incomplete and do not provide the needed structure. Communicating between a driver extension and a client app Connecting a network driver Bring your driver to iPad with DriverKit System Extensions and DriverKit My question revolves around architecture and how to set up a driver for these needs. I have gotten the examples to run and understand what is needed for entitlements and other local signing needs. But what I don't understand is if you need a basic setup similar to the "Communicating between a driver extension and a client app" where your base driver subclasses IOService and has two arms. One that subclasses IOUserclient and allows communication between the dext and your Swift app. And another arm that subclasses IOUserSerial or IOUserUSBSerial. I assume then that these two share buffers of memory set up by the base class that allows communication between the two. I have had little luck getting IOUserUSBSerial to compile and have made more progress on IOUserSerial. But when running that and with the supposed idVendor plist entry I am not getting that part of the dext to start or recognize when the USB device is plugged in. Long story short, I'm looking for a basic architecture or example reference to explain serial communication in DriverKit. Devices: Custom USB-C hardware that is CDC ACM compliant iPad Air 5th gen with M1 chip (iPadOS 17.2) M1 MBP (macOS 14.2.1)
1
2
1.9k
Mar ’24
DriverKit Support on USB-C iPhones
Hi @eskimo! With the introduction of USB-C ports on the newest iPhones, will there be any support for DriverKit (or USBSerialDriverKit 🤞) similar to the USB-C iPads? We are wanting to enable serial communication with a custom USB peripheral via the new USB-C port. Is this (or will this) be possible in any manor? Additionally, will this require MFi certification? Thanks!
13
4
3.3k
Mar ’24
Serial port communication from iOS app to device
Hello, We have a device that acts as a slave device and communicates with a master over data sent over a USB serial port over a wired connection. We are trying to develop an Application on iOS that will enable us to use the USB connection between iPhone and our device. Kindly suggest to us what is the way to achieve this. A few searches let us know that Apple's MFi program needs to be enrolled. Please let us know how this works and where could we find process for the same. I thank you in advance! Makarand
2
1
1.8k
Mar ’24
Using an existing driver with a USB serial chip with custom VID/PID
I am using a Silicon labs CP2102 chip. I have configured a custom USB VID and PID on the chip, and want to create a MacOs driver (or rather map this custom VID/PID to an existing driver) to make it accessible as a USB serial device from my Mac. Preferably I'd like to map my device to the com.apple.DriverKit-AppleUSBSLCOM.dext driver, but I think the generic USB serial driver (com.apple.DriverKit-AppleUSBSerial.dext) should work too. Silabs also has their own driver (com.silabs.cp210x.dext, downloadable from their web page), if for some reason it is easier to map to that than to one of the native drivers that could also work. Based on https://developer.apple.com/documentation/kernel/implementing_drivers_system_extensions_and_kexts#3616855 and https://developer.apple.com/documentation/driverkit/creating_a_driver_using_the_driverkit_sdk it should be possible to create a codeless dext, which just inherits from e.g. IOUserUSBSerial. I've tried both creating just a DriverKit driver and putting it under /Library/DriverExtensions/ and creating a (default) app and adding a DriverKit driver to it, and putting the app in my /Applications/ folder, but neither works for me. My driver implementation is just this: #include <USBSerialDriverKit/IOUserUSBSerial.iig> class MyDriver: public IOUserUSBSerial { }; and my IOKitPersonalities looks like this: <key>IOKitPersonalities</key> <dict> <key>MyDriver</key> <dict> <key>CFBundleIdentifier</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>IOClass</key> <string>IOUserUSBSerial</string> <key>IOMatchCategory</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>IOProviderClass</key> <string>IOUSBHostInterface</string> <key>IOUserClass</key> <string>MyDriver</string> <key>IOUserServerName</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>idProduct</key> <integer>(my custom PID, decimal value)</integer> <key>idVendor</key> <integer>(my custom VID, decimal value)</integer> </dict> </dict> I've disabled SIP and enabled developer mode (systemextensionsctl developer on), though I'm not sure if it's needed. I've scanned through the system logs and looked at the ioreg output. When I connect a CP2102 chip with default VID and PID, I can see that it maps to the native com.apple.DriverKit-AppleUSBSLCOM.dext driver. When I connect the same chip with my custom VID and PID, I don't see any trace of my driver being used. I can see it in the System Information app, but it doesn't map to my driver. I'm currently suspecting it is an Entitlements issue. In my app I have an Entitlements file, where I've added DriverKit USB Transport and DriverKit Serial Family. Do I need something like this for the driver target? There is no default Entitlements file there, but maybe I should create one? Or is there something else I'm missing? I've also noted one odd thing: When I install my app I can see a system log entry, complaining that "package type not SYSX" (for my driver). But I don't think it should be a SYSX package? It's currently specified as a DEXT package.
1
1
1.4k
Feb ’24
Protocol availability inconsistencies related to modern serial layers
I am currently writing a iPadOS application to act as a companion to the desktop version that controls a piece of hardware via a USB CDC serial connection. Due to modern iPads having USB-C ports for the last 2 years and the ability to attach certain USB devices via adaptors since the origin of the 30pin doc connector I would expect protocol availability to be fairly complete. So then why is it that the headers required to use USB CDC serial don't exist and if you make them yourself you need to use illegal symbols so you can't upload it to App Store connect. Where as USB CDC ethernet has full support along with Bluetooth RFCOMM (rs232 serial over bluetooth) and even USB MIDI given that midi is a superset of serial. So why isn't there a USB CDC serial kit/api/even just allowing a data stream to the TTY/CU port? If there is a way please tell me what it is and point me to the documentation.
11
0
6.5k
Dec ’23
Unable to link to or even find USBDriverKit for iPadOS
According to Apple's documentation USBDriverKit for iPadOS has been available since DriverKit 19 and the M1 iPad were released. However, using Xcode 15.0.1, I am unable to link to or even find USBDriverKit from within Xcode. Is the documentation incorrect? If not what do I need to do in order to access and leverage USBDriverKit? From what I've read, USBSerialDriverKit is not available. As I have a USB based serial device that I want to use from the iPad, the next obvious step is to write my own USB device extension using USBDriverKit as a provider. If you have experience with this and can definitively say whether or not what I'm attempting is even within the realm of possibility, please chime in. Thanks. -Michael
2
0
1.3k
Dec ’23
USB serial port not showing up after Monterey OS upgrade
Past 8-9 months we've been working on Arduino/ ESP32 with no issues, but after upgrading the OS the port stopped showing up under /dev/tty.cuserial. We tried to install the driver from Silicon Labs CP210x VCP Driver for MacOS(installed w/ no issues) but in the system information, we are seeing the S/w is sitting under disabled S/w list com.silabs.driver.CP210xVCPDriver: unknown. How can we fix this and get it out of disabled S/w?
2
0
2.2k
Feb ’23
USB communication with a pre-OS system
Hello everyone, We're working on an iOS app that needs to connect to a non-Apple pre-operating system using USB for serial communication. Our goal is to send and receive data between an iPhone and a UEFI-based system directly over USB. We've created a proof of concept using the USBMux protocol, which let us exchange basic messages. However, we're running into problems with the USB endpoint setup. In some cases, the USB communication doesn't start or stay connected. Since this is for a pre-boot environment, it might not fit into the usual iOS USB communication frameworks. We're looking for help with the following: Any guidance or documentation on setting up USB serial communication between an iPhone and a non-Apple pre-boot system Information on system APIs, frameworks, or protocols that iOS supports for direct USB communication in this scenario Access to official USBMux documentation or specs to understand its limitations and capabilities better Whether this communication requires MFi certification or if there are other Apple-supported interfaces we can use Thank you!
Replies
1
Boosts
0
Views
562
Activity
2w
Can't get USBSerialDriverKit driver loaded
I am writing a DriverKit driver for the first that uses the USBSerialDriverKit. The driver its purpose is to expose the device as serial interface (/dev/cu.tetra-pei0 or something like this). My problem: I don't see any logs from that driver in the console and I tried like 40 different approaches and checked everything. The last message I see is that the driver get successfully added to the system it is in the list of active and enabled system driver extensions but when I plug the device in none of my logs appear and it doesn't show up in ioreg. So without my driver the target device looks like this: +-o TETRA PEI interface@02120000 <class IOUSBHostDevice, id 0x10000297d, registered, matched, active, busy 0 (13 ms), retain 30> | { | "sessionID" = 268696051410 | "USBSpeed" = 3 | "UsbLinkSpeed" = 480000000 | "idProduct" = 36886 | "iManufacturer" = 1 | "bDeviceClass" = 0 | "IOPowerManagement" = {"PowerOverrideOn"=Yes,"DevicePowerState"=2,"CurrentPowerState"=2,"CapabilityFlags"=32768,"MaxPowerState"=2,"DriverPowerState"=0} | "bcdDevice" = 9238 | "bMaxPacketSize0" = 64 | "iProduct" = 2 | "iSerialNumber" = 0 | "bNumConfigurations" = 1 | "UsbDeviceSignature" = <ad0c16901624000000ff0000> | "USB Product Name" = "TETRA PEI interface" | "locationID" = 34734080 | "bDeviceSubClass" = 0 | "bcdUSB" = 512 | "USB Address" = 6 | "kUSBCurrentConfiguration" = 1 | "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "UsbPowerSinkAllocation" = 500 | "bDeviceProtocol" = 0 | "USBPortType" = 0 | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | "USB Vendor Name" = "Motorola Solutions, Inc." | "Device Speed" = 2 | "idVendor" = 3245 | "kUSBProductString" = "TETRA PEI interface" | "kUSBAddress" = 6 | "kUSBVendorString" = "Motorola Solutions, Inc." | } | +-o AppleUSBHostCompositeDevice <class AppleUSBHostCompositeDevice, id 0x100002982, !registered, !matched, active, busy 0, retain 5> | { | "IOProbeScore" = 50000 | "CFBundleIdentifier" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "IOProviderClass" = "IOUSBHostDevice" | "IOClass" = "AppleUSBHostCompositeDevice" | "IOPersonalityPublisher" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "bDeviceSubClass" = 0 | "CFBundleIdentifierKernel" = "com.apple.driver.usb.AppleUSBHostCompositeDevice" | "IOMatchedAtBoot" = Yes | "IOMatchCategory" = "IODefaultMatchCategory" | "IOPrimaryDriverTerminateOptions" = Yes | "bDeviceClass" = 0 | } | +-o lghub_agent <class AppleUSBHostDeviceUserClient, id 0x100002983, !registered, !matched, active, busy 0, retain 7> | { | "IOUserClientCreator" = "pid 1438, lghub_agent" | "IOUserClientDefaultLocking" = Yes | } | +-o IOUSBHostInterface@0 <class IOUSBHostInterface, id 0x100002986, registered, matched, active, busy 0 (5 ms), retain 9> | | { | | "USBPortType" = 0 | | "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | | "USB Vendor Name" = "Motorola Solutions, Inc." | | "bcdDevice" = 9238 | | "USBSpeed" = 3 | | "idProduct" = 36886 | | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | | "bInterfaceSubClass" = 0 | | "bConfigurationValue" = 1 | | "locationID" = 34734080 | | "USB Product Name" = "TETRA PEI interface" | | "bInterfaceProtocol" = 0 | | "iInterface" = 0 | | "bAlternateSetting" = 0 | | "idVendor" = 3245 | | "bInterfaceNumber" = 0 | | "bInterfaceClass" = 255 | | "bNumEndpoints" = 2 | | } | | | +-o lghub_agent <class AppleUSBHostInterfaceUserClient, id 0x100002988, !registered, !matched, active, busy 0, retain 6> | { | "UsbUserClientBufferStatistics" = {"IOMemoryDescriptor"=0,"IOBufferMemoryDescriptor"=0,"IOSubMemoryDescriptor"=0} | "IOUserClientCreator" = "pid 1438, lghub_agent" | "UsbUserClientBufferAllocations" = {"Bytes"=0,"Descriptors"=0} | "IOUserClientDefaultLocking" = Yes | } | +-o IOUSBHostInterface@1 <class IOUSBHostInterface, id 0x100002987, registered, matched, active, busy 0 (5 ms), retain 9> | { | "USBPortType" = 0 | "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "USB Vendor Name" = "Motorola Solutions, Inc." | "bcdDevice" = 9238 | "USBSpeed" = 3 | "idProduct" = 36886 | "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb")) | "bInterfaceSubClass" = 0 | "bConfigurationValue" = 1 | "locationID" = 34734080 | "USB Product Name" = "TETRA PEI interface" | "bInterfaceProtocol" = 0 | "iInterface" = 0 | "bAlternateSetting" = 0 | "idVendor" = 3245 | "bInterfaceNumber" = 1 | "bInterfaceClass" = 255 | "bNumEndpoints" = 2 | } | +-o lghub_agent <class AppleUSBHostInterfaceUserClient, id 0x10000298a, !registered, !matched, active, busy 0, retain 6> { "UsbUserClientBufferStatistics" = {"IOMemoryDescriptor"=0,"IOBufferMemoryDescriptor"=0,"IOSubMemoryDescriptor"=0} "IOUserClientCreator" = "pid 1438, lghub_agent" "UsbUserClientBufferAllocations" = {"Bytes"=0,"Descriptors"=0} "IOUserClientDefaultLocking" = Yes } more details in my comment.
Replies
6
Boosts
0
Views
663
Activity
Mar ’26
How to get a IOSerialBSDClient attached?
I have a driver extending IOUserUSBSerial and I want the device to show up as /dev/tty.mycustombasename-123 and /dev/cu. respectively. How can I achieve that?
Replies
1
Boosts
0
Views
573
Activity
Feb ’26
DriverKit IOUserSerial Driver
Hello everyone. After a lot of research and some tests from various sources, I have actually built a small SerialDriverKit IOUserSerial driver. Unfortunately, the documentation on the official sites is tight-lipped and very thin. At least I have a running driver instance. Now my request and question: Can anyone give me a tip on how to get the data from the serial client? I have already called IOUserSerial::ConnectQueues(...) in the IOUserSerial::Start() method and I got the IOMemoryDescriptors for interrupt, RX and TX to my driver instance. I tried to get access to the memory in the method IOUserSerial::TxDataAvailable() with IOMemoryDescriptor::CreateMapping(...). Unfortunately, no data is coming in. It's always 0x00. Here is the OS log: kernel: (org.eof.tools.VSPDriver.dext) kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] init called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] constructor called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] start called. kernel: (org.eof.tools.VSPDriver.dext) IOUserSerial::: 40 0x600000da4058 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] Start called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] Connect INT/RX/TX buffer. kernel: (org.eof.tools.VSPDriver.dext) IOUserSerial::: 59 0x600000da4058 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] prepare TCP socket. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] driver started successfully. kernel: DK: VSPDriver-0x100000753::start(IOUserResources-0x100000116) ok ... ... some client serial setup stuff ... kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 ==&gt;0 kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 &lt;== kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 locklevel = 1 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] HwResetFIFO called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] HwResetFIFO called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] HwResetFIFO: tx=0 rx=1 kernel: (IOUserSerial) IOUserSerial::hwResetFIFO: 1076 ==&gt;0 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriver] TxDataAvailable called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable called. kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: address=0x104c22000 length=16384 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: debug TX buffer kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00 kernel: (org.eof.tools.VSPDriver.dext) [VSPDriverPrivate] TxDataAvailable: TX&gt; 0x00
Replies
20
Boosts
1
Views
1.7k
Activity
Nov ’25
FTDI USB-serial driver on iPadOS
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
Replies
1
Boosts
0
Views
712
Activity
Oct ’25
USBSendSetLineCoding failing in DeviceRequest with error code 0xe0005000
Hi, This is the code snippet in my driver for an usb uart device. I am trying to call standard cdc-acm command to set the Line Coding in the device, but fails with this error: "USBSendSetLineCoding - Failed : 0xe0005000, bytes transferred: 0" I guess the USB device is returning this error due to incorrect buffer or format. There is no proper documentation on how to use IOMemoryDescriptor when the data has to be passed down in a buffer to the usb stack. (IOUSBHostInterface->DeviceRequest()) Can anyone please point out what is wrong with this code and suggest a right method? void MyDriver::USBSendSetLineCoding(uint32_t BaudRate, uint8_t StopBits, uint8_t TX_Parity, uint8_t CharLength) { kern_return_t ret = kIOReturnSuccess; LineCoding *lineParms; uint16_t lcLen = sizeof(LineCoding)-1; lineParms = (LineCoding *)IOMalloc(lcLen); if (!lineParms) { MyDebugLog("USBSendSetLineCoding - allocate lineParms failed"); return; } bzero(lineParms, lcLen); lineParms->bCharFormat = StopBits - 2; lineParms->bParityType = TX_Parity - 1; lineParms->bDataBits = CharLength; OSSwapBigToHostInt32(BaudRate); lineParms->dwDTERate = BaudRate; IOBufferMemoryDescriptor* bufferDescriptor = nullptr; _controlInterface->CreateIOBuffer(kIOMemoryDirectionOut, lcLen, &bufferDescriptor); IOMemoryMap *map = nullptr; bufferDescriptor->CreateMapping(kIOMemoryMapReadOnly, 0, 0, 0, 0, &map); if(map == nullptr) { MyDebugLog("USBSendSetLineCoding - Failed to map memory in CreateMapping\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); return; } uint64_t ptr = map->GetAddress(); if(!ptr) { MyDebugLog("USBSendSetLineCoding - Failed to get Memory Address\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); map->release(); return; } memcpy(&ptr, lineParms, lcLen); uint8_t bmRequestType = kIOUSBDeviceRequestDirectionOut | kIOUSBDeviceRequestTypeClass | kIOUSBDeviceRequestRecipientInterface; uint16_t wValue = 0; uint16_t wIndex = _bControlInterfaceNumber; uint16_t bytesTransferred = 0; ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000); IOFree(lineParms, lcLen); map->release(); bufferDescriptor->release(); if (ret != kIOReturnSuccess) { MyDebugLog("USBSendSetLineCoding - Failed : 0x%x, bytes transferred: %d\n", ret, bytesTransferred); return; } return; } I am able to call DeviceRequest() successfully on the same interface for any other setting that requires no data buffer, such as, "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSEND_BREAK, wValue, wIndex, 0, NULL, &bytesTransferred, 1000);" So I think the "bufferDescriptor" is not properly created or the data is not copied correctly in this function for the failure. "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000);" Any help is very much appreciated. Thanks in advance.
Replies
3
Boosts
0
Views
1.1k
Activity
Aug ’25
Which IOUserClient entitlements are really required?
Hello @all I'm develop a DriverKit driver extension and without entitlement checks by OS everything runs fine. But if the entitlements check is enabled in the NVRAM then I get an error due connecting my IOUserClient instance. Which entitlements are really and exactly required for my driver? My driver contains: one IOUserClient instance and multiple IOUserSerial instances The bundle identifier of the driver ist: org.eof.tools.VSPDriver The bundle identifier of the client app org.eof.tools.VSPInstall My entire source code is available on GitHub if any one want to dive deep in :) kernel[0:5107] () [VSPDriver]: NewUserClient called. kernel[0:5107] () [VSPDriver]: CreateUserClient: create VSP user client from Info.plist. kernel[0:5107] () [VSPUserClient]: init called. kernel[0:5107] () [VSPUserClient]: init finished. kernel[0:5107] () [VSPDriver]: CreateUserClient: check VSPUserClient type. kernel[0:5107] () [VSPDriver]: CreateUserClient: success. kernel[0:5107] () [VSPDriver]: NewUserClient finished. kernel[0:5107] () [VSPUserClient]: Start: called. kernel[0:5107] () [VSPUserClient]: User client successfully started. kernel[0:389f] DK: VSPUserClient-0x100001127:UC failed userclient-access check, needed bundle ID org.eof.tools.VSPDriver kernel[0:389f] DK: VSPUserClient-0x100001127:UC entitlements check failed kernel[0:5107] () [VSPUserClient]: Stop called. kernel[0:5107] () [VSPUserClient]: User client successfully removed. kernel[0:5107] () [VSPUserClient]: free called. Here my drivers entitlement file: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.family.serial</key> <true/> </dict> </plist> Here my drivers Info.plist file <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>NSHumanReadableCopyright</key> <string>Copyright © 2025 by EoF Software Labs</string> <key>OSBundleUsageDescription</key> <string>Provide virtual serial port</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-any-userclient-access</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.system-extension.redistributable</key> <true/> <key>OSBundleLibraries</key> <dict> <key>com.apple.iokit.IOSerialFamily</key> <string>1.0</string> </dict> <key>IOKitPersonalities</key> <dict> <key>VSPDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOUserResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOProbeScore</key> <integer>0</integer> <key>IOClass</key> <string>IOUserService</string> <key>IOUserClass</key> <string>VSPDriver</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>UserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>VSPUserClient</string> </dict> <key>SerialPortProperties</key> <dict> <key>CFBundleIdentifierKernel</key> <string>com.apple.driver.driverkit.serial</string> <key>IOProviderClass</key> <string>IOSerialStreamSync</string> <key>IOClass</key> <string>IOUserSerial</string> <key>IOUserClass</key> <string>VSPSerialPort</string> <key>HiddenPort</key> <false/> <key>IOTTYBaseName</key> <string>vsp</string> <key>IOTTYSuffix</key> <string>0</string> </dict> </dict> </dict> </dict> </plist> Here the entitlements of the client app <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.allow-third-party-userclients</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.shared-with-you</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.security.application-groups</key> <array> <string>$(TeamIdentifierPrefix).org.eof.apps</string> </array> </dict> </plist> Here the Info.plist of the client app: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1</string> <key>LSMinimumSystemVersion</key> <string>$(MACOSX_DEPLOYMENT_TARGET)</string> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.install</key> <true/> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.developer.system-extension.uninstall</key> <true/> <key>com.apple.developer.driverkit.userclient-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.private.driverkit.driver-access</key> <array> <string>VSPDriver</string> </array> <key>com.apple.security.temporary-exception.iokit-user-client-class</key> <array> <string>IOUserUserClient</string> </array> </dict> </plist>
Replies
2
Boosts
0
Views
781
Activity
Mar ’25
FTDI Serial Support on iOS18 with USB-C iPhones
I read that iPadOS supports driverkit, and, presumably, the same serial FTDI UARTs as macOS. Has this been migrated to USB-C iPhones on iOS 18? After some searching, the developer doc is not clear, and web responses are contradictory. We are currently using it for a wired sensor option of our BlueTooth HR sensor. When it is used in wired config, the radios are turned off. This is important to some of our customers. Since Lightning MFI sensors are being discontinued with Apple killing Lightning, we would love to have an alternative for iOS. -- Harald
Replies
2
Boosts
1
Views
804
Activity
Mar ’25
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; }
Replies
1
Boosts
0
Views
2.2k
Activity
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?
Replies
1
Boosts
0
Views
845
Activity
Feb ’25
How to implement macOS sleep and wake for USB serial drivers using USBSerialDriverKit.
Development environment: Xcode Version 15.1 (15C65), macOS 14.2.1 (23C71) Run-time configuration: macOS 14.2.1 (23C71) DESCRIPTION OF PROBLEM 1.The device supports sleep and wake functionality, and sleep/wake can be achieved on both Linux and Windows. 2.Does macOS's USBSerialDriverKit support sleep and wake? If so, how can I implement it? 3.Is it necessary to modify system permissions on macOS to use a USB serial device for sleep and wake functionality? STEPS TO REPRODUCE I don't know how macOS performs power management for serial devices. The sleep wake function fails to pass the test on macOS
Replies
1
Boosts
0
Views
827
Activity
Sep ’24
DriverKit architecture for USB-C device and iPad dext
I am attempting to communicate over serial with a USB-C device and an M-Series iPad. I have proven the device to communicate as expected (baud rate, parity, etc) via a Swift app on Mac using a third party library (IOKit) that utilizes the "AppleUSBACM (v5.0.0)" driver on macOS. I am looking to recreate this communication via iPadOS and a custom DriverKit driver that provides this same interface. There is not an example from Apple for serial communication and DriverKit but there is a couple for communicating from an app to the dext, and for other networking examples. There are also other mentions in WWDC videos but they are incomplete and do not provide the needed structure. Communicating between a driver extension and a client app Connecting a network driver Bring your driver to iPad with DriverKit System Extensions and DriverKit My question revolves around architecture and how to set up a driver for these needs. I have gotten the examples to run and understand what is needed for entitlements and other local signing needs. But what I don't understand is if you need a basic setup similar to the "Communicating between a driver extension and a client app" where your base driver subclasses IOService and has two arms. One that subclasses IOUserclient and allows communication between the dext and your Swift app. And another arm that subclasses IOUserSerial or IOUserUSBSerial. I assume then that these two share buffers of memory set up by the base class that allows communication between the two. I have had little luck getting IOUserUSBSerial to compile and have made more progress on IOUserSerial. But when running that and with the supposed idVendor plist entry I am not getting that part of the dext to start or recognize when the USB device is plugged in. Long story short, I'm looking for a basic architecture or example reference to explain serial communication in DriverKit. Devices: Custom USB-C hardware that is CDC ACM compliant iPad Air 5th gen with M1 chip (iPadOS 17.2) M1 MBP (macOS 14.2.1)
Replies
1
Boosts
2
Views
1.9k
Activity
Mar ’24
DriverKit Support on USB-C iPhones
Hi @eskimo! With the introduction of USB-C ports on the newest iPhones, will there be any support for DriverKit (or USBSerialDriverKit 🤞) similar to the USB-C iPads? We are wanting to enable serial communication with a custom USB peripheral via the new USB-C port. Is this (or will this) be possible in any manor? Additionally, will this require MFi certification? Thanks!
Replies
13
Boosts
4
Views
3.3k
Activity
Mar ’24
Serial port communication from iOS app to device
Hello, We have a device that acts as a slave device and communicates with a master over data sent over a USB serial port over a wired connection. We are trying to develop an Application on iOS that will enable us to use the USB connection between iPhone and our device. Kindly suggest to us what is the way to achieve this. A few searches let us know that Apple's MFi program needs to be enrolled. Please let us know how this works and where could we find process for the same. I thank you in advance! Makarand
Replies
2
Boosts
1
Views
1.8k
Activity
Mar ’24
Using an existing driver with a USB serial chip with custom VID/PID
I am using a Silicon labs CP2102 chip. I have configured a custom USB VID and PID on the chip, and want to create a MacOs driver (or rather map this custom VID/PID to an existing driver) to make it accessible as a USB serial device from my Mac. Preferably I'd like to map my device to the com.apple.DriverKit-AppleUSBSLCOM.dext driver, but I think the generic USB serial driver (com.apple.DriverKit-AppleUSBSerial.dext) should work too. Silabs also has their own driver (com.silabs.cp210x.dext, downloadable from their web page), if for some reason it is easier to map to that than to one of the native drivers that could also work. Based on https://developer.apple.com/documentation/kernel/implementing_drivers_system_extensions_and_kexts#3616855 and https://developer.apple.com/documentation/driverkit/creating_a_driver_using_the_driverkit_sdk it should be possible to create a codeless dext, which just inherits from e.g. IOUserUSBSerial. I've tried both creating just a DriverKit driver and putting it under /Library/DriverExtensions/ and creating a (default) app and adding a DriverKit driver to it, and putting the app in my /Applications/ folder, but neither works for me. My driver implementation is just this: #include <USBSerialDriverKit/IOUserUSBSerial.iig> class MyDriver: public IOUserUSBSerial { }; and my IOKitPersonalities looks like this: <key>IOKitPersonalities</key> <dict> <key>MyDriver</key> <dict> <key>CFBundleIdentifier</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>IOClass</key> <string>IOUserUSBSerial</string> <key>IOMatchCategory</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>IOProviderClass</key> <string>IOUSBHostInterface</string> <key>IOUserClass</key> <string>MyDriver</string> <key>IOUserServerName</key> <string>com.mydriver.MyDriverApp.MyDriver</string> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>idProduct</key> <integer>(my custom PID, decimal value)</integer> <key>idVendor</key> <integer>(my custom VID, decimal value)</integer> </dict> </dict> I've disabled SIP and enabled developer mode (systemextensionsctl developer on), though I'm not sure if it's needed. I've scanned through the system logs and looked at the ioreg output. When I connect a CP2102 chip with default VID and PID, I can see that it maps to the native com.apple.DriverKit-AppleUSBSLCOM.dext driver. When I connect the same chip with my custom VID and PID, I don't see any trace of my driver being used. I can see it in the System Information app, but it doesn't map to my driver. I'm currently suspecting it is an Entitlements issue. In my app I have an Entitlements file, where I've added DriverKit USB Transport and DriverKit Serial Family. Do I need something like this for the driver target? There is no default Entitlements file there, but maybe I should create one? Or is there something else I'm missing? I've also noted one odd thing: When I install my app I can see a system log entry, complaining that "package type not SYSX" (for my driver). But I don't think it should be a SYSX package? It's currently specified as a DEXT package.
Replies
1
Boosts
1
Views
1.4k
Activity
Feb ’24
Protocol availability inconsistencies related to modern serial layers
I am currently writing a iPadOS application to act as a companion to the desktop version that controls a piece of hardware via a USB CDC serial connection. Due to modern iPads having USB-C ports for the last 2 years and the ability to attach certain USB devices via adaptors since the origin of the 30pin doc connector I would expect protocol availability to be fairly complete. So then why is it that the headers required to use USB CDC serial don't exist and if you make them yourself you need to use illegal symbols so you can't upload it to App Store connect. Where as USB CDC ethernet has full support along with Bluetooth RFCOMM (rs232 serial over bluetooth) and even USB MIDI given that midi is a superset of serial. So why isn't there a USB CDC serial kit/api/even just allowing a data stream to the TTY/CU port? If there is a way please tell me what it is and point me to the documentation.
Replies
11
Boosts
0
Views
6.5k
Activity
Dec ’23
Unable to link to or even find USBDriverKit for iPadOS
According to Apple's documentation USBDriverKit for iPadOS has been available since DriverKit 19 and the M1 iPad were released. However, using Xcode 15.0.1, I am unable to link to or even find USBDriverKit from within Xcode. Is the documentation incorrect? If not what do I need to do in order to access and leverage USBDriverKit? From what I've read, USBSerialDriverKit is not available. As I have a USB based serial device that I want to use from the iPad, the next obvious step is to write my own USB device extension using USBDriverKit as a provider. If you have experience with this and can definitively say whether or not what I'm attempting is even within the realm of possibility, please chime in. Thanks. -Michael
Replies
2
Boosts
0
Views
1.3k
Activity
Dec ’23
How to use SWIFTUI and SWIFT language to call com port?
I can't find any useful help about the content described in the title on Apple's official website. The relevant help on its official website is almost all based on OC language, and even their sample programs are written in OC language. Can I ask if SWIFT can only use the COM port through the bridge of OC-SWIFT?
Replies
1
Boosts
0
Views
1.9k
Activity
Dec ’23
Streaming from an BT SPP device
I am trying to read/write from/to a Bluetooth device that has SPP(Serial port profile) from Python in Mac OSX. Could you recommend any good library to do so? I have been trying for long but the solutions I have tried does not work. Any help would be greatly appreciated!
Replies
2
Boosts
0
Views
793
Activity
Oct ’23
USB serial port not showing up after Monterey OS upgrade
Past 8-9 months we've been working on Arduino/ ESP32 with no issues, but after upgrading the OS the port stopped showing up under /dev/tty.cuserial. We tried to install the driver from Silicon Labs CP210x VCP Driver for MacOS(installed w/ no issues) but in the system information, we are seeing the S/w is sitting under disabled S/w list com.silabs.driver.CP210xVCPDriver: unknown. How can we fix this and get it out of disabled S/w?
Replies
2
Boosts
0
Views
2.2k
Activity
Feb ’23