Hello,
We are experiencing some issues with our USB accessory unexpectedly charging the iOS device it is connected with only when the iOS device supports USB-C and is on iOS 18+
The following is a description of the discrepancy we note between iOS versions:
After performing a USB Role switch, our Accessory becomes a typical USB Device and the Apple device becomes the USB host.
with iOS 17:
The Accessory then sends a PowerSourceUpdate message to the iOS 17 device via iAP2 protocol. Apple device has a USB Type C Connector. *
We are specifying:
AvailableCurrentForDevice = 0 mA
DeviceBatteryShouldChargeIfPowerIsPresent = 1.
Three observations:
iPad Battery Settings page - we observe 'Last charged to…' (indicating no charging)
On the Lumify App running (iOS 17), we observe that UIKit.current.batteryState indicated 'Not charging'
Battery icon on top right of the screen indicates 'No Charging'
with iOS 18:
The same Accessory sends the same PowerSourceUpdate message to the iOS 18 device via iAP2 protocol using USB Type C Connector.
We are specifying the same:
AvailableCurrentForDevice = 0 mA
DeviceBatteryShouldChargeIfPowerIsPresent = 1.
We observe:
iPad Battery Settings page - we observe 'Charging'
On the Lumify App running (iOS 18), we observe that UIKit.current.batteryState indicated 'Charging'
Battery icon on top right of the screen indicates 'No Charging'
Please could you help us understand why the Battery status is showing as 'Charging' in the Settings page and with the 'UIKit.current.batteryState' even though we have specified 'AvailableCurrentForDevice = 0 mA'?
Since our accessory is heavily reliant on the Battery status / Charging state, is there potentially another way we get an accurate battery charging status that we are missing? Or are there other suggestions outside of what we do currently to ensure our accessory does not place the iOS18 device into a charging state?
Drivers
RSS for tagUnderstand the role of drivers in bridging the gap between software and hardware, ensuring smooth hardware functionality.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
our virtual CoreAudio server plugin creates and removes dynamically CoreAudio devices. Each time it does so it leaves traces in
/Library/Preferences/Audio
com.apple.audio.DeviceSettings.plist
com.apple.audio.SystemSettings.plist
The files on the test machine now have become >1Mb and the system keeps recreating them.
How can I manually remove/cleanup these files? (This is for development only. It already became pretty tedious to evaluate current device settings for debugging purposes.)
How can the CoreAudio server plugin make sure once a device has been removed also its entries are removed from the .plist (It already removes it's storage, but the system still keeps other settings.)
Is there some documentation about what gets stored and how the settings are organized in these preferences? (This is also for development and debugging only. We are not intending to access these settings directly )
Thanks!
Hi,
I have a usb composite device with multiple interfaces that support cdc-acm UARTs.
My custom driver (.dext) loads and works for single channel usb-cdcccm device with these entries in the info.plist:
bInterfaceNumber
1
But there is no option to define multiple "bInterfaceNumber" key.
I tried bInterfaceClass also, as given below, but no success.
Option-1:
bInterfaceClass
10
bInterfaceSubClass
0
bInterfaceProtocol
0
Option-2:
bInterfaceClass
10
bInterfaceSubClass
0
bInterfaceProtocol
0
Both the above options yield no result.
But as I said in the beginning:
<key>IOProviderClass</key>
<string>IOUSBHostInterface</string>
<key>IOClass</key>
<string>IOUserSerial</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyDriver</string>
<key>IOUserServerName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>idVendor</key>
<integer>VENDORID</integer>
<key>idProduct</key>
<integer>PRODUCTID</integer>
<key>bInterfaceNumber</key>
<integer>1</integer>
<key>bConfigurationValue</key>
<integer>1</integer>
"MyDriver" loads for interface-1 and works fine. The default AppleCDCACM driver loads for the 2nd channel. I want the same driver load for both the channels.
Any help/suggestions \is very much appreciated.
Thank you.
Topic:
App & System Services
SubTopic:
Drivers
Hello everybody,
Since macOS 15, the systemextension allow in changed as switch style and put in the "Login items & Extensions". I know the URL navigating to here, which is:
x-apple.systempreferences:com.apple.LoginItems-Settings.extension
But the extension options we need to scroll deep down and we need to click the "!" to open it.
I want to open the finally window for user can easily see it and enable it. Please tell me how. Appreciate!!
I have an iPhone 14 Pro. I downloaded the iOS 26 beta and had a SERIOUS error, rendering the phone unusable.
I charged it to 60% and kept it plugged in while updating.
While updating, I restarted several times at the Apple logo, then at the Welcome screen, and it had quite a few bugs with low battery warnings.
When I turned it on, I noticed I had 1% (I thought it was strange).
When it was plugged in, it wouldn't charge; it only had 1% left, and it also restarted every 2 minutes. Off-plugged, it did exactly the same thing.
In the end, I had to go back to iOS 18.5; I had no problems with this version.
I am trying to localize the CFBundleDisplayName and OSBundleUsageDescription of a driver that is part of an app.
I am able to use InfoPlist.strings files to localize the Bundle display name for the app, but when I try to use the same file as part of the driver, the name displayed in settings for the app does not change correctly.
In fact, it seems to follow the default language set in the xcode project. If the default language is not included in the suite of InfoPlist.strings files, it seems to take the string from the info.plist file. sometimes it just seems to take the English version regardless of the default language or tablet language.
Has anyone had success with this?
Hi guys!
OK, reaching out for some help here.
I am having all kinds of trouble with OSDeclareDefaultStructors.
I have seriously been at this for nearly a week now and have come to the conclusion that I need to reach out for help from people that are more experience using Xcode.
I believe entirely that my issue is just that I can't for whatever reason see how to set up includes and libraries and things like that.
I have this line:
OSDeclareDefaultStructors(NukeVirtualGamepad)
No matter what I do, Xcode will not recognize OSDeclareDefaultStructors.
The project builds a DriverKit > Driver extension.
I have literally tried absolutely everything with this. I am at a loss for words. I even set up a new blank project and it still will not recognize OSDeclareDefaultStructors.
I did a lot of research and it looks like expo needs OSDeclareDefaultStructors in order for the extension to build with a binary in it instead of being just a codeless extension.
Here is the code with the issue:
#pragma once
#include <DriverKit/OSMetaClass.h>
#include <HIDDriverKit/IOUserHIDDevice.h>
#include <DriverKit/OSData.h>
class NukeVirtualGamepad : public IOUserHIDDevice {
OSDeclareDefaultStructors(NukeVirtualGamepad) // The problem is right here! This line!
public:
// Keep it minimal; no 'override' keywords since the .h types may not mark them virtual
bool init();
void free();
kern_return_t Start(IOService* provider);
void Stop (IOService* provider);
OSData* newReportDescriptor();
// (Optional) helper you’ll use later to inject input matching your report
kern_return_t PostInput(uint16_t buttons, int8_t x, int8_t y);
};
I do have to mention to everyone that I am still very new with Xcode. So there is a ton that I don't know yet or might be misunderstanding.
Has anyone seen this before?
Thank you in advance.
The device I am trying to develop a firmware updater for is an NVMe drive with a USB4 interface. It can connect in USB4 mode (tunneled NVMe), in USB 3 mode or in USB 2 mode.
In USB 2 and USB 3 mode, the device descriptor shows one interface with two alternates. Alternate 0 uses the bulk-only protocol, with one IN and one OUT pipe. Alternate 1 uses the UAS protocol, with two IN and two OUT pipes.
I use identical code in my driver to send custom CDBs. I can see using IORegistryExplorer that in USB 2 mode, macOS chooses alternate 0, the bulk-only protocol. My custom CDBs and their accompanying data pay loads are put on the bus, more or less as expected.
In USB 3 mode, macOS chooses alternate 1, the UAS protocol. My custom CDB is put on the bus, but no payload data is transferred.
Is this expected behavior?
If so, is there a way to force the OS to choose alternate 0 even when on USB 3, perhaps with another dext?
I'll file a bug about this when Feedback Assistant lets me.
Hi,
We are using the AX88772C as a USB->Ethernet bridge in a product we are developing. Due to the chip not following the NCM protocol, it is not supported by the default networking drivers on the iPhone.
Initially, we intended on using DriverKit to develop a userspace driver for this device. However, we have been informed DriverKit is only available on iPad OS, not iOS.
As such is the case, we have found two possible alternatives. First being IOkit, and the second being External Accessory Session (EASession).
What are the limitations of each of these options? We need the ability to send and receive USB packets to Control and Bulk endpoints. Is this possible with either of the options defined above? Would either of these options require the device to be MFi certified?
We have read that some APIs within IOkit require the apple device to be jailbroken. Is there a list of features that can be used without a jailbroken device? Documentation on these 2 options is limited, so any official documentation would be great.
Thanks!
Few user space applications are available in market for example xnvme, but does not have any interaction with Admin Submission/Completion queues.
Also IOCTLs are not very prominent . Is there any ways to get access to the native NVMe Mac driver source code?
Thanks, hopefully we will get some positive response here.
I have been working on a multi-platform multi-touch HID-standard digitizer clickpad device.
The device uses Bluetooth Low Energy (BLE) as its connectivity transport and advertises HID over GATT. To date, I have the device working successfully on Windows 11 as a multi-touch, gesture-capable click pad with no custom driver or app on Windows.
However, I have been having difficulty getting macOS to recognize and react to it as a HID-standard multi-touch click pad digitizer with either the standard Apple HID driver (AppleUserHIDEventDriver) or with a custom-coded driver extension (DEXT) modeled, based on the DTS stylus example and looking at the IOHIDFamily open source driver(s).
The trackpad works with full-gesture support on Windows 11 and the descriptors seem to be compliant with the R23 Accessory Guidelines document, §15.
With the standard, matching Apple AppleUserHIDEventDriver HID driver, when enumerating using stock-standard HID mouse descriptors, the device works fine on macOS 14.7 "Sonoma" as a relative pointer device with scroll wheel capability (two finger swipe generates a HID scroll report) and a single button.
With the standard, matching Apple AppleUserHIDEventDriver HID driver, when enumerating using stock-standard HID digitizer click/touch pad descriptors (those same descriptors used successfully on Windows 11), the device does nothing. No button, no cursor, no gestures, nothing. Looking at ioreg -filtb, all of the key/value pairs for the driver match look correct.
Because, even with the Apple open source IOHIDFamily drivers noted above, we could get little visibility into what might be going wrong, I wrote a custom DriverKit/HIDDriverKit driver extension (DEXT) (as noted above, based on the DTS HID stylus example and the open source IOHIDEventDriver.
With that custom driver, I can get a single button click from the click pad to work by dispatching button events to dispatchRelativePointerEvent; however, when parsing, processing, and dispatching HID digitizer touch finger (that is, transducer) events via IOUserHIDEventService::dispatchDigitizerTouchEvent, nothing happens.
If I log with:
% sudo log stream --info --debug --predicate '(subsystem == "com.apple.iohid")'
either using the standard AppleUserHIDEventDriver driver or our custom driver, we can see that our input events are tickling the IOHIDNXEventTranslatorSessionFilter HID event filter, so we know HID events are getting from the device into the macOS HID stack. This was further confirmed with the DTS Bluetooth PacketLogger app. Based on these events flowing in and hitting IOHIDNXEventTranslatorSessionFilter, using the standard AppleUserHIDEventDriver driver or our custom driver, clicks or click pad activity will either wake the display or system from sleep and activity will keep the display or system from going to sleep.
In short, whether with the stock driver or our custom driver, HID input reports come in over Bluetooth and get processed successfully; however, nothing happens—no pointer movement or gesture recognition.
STEPS TO REPRODUCE
For the standard AppleUserHIDEventDriver:
Pair the device with macOS 14.7 "Sonoma" using the Bluetooth menu.
Confirm that it is paired / bonded / connected in the Bluetooth menu.
Attempt to click or move one or more fingers on the touchpad surface.
Nothing happens.
For the our custom driver:
Pair the device with macOS 14.7 "Sonoma" using the Bluetooth menu.
Confirm that it is paired / bonded / connected in the Bluetooth menu.
Attempt to click or move one or more fingers on the touchpad surface.
Clicks are correctly registered. With transducer movement, regardless of the number of fingers, nothing happens.
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?
Firstly, I realise that Kexts are deprecated. And for my needs, user-space IOKit from an application might be more than I’ll ever need, but I can’t help ensuring I’ve got all my ducks in a row while I’m designing an app.
I noticed in the above Kext deprecation notice that it’s more about specific APIs that are deprecated rather than the kext mechanism itself (no mention of IOKit kernel APIs there). Along with the fact that a reboot would be required and various other policy changes.
While reading up on System Extensions and the various newer tools, DriverKit, Endpoint Security etc, I’ve noticed there’s no mention of this “IOKit Driver” target/deliverable in the Xcode template chooser. It looks like, from the requirements, that DriverKit is aimed at hardware manufacturers, with a need to request the DriverKit entitlement for development.
With respect to Apple’s internal Kext deprecation roadmap, how safe is it to build a product that relies on using an IOKit Driver and are there any requirements similar to DriverKit? Would a developer need to request an entitlement?
If I developed an app using user-space IOKit and, for illustration purposes let’s say I also included an IOKit Driver in the app bundle. If I used the IOKit API, including header file constants only (no digging around in the IORegistryExplorer for non-public keys), as Apple intends them to be used, would this fall foul of any App Store rules that anyone is aware of?
Put another way, would making use of an IOKit Driver disqualify my app from being distributed via the App Store, similar to an Endpoint Security extension?
As an aside, there are a lot of API in the ES Framework that could be used to build apps that have nothing to do with Endpoint Security. File system related apps for example. It’s a shame there isn’t an enhanced middle ground between FSEvents and Endpoint Security framework.
Hello Everyone,
I encountered an issue with PCI memory access in DriverKit. In my case, BAR0 is not available, but BAR1 is ready for use. Here’s the log output:
!!! ERROR : Failed to get BAR0 info (error: 0xe00002f0). !!!
BAR1 - MemoryIndex: 0x00000000, Size: 0x00040000, Type: 0
Issue Description
When I initially wrote to BAR0 using memoryIndex = 0, it worked successfully:
AME_Address_Write_32(pAMEData, pAMEData->memoryIndex, AME_HOST_INT_MASK_REGISTER, 0x0F);
However, I mistakenly forgot to update memoryIndex to 1 for BAR1. Surprisingly, the write operation still succeeded.
When I fixed memoryIndex = 1 for BAR1, the write operation no longer had any effect. There was no error, but the expected behavior did not occur.
Relevant API (From IOPCIDevice.iig)
/*!
/*!
* @brief Writes a 32-bit value to the PCI device's aperture at a given memory index.
* @discussion This method writes a 32-bit register on the device and returns its value.
* @param memoryIndex An index into the array of ranges assigned to the device.
* @param offset An offset into the device's memory specified by the index.
* @param data A 32-bit value to be written in host byte order.
*/
void
MemoryWrite32(uint8_t memoryIndex,
uint64_t offset,
uint32_t data) LOCALONLY;
Log Output:
Writes to BAR0 (memoryIndex = 0)
AME_Address_Write_32() called
memoryIndex: 0, offset: 0x34, data: 0xf
Wrote data 0xF to offset 52
AME_Address_Write_32() called
memoryIndex: 0, offset: 0xa0, data: 0x1
Wrote data 0x1 to offset 160
AME_Address_Write_32() called
memoryIndex: 0, offset: 0x20, data: 0xffffffff
Wrote data 0xFFFFFFFF to offset 32
Writes to BAR1 (memoryIndex = 1) – No Response
AME_Address_Write_32() called
memoryIndex: 1, offset: 0x34, data: 0xf
No confirmation log, no visible effect.
Questions
What should memoryIndex be set to for BAR1?
The log shows "BAR1 - MemoryIndex: 0x00000000", but should I be using 1 instead?
How can I verify if a write operation to BAR1 is successful?
Is there a way to check if the memory region is actually writable?
Should I use MemoryRead32() to confirm the written value?
Any guidance would be greatly appreciated!
Best Regards,
Charles
Hello everyone,
I’m working on implementing hardware interrupt handling in DriverKit and came across the InterruptOccurred method in IOInterruptDispatchSource. I noticed that its declaration ends with a TYPE macro:
virtual void InterruptOccurred(OSAction* action, uint64_t count, uint64_t time)
TYPE(IOInterruptDispatchSource::InterruptOccurred);
This structure seems similar to how Timer Events are set up, where an event is linked to a callback and triggered by a timer. I’m attempting to use a similar approach, but for hardware-triggered interrupts rather than timer events.
I’m currently in the trial-and-error phase of the implementation, but if anyone has a working example or reference on how to properly implement and register InterruptOccurred, it would be greatly appreciated!
Best regards,
Charles
I'm developing a CarPlay Fueling app with CarPlay entitlement properly configured. While testing, I ran into two issues and would appreciate any guidance:
UserDefaults access while iPhone is locked:
In my CarPlay implementation, I read values from UserDefaults that were previously saved in the iOS app. However, when the iPhone is locked and the CarPlay session is active, it seems that the CarPlay extension cannot read the stored values. Is this the expected behavior? If so, how can I persist and access data across the app and CarPlay reliably?
API calls while iPhone is locked:
The CarPlay interface in my app communicates with a server to display lists and detail views. When the iPhone is locked, are network calls still allowed from the CarPlay extension?
Currently, I do not have any background modes enabled in the app capabilities.
If I enable background modes and implement background network logic to ensure API calls complete properly, would this be considered acceptable usage for CarPlay in App Store review? Or could it raise any rejection concerns during the approval process?
Thanks in advance for your help.
In my app, I want to launch Apple Maps and start turn-by-turn navigation when the user taps a button.
I referred to Apple’s documentation and sample projects and implemented the following code:
if let url = URL(string: "maps://?t=m&amp;amp;daddr=(addr)") {
self.carplayScene?.open(url, options: nil, completionHandler: nil)
}
This works only if Apple Maps has been launched at least once on the iPhone or in the CarPlay environment.
If Apple Maps has never been opened before, it launches the app but does not automatically start navigation.
However, once the user has opened Apple Maps at least once — either on the phone or through CarPlay — then navigation starts as expected from that point on.
Is this behavior expected? Or is it a bug?
Hello,
I have DriverKit SCSI driver (PCI through Thunderbolt). And there is some logic and command which should be send to device in UserAbortTaskRequest method. But I cannot find out a way UserAbortTaskRequest to be called by system, so cannot debug the code inside.
In which cases IOUserSCSIParallelInterfaceController/DriverKit framework calls UserAbortTaskRequest ?
Is there a way to imitate situation (in driver or in some external tool), so that UserAbortTaskRequest be called to debug such case?
Topic:
App & System Services
SubTopic:
Drivers
Hi,
In Linux we have this driver structure where the handlers are defined as below:
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = etx_read,
.write = etx_write,
.open = etx_open,
.unlocked_ioctl = etx_ioctl,
.release = etx_release,
};
So when the user app calls open() with the appropriate file/device handle "etx_open" in the driver is acalled, etc. However, the Apple driver structure that is exposed to developers is different and it has changed drastically with the DriverKit architecture.
I have some custom requests from the user app where I need to call this ioctl() type requests on my serial port "tty.myusbserial1234". My driver is derived from IOUserUSBSerial and is working fine for all other practical purposes except for such custom requirements.
Has anyone encountered such a problem in MacOS DriverKit and what is the solution or an alternative?
https://developer.apple.com/documentation/driverkit/communicating-between-a-driverkit-extension-and-a-client-app
This gives a different approach, but the serial ports are accessed via open/read/write/close system calls and tcsetattr and other termios functions to set baud-rate and such. So, the above approcah is not suitable for my purpose.
Any ideas/help is very much appreciated.
Thanks.
Topic:
App & System Services
SubTopic:
Drivers
Hi,
we are listed for the MFI program as a licensed manufacturer. We have now started with the IAP3 sample code and the IAP chips to build up a USB communication between our accessory and an iOS device. We are looking for a sample project for the iOS part. Is there some available? The only official I can find is this:
https://developer.apple.com/library/archive/samplecode/EADemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010079
This app is somehow outdated and from 2016. Is there something else available as a starting point? And how does this relate to IOKit since it is available for serial communication on iOS16 as well?
Kind regards,