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

Drivers Documentation

Posts under Drivers subtopic

Post

Replies

Boosts

Views

Activity

How to sign a DEXT
Kevin's Guide to DEXT Signing The question of "How do I sign a DEXT" comes up a lot, so this post is my attempt to describe both what the issues are and the best current solutions are. So... The Problems: When DEXTs were originally introduced, the recommended development signing process required disabling SIP and local signing. There is a newer, much simpler process that's built on Xcode's integrated code-signing support; however, that newer process has not yet been integrated into the documentation library. In addition, while the older flow still works, many of the details it describes are no longer correct due to changes to Xcode and the developer portal. DriverKit's use of individually customized entitlements is different than the other entitlements on our platform, and Xcode's support for it is somewhat incomplete and buggy. The situation has improved considerably over time, particularly from Xcode 15 and Xcode 16, but there are still issues that are not fully resolved. To address #1, we introduced "development" entitlement variants of all DriverKit entitlements. These entitlement variants are ONLY available in development-signed builds, but they're available on all paid developer accounts without any special approval. They also allow a DEXT to match against any hardware, greatly simplifying working with development or prototype hardware which may not match the configuration of a final product. Unfortunately, this also means that DEXT developers will always have at least two entitlement variants (the public development variant and the "private" approved entitlement), which is what then causes the problem I mentioned in #2. The Automatic Solution: If you're using Xcode 16 or above, then Xcode's Automatic code sign support will work all DEXT Families, with the exception of distribution signing the PCI and USB Families. For completeness, here is how that Automatic flow should work: Change the code signing configuration to "Automatic". Add the capability using Xcode. (USB & PCI) Edit your Entitlement.plist to include the correct "Development Only" configuration: USB Development Only Configuration: <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <string>*</string> </dict> </array> PCI Development Only Configuration: <key>com.apple.developer.driverkit.transport.pci</key> <array> <dict> <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&amp;0x00000000</string> </dict> </array> If you've been approved for one of these entitlements, the one oddity you'll see is that adding your approved capability will add both the approved AND the development variant, while deleting either will delete both. This is a visual side effect of #2 above; however, aside from the exception described below, it can be ignored. Similarly, you can sign distribution builds by creating a build archive and then exporting the build using the standard Xcode flow. Debugging Automatic Code-signing In a new project, the flow I describe above should just work; however, if you're converting an existing project, you may get code signing errors, generally complaining about how the provisioning profile configuration doesn't match. In most cases, this happens because Xcode is choosing to reuse a previously downloaded profile with an older configuration instead of generating a new configuration which would then include the configuration changes you made. Currently, you can find these profile files in: ~/Library/Developer/Xcode/UserData/Provisioning Profiles ...which can make it easier to find and delete the specific profile (if you choose). However, one recommendation I'd have here is to not treat the contents of that folder as "precious" or special. What automatic code signing actually does is generate provisioning profiles "on demand", so if you delete an automatic profile... Xcode will just generate it again at the next build. Manually generating profiles is more cumbersome, but the solution there is to preserve them as a separate resource, probably as part of your project data, NOT to just "lose" them in the folder here. If they get deleted from Xcode's store, then you can just copy them back in from your own store (or using Xcode, which can manually download profiles as well). The advantage of this approach is that when profiles "pile up" over time (which they tend to do), you can just delete[1] all of them then let Xcode regenerate the ones you're actually trying to investigate. In terms of looking at their contents, TN3125: Inside Code Signing: Provisioning Profiles has the details of how to see exactly what's there. [1] Moving them somewhere else works too, but could indicate a fear of commitment. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
1
1
2.6k
Mar ’26
Basic introduction to DEXT Matching and Loading
Note: This document is specifically focused on what happens after a DEXT has passed its initial code-signing checks. Code-signing issues are dealt with in other posts. Preliminary Guidance: Using and understanding DriverKit basically requires understanding IOKit, something which isn't entirely clear in our documentation. The good news here is that IOKit actually does have fairly good "foundational" documentation in the documentation archive. Here are a few of the documents I'd take a look at: IOKit Fundamentals IOKit Device Driver Design Guidelines Accessing Hardware From Applications Special mention to QA1075: "Making sense of IOKit error codes", which I happened to notice today and which documents the IOReturn error format (which is a bit weird on first review). Those documents do not cover the full DEXT loading process, but they are the foundation of how all of this actually works. Understanding the IOKitPersonalities Dictionary The first thing to understand here is that the "IOKitPersonalities" is called that because it is in fact a fully valid "IOKitPersonalities" dictionary. That is, what the system actually uses that dictionary "for" is: Perform a standard IOKit match and load cycle in the kernel. The final driver in the kernel then uses the DEXT-specific data to launch and run your DEXT process outside the kernel. So, working through the critical keys in that dictionary: "IOProviderClass"-> This is the in-kernel class that your in-kernel driver loads "on top" of. The IOKit documentation and naming convention uses the term "Nub", but the naming convention is not consistent enough that it applies to all cases. "IOClass"-> This is the in-kernel class that your DEXT attaches to and works through. This is where things can become a bit confused, as some families work by: Routing all activity through the provider reference so that the DEXT-specific class does not matter (PCIDriverKit). Having the DEXT subclass a specific subclass which corresponds to a specific kernel driver (SCSIPeripheralsDriverKit). This distinction is described in the documentation, but it's easy to overlook if you don't understand what's going on. However, compare PCIDriverKit: "When the system loads your custom PCI driver, it passes an IOPCIDevice object as the provider to your driver. Use that object to read and write the configuration and memory of your PCI hardware." Versus SCSIPeripheralsDriverKit: Develop your driver by subclassing IOUserSCSIPeripheralDeviceType00 or IOUserSCSIPeripheralDeviceType05, depending on whether your device works with SCSI Block Commands (SBC) or SCSI Multimedia Commands (SMC), respectively. In your subclass, override all methods the framework declares as pure virtual. The reason these differences exist actually comes from the relationship and interactions between the DEXT families. Case in point, PCIDriverKit doesn't require a specific subclass because it wants SCSIControllerDriverKit DEXTs to be able to directly load "above" it. Note that the common mistake many developers make is leaving "IOUserService" in place when they should have specified a family-specific subclass (case 2 above). This is an undocumented implementation detail, but if there is a mismatch between your DEXT driver ("IOUserSCSIPeripheralDeviceType00") and your kernel driver ("IOUserService"), you end up trying to call unimplemented kernel methods. When a method is "missing" like that, the codegen system ends up handling that by returning kIOReturnUnsupported. One special case here is the "IOUserResources" provider. This class is the DEXT equivalent of "IOResources" in the kernel. In both cases, these classes exist as an attachment point for objects which don't otherwise have a provider. It's specifically used by the sample "Communicating between a DriverKit extension and a client app" to allow that sample to load on all hardware but is not something the vast majority of DEXT will use. Following on from that point, most DEXT should NOT include "IOMatchCategory". Quoting IOKit fundamentals: "Important: Any driver that declares IOResources as the value of its IOProviderClass key must also include in its personality the IOMatchCategory key and a private match category value. This prevents the driver from matching exclusively on the IOResources nub and thereby preventing other drivers from matching on it. It also prevents the driver from having to compete with all other drivers that need to match on IOResources. The value of the IOMatchCategory property should be identical to the value of the driver's IOClass property, which is the driver’s class name in reverse-DNS notation with underbars instead of dots, such as com_MyCompany_driver_MyDriver." The critical point here is that including IOMatchCategory does this: "This prevents the driver from matching exclusively on the IOResources nub and thereby preventing other drivers from matching on it." The problem here is that this is actually the exceptional case. For a typical DEXT, including IOMatchCategory means that a system driver will load "beside" their DEXT, then open the provider blocking DEXT access and breaking the DEXT. DEXT Launching The key point here is that the entire process above is the standard IOKit loading process used by all KEXT. Once that process finishes, what actually happens next is the DEXT-specific part of this process: IOUserServerName-> This key is the bundle ID of your DEXT, which the system uses to find your DEXT target. IOUserClass-> This is the name of the class the system instantiates after launching your DEXT. Note that this directly mimics how IOKit loading works. Keep in mind that the second, DEXT-specific, half of this process is the first point your actual code becomes relevant. Any issue before that point will ONLY be visible through kernel logging or possibly the IORegistry. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
1
0
1.9k
2w
DriverKit USB Transport entitlement request pending — iPadOS Photo Booth with DNP / Citizen / HiTi printers
Hello Apple Developer Support, We have submitted a DriverKit entitlement request for our iPadOS photo booth application, which uses a USB DriverKit extension to communicate with professional dye-sublimation photo printers over USB-C. Our request covers one USB Transport configuration with the following Vendor IDs: 0x1343 (4931) — DNP / Citizen 0x1452 (5202) — DNP 0x0D16 (3350) — HiTi The DriverKit extension is used exclusively by our own iPadOS application, and we do not require UserClient Access. Our entitlement request is currently pending. We would appreciate any guidance from the DriverKit team regarding the review of our request. Request ID: 2DN73H7DCY Thank you.
0
0
7
1h
Read file with System Network Extension from App Group
I have trouble with reading a file from an App Group with my System Network Extension. The app group container is found successfully. However the file read returns empty. In the app itself the same code runs fine and returns a string array of items found in the file. Code: func readFile() - [String] {         var jsonResult: [String] = []         guard let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppConstants.groupID) else {             fatalError()         }         let fileURL = containerURL.appendingPathComponent("file.json")         if let data = try? NSData(contentsOfFile: fileURL.path, options: .mappedIfSafe) as Data {             if let json = try? JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) {                 jsonResult = json as! [String]             }         }         os_log("jsonResult: %{public}@", jsonResult)         return jsonResult     } Log: default 09:42:19.486793+0200 app-network-extension container_create_or_lookup_app_group_path_by_app_group_ identifier: success default 09:42:20.105792+0200 app-network-extension jsonResult: ( ) Edit, after more digging: fileURL is different! App: file:///Users/me/Library/Group%20Containers/ SysExt: file:///private/var/root/Library/Group%20Containers/
4
1
1.4k
5h
What is the supported DriverKit Stop/drain sequence for an IOUserClient operation queue?
Environment: macOS 26.6.2 (25G83), Apple silicon Xcode 26.6 (17F113) DriverKit SDK 25.5 I am implementing a DriverKit IOService with an IOUserClient. This is a lifecycle and object-ownership question independent of the device protocol. The intended design admits at most one user client during a provider lifetime. Lifecycle methods run on the provider’s default queue, while IOUserClient ExternalMethod requests run on a separate serial IODispatchQueue. At most one device request may be in flight. The shutdown invariant we need is: Stop accepting new requests. Allow every accepted request to complete exactly once, or cancel it. Observe completion of the operation queue’s cancellation handler. Call the inherited Stop implementation last. Perform no provider access afterward. The relevant public documentation is: IOService::Stop: https://developer.apple.com/documentation/driverkit/ioservice/stop IODispatchQueue::Cancel: https://developer.apple.com/documentation/driverkit/iodispatchqueue/cancel IOService::SetDispatchQueue: https://developer.apple.com/documentation/driverkit/ioservice/setdispatchqueue For the normal path, the proposed sequence is conceptually: Stop(provider): close request admission operationQueue->Cancel(cancellationHandler) wait for the cancellation handler from the separate queue super::Stop(provider) I need clarification of the complete supported public API contract: If IODispatchQueue::Cancel returns a non-success result, is its cancellation handler still guaranteed to execute? If it is not, what supported action lets Stop keep the provider and user client valid until previously accepted work is no longer capable of accessing them? Is it supported for the provider and its one user client to share the provider-owned serial operation queue? If the IOUserClient stops independently, must it own and cancel a separate queue, or is there a supported per-client drain mechanism that does not cancel provider-owned work? Is the driver’s public IOService::Stop override guaranteed to run on every termination path where accepted user-client work must be drained, including when the provider is already inactive or the DriverKit server has slept? If not, which public lifecycle callback supplies that drain point? Is blocking the provider’s default queue inside Stop while awaiting the cancellation handler from a separate operation queue the supported interpretation of “wait for your cancellation handlers”? If not, what public continuation mechanism should be used before calling inherited Stop? We also observed one power-management panic after sleep/wake: HiMDScsiDriver::setPowerState(..., 0 -> 4) timed out after 20342 ms The DEXT does not currently override SetPowerState. This panic motivates the lifecycle review, but I am not treating it as proof that the Stop/drain design caused the timeout. I am looking specifically for a supported public DriverKit sequence. I do not want to rely on private framework entry points or infer object-lifetime guarantees from a successful build or experiment.
4
0
850
2d
IOConnectMapMemory questions
I am developing a dext that is running into issues pertaining to IOConnectMapMemory (at least I think so). There are 3 parts of code that are involved, the dext (which allocates the memory in the first place), a user client library which is involved in connecting to the dext and releasing when the hardware is removed, and finally some processing code (at the user level) which executes on this shared block of memory from the dext. The shared memory is allocated using an IOBufferMemoryDescriptor: IOBufferMemoryDescriptor::Create(kIOMemoryDirectionNone, sizeof(sharedMemoryBlock), IOVMPageSize, &(ivars->mSharedMemoryBlockMemDesc)); The User Client Library acquires a mapped pointer to this memory by calling IOConnectMapMemory: IOConnectMapMemory(mConnect, kMemoryType_SharedMemoryBlock, mach_task_self(), (mach_vm_address_t*)&mUserClientSharedBlockPtr, (mach_vm_size_t*)&mSizeOfUserClientSharedBlock, kIOMapAnywhere); …which triggers the dext’s IOUserClient subclass' “CopyClientMemoryForType_Impl”. That code adds a retain and returns a pointer to the IOBufferMemoryDescriptor: case kMemoryType_SharedMemoryBlock: // error checks first (make sure it’s allocated and initialized, etc) ivars->mSharedMemoryBlockMemDesc->retain(); *memory = ivars->mSharedMemoryBlockMemDesc; break; IOConnectMapMemory returns the “mapped pointer” (in mUserClientSharedBlockPtr) to the User Client Library, which in turn provides it to the processing code. The processing code checks the pointer validity, and if valid, runs its processing. This worked fine with a kext implementation. This fails with dext implementation, because during the processing call (after validity check but during usage) the mapped pointer can become NULL, which seems to be against the design pattern, and causes the application to crash due to an access violation (dereferencing NULL). I assume I am doing something incorrect here, but I’m not seeing what it is. The memory was retained, so it should not be deleted until the User Client Library has released it, but the only release available would be IOConnectUnmapMemory, and that fails with “invalid argument” (0xE00002C2) after the device is hot-unplugged. I am not finding IOConnectMapMemory examples on developer.apple.com. I have verified via the forums that IOConnectMapMemory is still a recommended practice with DriverKit development: https://developer.apple.com/forums/thread/803947?answerId=862249022#862249022 . What’s the trick here for stability? The device is a peripheral which can be unplugged or turned off at any time, which would result in the dext and user client library code tearing down the structures and memory, but it should be able to do so safely without causing access violations. (Note, this has been simplified for the purpose of focusing the question, in reality there are 4 separate memory blocks which are shared in this fashion: two ring buffers, main engine status, and client status. They each use their own memory_type definition, but a general solution is needed and can be applied to all 4, and there can be multiple clients at any point in time).
1
0
997
3d
Network UPS?
I found some nice code that implements a NUT client, and now I want to take the next step -- I would like to get it to show up as a UPS for macOS. But I've never done anything with IOKit... and there don't seem to be a lot of examples of, maybe, IOPowerSources?
6
0
395
3d
HIDVirtualDevice digitizer pen: position, proximity and tip switch reach NSEvent, but tablet pressure is always 0 — is pen pressure supported at all?
I'm building a virtual pen digitizer with HIDVirtualDevice (CoreHID, macOS 26.2, com.apple.developer.hid.virtual.device entitlement granted, Developer ID signed with the provisioning profile embedding the entitlement). The device is created and activated fine and shows up as expected: hidutil list: 0xface 0xbeef UsagePage 13 Usage 2 Transport Virtual "Hej Stylus Virtual Pen" AppleUserHIDEventService / AppleUserHIDEventDriver Report descriptor (Digitizer/Pen application collection, Stylus physical collection, 7-byte input report): 05 0D Usage Page (Digitizer) 09 02 Usage (Pen) A1 01 Collection (Application) 09 20 Usage (Stylus) A1 00 Collection (Physical) 09 42 Usage (Tip Switch) 09 32 Usage (In Range) 15 00 25 01 75 01 95 02 81 02 ; 2 bits 95 06 81 03 ; 6 bits padding (Const) 05 01 09 30 09 31 ; Generic Desktop X, Y 16 00 00 26 FF 7F 75 10 95 02 81 02 ; 0..32767, 16 bit each 05 0D 09 30 ; Digitizer / Tip Pressure 16 00 00 26 FF 1F 75 10 95 01 81 02 ; 0..8191, 16 bit C0 C0 I feed it a synthetic stream at 60 Hz (X sweep, Y fixed, tip switch down, in range, pressure ramping 0→8191) via dispatchInputReport(data:timestamp:) and observe the results with a global NSEvent monitor (.tabletProximity, .tabletPoint, .leftMouseDown/Up/Dragged, .mouseMoved) plus the raw CGEvent fields. What works tabletProximity: isEnteringProximity=1, pointingDeviceType=.pen, vendorID=0xFACE, tabletID=0xBEEF, systemTabletID assigned. All movement arrives as tabletPoint / mouseMoved with subtype == .tabletPoint; positions are exact. Tip switch maps to leftMouseDown / leftMouseUp correctly (verified by toggling the tip bit with pressure held at max). capabilityMask on the proximity event is 0x407 = NX_TABLET_CAPABILITY_DEVICEIDMASK | ABSXMASK | ABSYMASK | PRESSUREMASK — so the system declares pressure capability for this device. What doesn't NSEvent.pressure, kCGTabletEventPointPressure and kCGMouseEventPressure are always 0.000, on every event type, including with a constant maximum pressure value (8191). NSEvent.buttonMask is 1 (pen tip) and kCGTabletEventPointButtons is 1, so the report is being parsed — the pressure field just never makes it into the tablet event data. Things I've established / tried The pressure value is parsed and does influence touch/click: with tip switch held down and pressure held at 0, no mouse down is ever generated. With pressure ramping, the click happens at exactly 75 % of the logical range. Reading the open-source IOHIDEventDriver::parseDigitizerTransducerElement explains this: Tip Pressure is read with kIOHIDValueScaleTypeCalibrated, but only X/Y/Z elements get a calibration, and an uncalibrated element scales to −1…+1 — so raw 0…8191 becomes −1…+1 and the touch threshold (+0.5) sits at 75 %. Changing Logical Minimum to −8191 (so raw 0…8191 maps to 0…1) moves the click to exactly 50 % — confirming the model. Pressure in the event data is still 0. Adding Physical Minimum/Maximum and a Unit to the pressure element: no change. hidutil monitor no longer exists on macOS 26, so I can't inspect the IOHIDEvent digitizer fields directly. This looks like the same behaviour reported for kext-based digitizers since macOS 10.12 (developer.apple.com/forums thread "IOHIPointing dispatchAbsolutePointerEvent not works" and its sibling: "the pressure information is there from the transducer, the OS doesn't respond to it on 10.12+"). The tablet-pressure dispatch in the open-source IOHIDEventService::dispatchDigitizerEventWithOrientation is commented out, and the userspace IOHIDEventTranslation isn't open source, so I can't tell where the value is dropped. Questions Is pen pressure from a HIDVirtualDevice (or any generic HID digitizer handled by AppleUserHIDEventDriver) expected to reach NSEvent.pressure / kCGTabletEventPointPressure at all on current macOS? Or is that path reserved for vendor drivers posting tablet events themselves? If it is supported: which descriptor properties does the digitizer→tablet translation require for pressure — specific usages (Transducer Index, Barrel Switch, Tilt, Twist), Report ID, Physical range/Unit on the pressure element, a Feature report, or a particular device property (e.g. something in HIDVirtualDevice.Properties / kIOHIDDigitizer* keys)? Is there a documented way to set element calibration for a virtual device so Tip Pressure scales 0…1 instead of −1…+1 without abusing Logical Minimum? Is there a supported diagnostic on macOS 26 to see the IOHIDEvent digitizer fields (pressure, touch, event mask) that the event system builds from my reports, now that hidutil monitor is gone? Happy to file a Feedback with the full project and a sysdiagnose if that helps.
2
0
82
5d
iPhone 17 Pro loses all touchscreen input on iOS 27 public 24A437 — reproducible on RC 24A435
Device: iPhone 17 Pro 256GB Affected builds: • iOS 27 RC — 24A435 • iOS 27 public release — 24A437 Known working version: • iOS 26.7 DESCRIPTION I am seeing a reproducible total loss of touchscreen input on this specific iPhone 17 Pro when running iOS 27. Before today's test, the device was running iOS 26.7 and the touchscreen was working normally. On September 14, I updated through the official OTA Software Update to iOS 27.0 public release, build 24A437. Beta Updates were disabled. After the update completed, the iPhone booted normally and reached the Hello screen. The display renders normally. Physical buttons respond normally. However, all touchscreen input is completely unavailable. No taps or swipes are recognized anywhere on the display, so it is not possible to proceed past the Hello screen. REPRODUCIBLE ON IOS 27 RC The exact same behavior previously occurred on iOS 27 RC build 24A435. To eliminate backup corruption, user data, apps and settings as possible variables, I performed a complete clean restore of 24A435 using Apple Configurator. No backup was restored. No apps were installed. No user data was restored. No previous settings were restored. Immediately after the clean restore, at the initial Hello screen, touchscreen input was still completely unavailable. Restoring the same device back to iOS 26 immediately restored touchscreen functionality. REPRODUCTION HISTORY iOS 26.7 → Touchscreen works normally iOS 27 RC 24A435 → Touchscreen completely unresponsive after boot Clean restore of 24A435 → Touchscreen still completely unresponsive at the initial Hello screen Restore back to iOS 26 → Touchscreen functionality returns iOS 27 public 24A437 → Touchscreen completely unresponsive again after boot DIAGNOSTICS Apple has already performed: • Remote diagnostics — passed • MRI — passed • Multi-Touch diagnostic — passed None of these diagnostics detected a hardware failure. The issue was reported through Feedback Assistant before the public release: Feedback ID: FB24728805 I also have an active Apple Support case, and the device is being evaluated by an Apple Authorized Service Provider. QUESTION / TECHNICAL OBSERVATION The particularly unusual aspect is the repeatability across OS versions on the same physical device: iOS 26 → touch works iOS 27 → touch does not work iOS 26 → touch works again iOS 27 → touch does not work again I am not assuming that the root cause is purely software or purely hardware. I am interested in whether this could involve touchscreen/HID initialization, digitizer-related firmware, or an interaction between iOS 27 and a particular hardware/display/controller revision. Has anyone observed a similar condition where: • the display continues rendering normally; • physical buttons continue working; • all touchscreen input is lost immediately after booting iOS 27; • a clean restore of iOS 27 does not resolve it; and • restoring the same device to iOS 26 restores touchscreen functionality? If anyone has reproduced this on another iPhone 17 Pro or 17 Pro Max, the exact model and iOS build would be particularly useful. RELATED PUBLIC DISCUSSIONS Apple Support Community: https://discussions.apple.com/thread/256356702 MacRumors: https://forums.macrumors.com/threads/iphone-17-pro-touchscreen-completely-dead-on-ios-27-public-24a437-same-issue-on-rc-24a435.2489323/
0
0
353
6d
Which virtual-HID entitlement path for a gamepad app — CoreHID or DriverKit? (Request H8Q3K9CK7Z stuck 2.5 months)
I'm building a macOS app that creates a virtual gamepad (Xbox-style HID device) so games can see input coming from a companion mobile app — similar in spirit to Karabiner-DriverKit-VirtualHIDDevice, but for a gamepad rather than keyboard/mouse. I submitted a Capability Request for "HID Virtual Device" (com.apple.developer.hid.virtual.device) under Capability Requests in Certificates, Identifiers & Profiles: Request ID: H8Q3K9CK7Z Submitted: June 30, 2026 Status: still shows "Submitted" with no change, ~2.5 months later Two questions I'd appreciate guidance on: Is this request queue still actively processed? I haven't received any request for more information, and there's been no status change since submission. Is 2.5 months a normal wait right now, or should I be following up through a different channel? Is the app-level CoreHID entitlement (com.apple.developer.hid.virtual.device) actually sufficient for a gamepad to be detected by GameController.framework (i.e. GCController.controllers()), or does that require wrapping the virtual device in a DriverKit driver extension instead, similar to how Karabiner ships com.apple.developer.driverkit + .transport.hid + .family.hid.device + .family.hid.eventservice alongside this same CoreHID key, rather than relying on the CoreHID entitlement standalone? Any clarity on the right entitlement combination, and on whether I should expect movement on H8Q3K9CK7Z, would be a big help.
1
0
660
6d
Lessons learned shipping an open-source NetworkingDriverKit NIC driver (Realtek RTL8127, 10GbE)
I've just shipped a signed NetworkingDriverKit driver for the Realtek RTL8127 10GbE PCIe NICs on Apple Silicon, source at https://github.com/stefb69/RTL812xLucy (directory RTL8127Dext). It runs at line rate (9.4 Gbit/s each way at MTU 1500, 9.9 with jumbo frames) with TSO, checksum offload and four TX queues by service class. Since there are very few public NetworkingDriverKit drivers to learn from, here is what cost me the most time, in case it saves someone else a week. Three of these are filed as feedback. TX packets from native Skywalk flows have a 2-byte data offset (FBxxxxxxxx). getDataVirtualAddress() / getDataIOVirtualAddress() return the buffer base; the frame starts at getDataOff(). BSD-path packets (ping, curl, ssh, DHCP) have offset 0, Network.framework flows (Safari, URLSession, App Store, codesign --timestamp) have offset 2. If you DMA from the base, everything "works" except every modern client, which sits in SYN_SENT. The headers don't mention it. getMaxTransferUnit() is the maximum MTU, not the current one (FBxxxxxxxx). It is read once at registerEthernetInterface() and becomes the hard ceiling for ifconfig mtu; return your current 1500 and jumbo frames fail with EINVAL before your dext is called. Don't call bpfAttach() on macOS 26.6 (FBxxxxxxxx). It worked once, then panicked the kernel inside IOSkywalkFamily when the dext was replaced while tcpdump was attached. Without it, tcpdump on your interface only sees host-path frames, not native flows, so debugging point 1 is done from the peer side. Smaller ones: the personality needs IOClass = IOUserNetworkEthernet and CFBundleIdentifierKernel = com.apple.iokit.IOSkywalkFamily, not IOUserService, or super::Start fails with 0xe00002bc. All queues are created disabled: setEnable(true) in setInterfaceEnable(), plus requestDequeue() on the TX queues when the link comes up. setMulticastAddresses() must be implemented or no multicast group is ever joined (mDNS and IPv6 solicited-node are silently dead). Release dispatch sources from the Cancel() completion block, not right after Cancel(), or the dext crashes at every upgrade. The dext bundle must be named .dext or the host app reports "Extension not found in App bundle". Dext os_log lines show up as kernel: messages with the .dext bundle as sender; use %{public}s. Performance question for Apple engineers: with eight or more parallel TCP senders at MTU 1500 the stack emits ~3 KB TSO packets at ~160k packets/s and the dext saturates one core around 4.5 Gbit/s (fine at MTU 9000, fine with one to four streams). Is IOUserNetworkPacketPoller the intended answer for per-packet cost in a NIC dext, and is there any guidance on batch sizes for IOUserNetworkTxSubmissionQueue dequeues?
1
0
205
1w
DriverKit USB Transport entitlement pending 6+ weeks (DNP + HiTi photo printers) - same VIDs already approved for another team
We build an iPad photo booth app and have a DriverKit USB transport driver for DNP/Citizen and HiTi dye-sub photo printers. These printers have no vendor drivers for iPadOS, so a dext is the only way to print from an iPad. The driver is complete and hardware-validated on both printer families under a development profile. The only thing blocking distribution is the entitlement. Our requests have been in "Submitted" state since July: 72B5P53K28 (July 24, 2026): DriverKit, USB Transport, UserClient Access, vendor IDs 4931 (0x1343) and 5202 (0x1452) 4Z76G958GF (July 25, 2026): amendment adding vendor ID 3350 (0x0D16, HiTi Digital) Developer Support case 20000136465729 was opened for this and acknowledged on September 1, but there has been no decision. I noticed in https://developer.apple.com/forums/thread/826658 that a DTS engineer confirmed the identical configuration (one USB dext, vendor IDs 3350, 4931, 5202) was approved for another team on May 5, so the scope itself is clearly something Apple grants. Is there anything further needed from us to move these along, or a way to get a status on them? Team ID: 7B3398CSQU
2
0
459
1w
DriverKit entitlement for USB transport - support all vendor id's
Hey, We are developing a dext that would like to match with all USB devices, no matter the vendor. We use VendorID = * in the plist of the Dext to help achieve this when running it locally without entitlements. I know that the transport.usb entitlement requires a list of Vendor id's, but is it possible to receive an entitlement which is suitable for all VID's? Kind of like this: <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <string>*</string> </dict> </array> Thanks
2
1
1.2k
1w
Guidance requested: DriverKit entitlement follow-up for DLP application (Endpoint Security entitlement already granted)
Entitlements requested: com.apple.developer.driverkit.userclient-access com.apple.developer.driverkit.transport.usb com.apple.developer.driverkit.transport.hid com.apple.developer.driverkit.family.hid.eventservice com.apple.developer.driverkit.family.serial com.apple.developer.driverkit.family.scsicontroller com.apple.developer.driverkit.family.networking com.apple.developer.driverkit.family.hid.device , and the base com.apple.developer.driverkit entitlement Hi all, We recently received a decline on the DriverKit entitlement set listed above. The response noted: "Technical details within DriverKit mean that it is not a viable solution for security block or broad-scale system modifications." I'd like to get some clarity on how to bring our request in line with what's approvable, and I'm hoping the forum (or a Code-Level Support engineer) can point us in the right direction. Context on what we're building: We develop a Data Loss Prevention (DLP) product for macOS. We already hold the Endpoint Security entitlement (com.apple.developer.endpoint-security.client) and use it in production today for our core monitoring and policy-enforcement functionality. Why we're requesting DriverKit specifically: ESF gives us visibility and the ability to authorize/deny many file and process events, but it does not give us the control we need over removable/peripheral hardware. Two concrete gaps in our DLP policy enforcement that we're trying to close: Blocking data exfiltration via USB-connected Android devices — when an Android phone is plugged in, it mounts as a USB mass-storage/MTP-style device, and our policy needs to be able to prevent it from mounting or being written to, on a per-policy basis (e.g., disable an endpoint's ability to copy files to a connected Android device). Camera blocking — disabling the built-in/USB camera device at the hardware transport level as part of a DLP policy, rather than a userspace toggle that a privileged process could bypass. Our understanding was that "com.apple.developer.driverkit.transport.usb" combined with the HID/USB family entitlements would let us implement a DriverKit-based USB filtering driver to enforce this. Given the decline language about "security block or broad-scale system modifications," it sounds like Apple's position is that DriverKit is not intended to be used to build a general device-blocking layer this way. What I'm hoping to learn: Is per-policy USB mass-storage/MTP mounting control (blocking a specific class of device, e.g., Android phones, from mounting or transferring files) something DriverKit is intended to support at all for third-party DLP vendors, or is this fundamentally out of scope regardless of how the request is written up? If it is in scope, what should we change in the entitlement request write-up (use case description, scoping of which entitlements we actually need vs. what we requested) to make it approvable? We may have over-requested — for example, do we need family.networking and family.serial at all for USB mass-storage/camera blocking, or should we narrow the request to just the USB transport + HID/SCSI entitlements? Is there a preferred way to demonstrate that our use case is a scoped, policy-driven enterprise DLP control (with IT/MDM deployment, not a consumer app) rather than "broad-scale system modification," or does the entitlement review not distinguish on that basis? Any pointers — either on scoping this request correctly, or on whether this is simply not achievable via DriverKit and we should be looking at a different API — would be much appreciated. Happy to provide more detail on our exact enforcement flow if that's useful for a Code-Level Support ticket. Thanks in advance
1
0
359
2w
DriverKit entitlement eligibility for independently supporting an EOL third-party USB audio device
I am developing an independent macOS compatibility driver for the Avid/Digidesign Eleven Rack, an EOL USB audio device that does not have an Apple-silicon-compatible OEM driver. The existing hardware identifies as: Vendor ID: 0x0DBA — Digidesign/Avid Product ID: 0xB011 — Eleven Rack Transport: USB 2.0 high-speed isochronous audio The proposed implementation uses AudioDriverKit and USBDriverKit. It consists of a DriverKit system extension packaged inside a macOS control application. The USB entitlement would be restricted to this exact VID/PID. I am an independent developer and do not own the Digidesign/Avid VID. I am not manufacturing hardware or attempting to use that VID for a new USB product. The driver would only match existing Eleven Rack devices. The implementation is independently written for interoperability, and no Avid executable code would be included. I currently have a working direct user-space USB proof of concept, but I cannot properly activate and test the AudioDriverKit extension with SIP enabled without the required entitlements. Before enrolling in the paid Apple Developer Program, I would appreciate clarification on the following: Does Apple consider DriverKit development and distribution entitlement requests from independent developers supporting existing EOL hardware when the developer does not own the device’s VID? Is written authorization from the VID owner always required, or are these requests evaluated individually? Would restricting the USB transport entitlement to the exact 0x0DBA:0xB011 device affect eligibility? Is there a way to obtain an initial eligibility determination before purchasing Apple Developer Program membership? The anticipated entitlements are: com.apple.developer.driverkit com.apple.developer.driverkit.family.audio com.apple.developer.driverkit.transport.usb com.apple.developer.system-extension.install for the host application Restricted user-client access between the host application and driver I understand that the forum cannot grant an entitlement. I am trying to determine the appropriate process and whether manufacturer authorization is a prerequisite before submitting a formal request.
5
0
725
2w
IOPCIFamily matching precedence and runtime behavior for unmatched PCIe functions
I'm working on diagnostic tooling for PCIe storage devices and I've run into a gap in my understanding of how IOKit resolves matching against a single PCIe function, and what the kernel continues to do with a function that nothing claims. The scenario I'm designing around: an NVMe controller that is degraded but still enumerable. It responds to config space reads and completes some admin commands, but intermittently times out — in the worst case on Identify — which surfaces as a kernel panic rather than a recoverable error. For test and triage purposes I want the ability to leave such a device physically installed while preventing the storage stack from binding to it, scoped to that one function rather than to NVMe generally. Questions on the matching side: When two personalities match on IOPCIPrimaryMatch for the same vendor/device ID, is IOProbeScore the only tiebreaker? I've seen suggestions that which kext collection a personality lives in (boot vs. auxiliary) also influences the outcome, and I'd like to know whether that's genuinely part of the matching algorithm or an artifact of load ordering. If a higher-scored driver's probe() returns NULL, does the nub reliably fall through to the next candidate, including a family driver? Is there a case where a failed probe leaves the nub unmatched rather than retrying lower-scored candidates? Are there properties on an IOPCIDevice nub that gate matching independently of score? IOPCITunnelCompatible clearly does something like this for tunneled devices, which suggests the general mechanism exists — is there a documented, per-function form of it? Questions on runtime behavior: If a PCIe function ends up with no driver attached, what does IOPCIFamily continue to do with it? Specifically, does it may issue config space accesses, participate in the IOKit power management tree, transition the function to D3 on system sleep or on idle, and save/restore config space across wake? Related: does an unmatched function may get a DART/VT-d mapping established, and does IOPCIFamily poll or act on link status or AER state for it? The distinction in 4 and 5 matters a lot for my case. If an unmatched nub is genuinely inert from the device's point of view, blocking driver attachment is a complete solution. If IOPCIFamily is may driving power state transitions on it, then a device that fails during D3 entry or exit will still take the system down, and I need a different approach. Finally — is any of this reachable from DriverKit, or does a per-device matching override necessarily mean a kext? I'd rather build on something supported if a supported path exists. Happy to be pointed at headers or open-source IOPCIFamily if the answers are best read from source; I'm mainly trying to confirm the intended behavior rather than infer it from observation.
1
0
329
2w
After upgrading to iOS 18 and iOS 26, the project encounters an error retrieving BOOL values in the simulator. It works fine on a physical device.
I have updated to the latest official release: Xcode 26.5 with iOS 26 Simulator runtime, unfortunately the exact same problem still 100% reproduces only on the iOS Simulator. Important background: The production app uploaded to App Store runs perfectly on all physical iOS devices and Mac Catalyst, no logic error at all. The defect is isolated exclusively to simulator Debug environment. Two concrete problematic code snippets: Case 1: BOOL property overflow from system API @property (nonatomic, assign) BOOL isRunningOnMacOSX; // Assign value from NSProcessInfo self.isRunningOnMacOSX = [NSProcessInfo processInfo].isMacCatalystApp; On simulator, BOOL is signed char, the return value is truncated to a negative number. Since any non-zero value evaluates to true in C if() check, the branch is always incorrectly triggered. Case 2: __block BOOL returns garbage value after dispatch_sync GCD call (BOOL)isConnected { __block BOOL result = NO; dispatch_block_t block = ^{ result = (self->flags & kConnected) ? YES : NO; }; if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) { block(); } else { dispatch_sync(socketQueue, block); } NSLog(@"Logged result = %d", result); // Prints clean 0 in log return result; // Returns huge negative garbage integer only on simulator } When calling if ([aSocket isConnected]), it incorrectly enters the true branch. My analysis: This stems from inconsistent ABI handling of signed char return value zero-extension between simulator runtime, real ARM device and Mac Catalyst. Even in Xcode 26.5 stable release, the simulator still does not zero out high bits when extending 1-byte signed char to full register in Debug -O0 mode, leading to heap garbage value after cross-thread dispatch_sync. Current temporary workaround: Replace BOOL type with int internally and strictly store only 0 or 1 to bypass all signed char overflow and register extension issues. Could you help confirm whether this simulator ABI discrepancy is a known runtime limitation, or if there is any compiler/build setting to unify the BOOL behavior across simulator and physical devices? Thanks a lot.
0
0
327
3w
Toggle to enable Driverkit Driver not appearing in App Settings in iPadOS
We have an app which uses a DriverKit-based driver to communicate with an external device. In multiple iPadOS versions, users have been facing this issue where the option/toggle to enable/disable the Driver is not appearing in the App Settings. As a result, users have to uninstall/install the app to get the option again. Ideally, the option should always appear in the App Settings so that users can freely toggle it according to their needs. Due to this, the external devices connected to the iPad will not be detected. I have not seen this happen during development or in any of the iPad(s) that I have tested the app on. Has anyone seen this happen with their apps and if so, what is the issue/workaround? Is this a known bug only in some specific versions of iPadOS? Also, I have raised a feedback for the same here but there has been no reply. Thanks, Abishek.
5
0
715
3w
Correcting a line item on an already-submitted DriverKit USB Transport request
We ship an iPadOS app with an embedded USBDriverKit extension that drives Citizen/DNP dye-sub photo printers. It works: on a development-provisioned iPad the dext registers, matches, opens its user client and prints, verified on two units in hand (DNP DS-RX1 0x1343:0x0005, DNP QW410 0x1452:0x9201). The extension declares twelve IOKitPersonalities, each pinned to one exact idVendor/idProduct pair plus bConfigurationValue and bInterfaceNumber. Those twelve span two vendor IDs — 4931 (0x1343, Citizen Systems) and 5202 (0x1452, Dai Nippon Printing) — because the same printer families ship Citizen-badged on one and DNP-badged on the other. We have one USB Transport – VendorID request per vendor ID, both currently Submitted. Thread 842748 already answered the scope question for us, so I'm not asking that one: at twelve devices we read vendor-level as the right ask rather than twelve VendorID+ProductID requests, and we've kept the personalities narrow so the entitlement is a ceiling rather than what actually matches. Please correct me if that's the wrong reading for two vendor IDs rather than one. My actual question is about a mistake in one of the submissions. The older request also asked for UserClient Access, which we now understand is macOS-only (com.apple.developer.driverkit.userclient-access lists DRIVER_KIT and MAC_OS, not IOS). We don't need it — on iPadOS the app opens the dext's user client with com.apple.developer.driverkit.communicates-with-drivers, which needs no approval. Does an inapplicable entitlement on a submitted request need to be formally withdrawn, or is it simply ignored during review? I'd rather not leave a macOS-only entitlement sitting on an iPadOS request if that's something a reviewer has to resolve. If it does need correcting, what's the mechanism? Re-filing would create a third request, and I'd rather not muddy the queue. (Developer Support told me request handling is outside their scope, which is what brings me here.) Is there any way to indicate that two requests belong to one driver extension and are only useful together? Happy to post the Info.plist personalities or the dext's entitlements if useful. Thank you.
1
0
386
3w
IOUserSCSIParallelInterfaceController: what triggers UserLogicalUnitResetRequest?
I am working on a DriverKit driver and we are subclassing IOUserSCSIParallelInterfaceController. I have implemented UserLogicalUnitResetRequest end-to-end and it sends a real Task management IU to the controller and returns the correct kSCSIServiceResponse_*. When I call the hook from within the dext manually it works but I am not able to invoke this UserLogicalUnitResetRequest from macOS. My question is, under what conditions does macOS itself invoke this hook (or the other five TMF hooks - abort/set, TargetReset, ClearACA/TaskSet)? I tried to insert a gate at the top of UserProcessParallelTask, which for one chosen target, swallows the incoming task without submitting it to the controller and without completing the OSAction. I then ran normal APFS filesystem IO against the target and observed following: Every stalled command arrives with SCSIUserParallelTask.fTimeoutInMilliSec = 0. The command hang indefinitely. None of the TMF hooks are ever invoked by the framework. I am not sure if I am doing something wrong here. Is fTimeoutInMilliSec = 0 on filesystem IO expected? Is there a way for the dext to surface a shorter deadline that the framework will watchdog? What actually invokes the TMF hooks- filesystem-IO timeout escalation, storage recovery, or is there an expectation that the dext runs its own per-command watchdog and invokes its reset code internally? Any help would be really appreciated! Thank you for your time!
2
0
399
3w
HID Entitlement Configuration Guide
HID Entitlement Configuration Guide: NOTE:The document assumes you're already familiar with the DEXT loading process, as described here. Here are the three core kernel support drivers and their corresponding HID entitlements: AppleUserHIDDevice-> com.apple.developer.driverkit.family.hid.device AppleUserHIDEventService-> com.apple.developer.driverkit.family.hid.eventservice IOHIDInterface-> com.apple.developer.driverkit.transport.hid When building a HID DEXT, you'll first determine your kernel support (IOClass) driver, then include that entitlement in your DEXT. Including any other HID entitlement is unnecessary. Additional Entitlements There are two other HID-related entitlements worth noting: com.apple.developer.driverkit.family.hid.virtual.device -> This entitlement is a defunct entitlement that has no function on any of our platforms. It should not be included in any product and will be removed from the documentation in the future (r.184046926). com.apple.developer.hid.virtual.device -> This entitlement controls access to the CoreHID virtual device API. This is NOT a DEXT entitlement and should never be included in a DEXT. Note that the concept of "virtual" devices in DriverKit is somewhat misleading. A DEXT can publish a "virtual" device, but that’s because a DEXT is the ultimate arbitrator that controls what's visible to the system AT ALL. Putting that in more concrete terms, the system itself doesn't really differentiate between: A standard USB HID device. A software-only HID device. A Thunderbolt mouse (hypothetical). A Ethernet mouse (hypothetical). Like most other IOKit families, the system makes no strong attempt to identify the transport bus[1], so, as far as the system is concerned, all of those are just "HID devices". Within that architecture, CoreHID virtual device API works by using an existing kernel driver to publish new HID devices to the system, duplicating exactly the same architecture a DEXT-based virtual HID driver would use. There's no reason to prefer a DEXT-based solution over CoreHID, as the DEXT simply requires more work without significant benefit. [1] Many places in the system do include information about "where" a device is located. In most cases, this is nothing more than a string directly published by the corresponding driver as an IORegistry key/value. In other words, a device labeled "USB" could easily have been labeled "FireWire", "PCI", "Nowhere", or anything else the driver chose to label it. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
290
3w
How to sign a DEXT
Kevin's Guide to DEXT Signing The question of "How do I sign a DEXT" comes up a lot, so this post is my attempt to describe both what the issues are and the best current solutions are. So... The Problems: When DEXTs were originally introduced, the recommended development signing process required disabling SIP and local signing. There is a newer, much simpler process that's built on Xcode's integrated code-signing support; however, that newer process has not yet been integrated into the documentation library. In addition, while the older flow still works, many of the details it describes are no longer correct due to changes to Xcode and the developer portal. DriverKit's use of individually customized entitlements is different than the other entitlements on our platform, and Xcode's support for it is somewhat incomplete and buggy. The situation has improved considerably over time, particularly from Xcode 15 and Xcode 16, but there are still issues that are not fully resolved. To address #1, we introduced "development" entitlement variants of all DriverKit entitlements. These entitlement variants are ONLY available in development-signed builds, but they're available on all paid developer accounts without any special approval. They also allow a DEXT to match against any hardware, greatly simplifying working with development or prototype hardware which may not match the configuration of a final product. Unfortunately, this also means that DEXT developers will always have at least two entitlement variants (the public development variant and the "private" approved entitlement), which is what then causes the problem I mentioned in #2. The Automatic Solution: If you're using Xcode 16 or above, then Xcode's Automatic code sign support will work all DEXT Families, with the exception of distribution signing the PCI and USB Families. For completeness, here is how that Automatic flow should work: Change the code signing configuration to "Automatic". Add the capability using Xcode. (USB & PCI) Edit your Entitlement.plist to include the correct "Development Only" configuration: USB Development Only Configuration: <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <string>*</string> </dict> </array> PCI Development Only Configuration: <key>com.apple.developer.driverkit.transport.pci</key> <array> <dict> <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&amp;0x00000000</string> </dict> </array> If you've been approved for one of these entitlements, the one oddity you'll see is that adding your approved capability will add both the approved AND the development variant, while deleting either will delete both. This is a visual side effect of #2 above; however, aside from the exception described below, it can be ignored. Similarly, you can sign distribution builds by creating a build archive and then exporting the build using the standard Xcode flow. Debugging Automatic Code-signing In a new project, the flow I describe above should just work; however, if you're converting an existing project, you may get code signing errors, generally complaining about how the provisioning profile configuration doesn't match. In most cases, this happens because Xcode is choosing to reuse a previously downloaded profile with an older configuration instead of generating a new configuration which would then include the configuration changes you made. Currently, you can find these profile files in: ~/Library/Developer/Xcode/UserData/Provisioning Profiles ...which can make it easier to find and delete the specific profile (if you choose). However, one recommendation I'd have here is to not treat the contents of that folder as "precious" or special. What automatic code signing actually does is generate provisioning profiles "on demand", so if you delete an automatic profile... Xcode will just generate it again at the next build. Manually generating profiles is more cumbersome, but the solution there is to preserve them as a separate resource, probably as part of your project data, NOT to just "lose" them in the folder here. If they get deleted from Xcode's store, then you can just copy them back in from your own store (or using Xcode, which can manually download profiles as well). The advantage of this approach is that when profiles "pile up" over time (which they tend to do), you can just delete[1] all of them then let Xcode regenerate the ones you're actually trying to investigate. In terms of looking at their contents, TN3125: Inside Code Signing: Provisioning Profiles has the details of how to see exactly what's there. [1] Moving them somewhere else works too, but could indicate a fear of commitment. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
1
Boosts
1
Views
2.6k
Activity
Mar ’26
Basic introduction to DEXT Matching and Loading
Note: This document is specifically focused on what happens after a DEXT has passed its initial code-signing checks. Code-signing issues are dealt with in other posts. Preliminary Guidance: Using and understanding DriverKit basically requires understanding IOKit, something which isn't entirely clear in our documentation. The good news here is that IOKit actually does have fairly good "foundational" documentation in the documentation archive. Here are a few of the documents I'd take a look at: IOKit Fundamentals IOKit Device Driver Design Guidelines Accessing Hardware From Applications Special mention to QA1075: "Making sense of IOKit error codes", which I happened to notice today and which documents the IOReturn error format (which is a bit weird on first review). Those documents do not cover the full DEXT loading process, but they are the foundation of how all of this actually works. Understanding the IOKitPersonalities Dictionary The first thing to understand here is that the "IOKitPersonalities" is called that because it is in fact a fully valid "IOKitPersonalities" dictionary. That is, what the system actually uses that dictionary "for" is: Perform a standard IOKit match and load cycle in the kernel. The final driver in the kernel then uses the DEXT-specific data to launch and run your DEXT process outside the kernel. So, working through the critical keys in that dictionary: "IOProviderClass"-> This is the in-kernel class that your in-kernel driver loads "on top" of. The IOKit documentation and naming convention uses the term "Nub", but the naming convention is not consistent enough that it applies to all cases. "IOClass"-> This is the in-kernel class that your DEXT attaches to and works through. This is where things can become a bit confused, as some families work by: Routing all activity through the provider reference so that the DEXT-specific class does not matter (PCIDriverKit). Having the DEXT subclass a specific subclass which corresponds to a specific kernel driver (SCSIPeripheralsDriverKit). This distinction is described in the documentation, but it's easy to overlook if you don't understand what's going on. However, compare PCIDriverKit: "When the system loads your custom PCI driver, it passes an IOPCIDevice object as the provider to your driver. Use that object to read and write the configuration and memory of your PCI hardware." Versus SCSIPeripheralsDriverKit: Develop your driver by subclassing IOUserSCSIPeripheralDeviceType00 or IOUserSCSIPeripheralDeviceType05, depending on whether your device works with SCSI Block Commands (SBC) or SCSI Multimedia Commands (SMC), respectively. In your subclass, override all methods the framework declares as pure virtual. The reason these differences exist actually comes from the relationship and interactions between the DEXT families. Case in point, PCIDriverKit doesn't require a specific subclass because it wants SCSIControllerDriverKit DEXTs to be able to directly load "above" it. Note that the common mistake many developers make is leaving "IOUserService" in place when they should have specified a family-specific subclass (case 2 above). This is an undocumented implementation detail, but if there is a mismatch between your DEXT driver ("IOUserSCSIPeripheralDeviceType00") and your kernel driver ("IOUserService"), you end up trying to call unimplemented kernel methods. When a method is "missing" like that, the codegen system ends up handling that by returning kIOReturnUnsupported. One special case here is the "IOUserResources" provider. This class is the DEXT equivalent of "IOResources" in the kernel. In both cases, these classes exist as an attachment point for objects which don't otherwise have a provider. It's specifically used by the sample "Communicating between a DriverKit extension and a client app" to allow that sample to load on all hardware but is not something the vast majority of DEXT will use. Following on from that point, most DEXT should NOT include "IOMatchCategory". Quoting IOKit fundamentals: "Important: Any driver that declares IOResources as the value of its IOProviderClass key must also include in its personality the IOMatchCategory key and a private match category value. This prevents the driver from matching exclusively on the IOResources nub and thereby preventing other drivers from matching on it. It also prevents the driver from having to compete with all other drivers that need to match on IOResources. The value of the IOMatchCategory property should be identical to the value of the driver's IOClass property, which is the driver’s class name in reverse-DNS notation with underbars instead of dots, such as com_MyCompany_driver_MyDriver." The critical point here is that including IOMatchCategory does this: "This prevents the driver from matching exclusively on the IOResources nub and thereby preventing other drivers from matching on it." The problem here is that this is actually the exceptional case. For a typical DEXT, including IOMatchCategory means that a system driver will load "beside" their DEXT, then open the provider blocking DEXT access and breaking the DEXT. DEXT Launching The key point here is that the entire process above is the standard IOKit loading process used by all KEXT. Once that process finishes, what actually happens next is the DEXT-specific part of this process: IOUserServerName-> This key is the bundle ID of your DEXT, which the system uses to find your DEXT target. IOUserClass-> This is the name of the class the system instantiates after launching your DEXT. Note that this directly mimics how IOKit loading works. Keep in mind that the second, DEXT-specific, half of this process is the first point your actual code becomes relevant. Any issue before that point will ONLY be visible through kernel logging or possibly the IORegistry. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
1
Boosts
0
Views
1.9k
Activity
2w
DriverKit USB Transport entitlement request pending — iPadOS Photo Booth with DNP / Citizen / HiTi printers
Hello Apple Developer Support, We have submitted a DriverKit entitlement request for our iPadOS photo booth application, which uses a USB DriverKit extension to communicate with professional dye-sublimation photo printers over USB-C. Our request covers one USB Transport configuration with the following Vendor IDs: 0x1343 (4931) — DNP / Citizen 0x1452 (5202) — DNP 0x0D16 (3350) — HiTi The DriverKit extension is used exclusively by our own iPadOS application, and we do not require UserClient Access. Our entitlement request is currently pending. We would appreciate any guidance from the DriverKit team regarding the review of our request. Request ID: 2DN73H7DCY Thank you.
Replies
0
Boosts
0
Views
7
Activity
1h
Read file with System Network Extension from App Group
I have trouble with reading a file from an App Group with my System Network Extension. The app group container is found successfully. However the file read returns empty. In the app itself the same code runs fine and returns a string array of items found in the file. Code: func readFile() - [String] {         var jsonResult: [String] = []         guard let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppConstants.groupID) else {             fatalError()         }         let fileURL = containerURL.appendingPathComponent("file.json")         if let data = try? NSData(contentsOfFile: fileURL.path, options: .mappedIfSafe) as Data {             if let json = try? JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) {                 jsonResult = json as! [String]             }         }         os_log("jsonResult: %{public}@", jsonResult)         return jsonResult     } Log: default 09:42:19.486793+0200 app-network-extension container_create_or_lookup_app_group_path_by_app_group_ identifier: success default 09:42:20.105792+0200 app-network-extension jsonResult: ( ) Edit, after more digging: fileURL is different! App: file:///Users/me/Library/Group%20Containers/ SysExt: file:///private/var/root/Library/Group%20Containers/
Replies
4
Boosts
1
Views
1.4k
Activity
5h
What is the supported DriverKit Stop/drain sequence for an IOUserClient operation queue?
Environment: macOS 26.6.2 (25G83), Apple silicon Xcode 26.6 (17F113) DriverKit SDK 25.5 I am implementing a DriverKit IOService with an IOUserClient. This is a lifecycle and object-ownership question independent of the device protocol. The intended design admits at most one user client during a provider lifetime. Lifecycle methods run on the provider’s default queue, while IOUserClient ExternalMethod requests run on a separate serial IODispatchQueue. At most one device request may be in flight. The shutdown invariant we need is: Stop accepting new requests. Allow every accepted request to complete exactly once, or cancel it. Observe completion of the operation queue’s cancellation handler. Call the inherited Stop implementation last. Perform no provider access afterward. The relevant public documentation is: IOService::Stop: https://developer.apple.com/documentation/driverkit/ioservice/stop IODispatchQueue::Cancel: https://developer.apple.com/documentation/driverkit/iodispatchqueue/cancel IOService::SetDispatchQueue: https://developer.apple.com/documentation/driverkit/ioservice/setdispatchqueue For the normal path, the proposed sequence is conceptually: Stop(provider): close request admission operationQueue->Cancel(cancellationHandler) wait for the cancellation handler from the separate queue super::Stop(provider) I need clarification of the complete supported public API contract: If IODispatchQueue::Cancel returns a non-success result, is its cancellation handler still guaranteed to execute? If it is not, what supported action lets Stop keep the provider and user client valid until previously accepted work is no longer capable of accessing them? Is it supported for the provider and its one user client to share the provider-owned serial operation queue? If the IOUserClient stops independently, must it own and cancel a separate queue, or is there a supported per-client drain mechanism that does not cancel provider-owned work? Is the driver’s public IOService::Stop override guaranteed to run on every termination path where accepted user-client work must be drained, including when the provider is already inactive or the DriverKit server has slept? If not, which public lifecycle callback supplies that drain point? Is blocking the provider’s default queue inside Stop while awaiting the cancellation handler from a separate operation queue the supported interpretation of “wait for your cancellation handlers”? If not, what public continuation mechanism should be used before calling inherited Stop? We also observed one power-management panic after sleep/wake: HiMDScsiDriver::setPowerState(..., 0 -> 4) timed out after 20342 ms The DEXT does not currently override SetPowerState. This panic motivates the lifecycle review, but I am not treating it as proof that the Stop/drain design caused the timeout. I am looking specifically for a supported public DriverKit sequence. I do not want to rely on private framework entry points or infer object-lifetime guarantees from a successful build or experiment.
Replies
4
Boosts
0
Views
850
Activity
2d
IOConnectMapMemory questions
I am developing a dext that is running into issues pertaining to IOConnectMapMemory (at least I think so). There are 3 parts of code that are involved, the dext (which allocates the memory in the first place), a user client library which is involved in connecting to the dext and releasing when the hardware is removed, and finally some processing code (at the user level) which executes on this shared block of memory from the dext. The shared memory is allocated using an IOBufferMemoryDescriptor: IOBufferMemoryDescriptor::Create(kIOMemoryDirectionNone, sizeof(sharedMemoryBlock), IOVMPageSize, &(ivars->mSharedMemoryBlockMemDesc)); The User Client Library acquires a mapped pointer to this memory by calling IOConnectMapMemory: IOConnectMapMemory(mConnect, kMemoryType_SharedMemoryBlock, mach_task_self(), (mach_vm_address_t*)&mUserClientSharedBlockPtr, (mach_vm_size_t*)&mSizeOfUserClientSharedBlock, kIOMapAnywhere); …which triggers the dext’s IOUserClient subclass' “CopyClientMemoryForType_Impl”. That code adds a retain and returns a pointer to the IOBufferMemoryDescriptor: case kMemoryType_SharedMemoryBlock: // error checks first (make sure it’s allocated and initialized, etc) ivars->mSharedMemoryBlockMemDesc->retain(); *memory = ivars->mSharedMemoryBlockMemDesc; break; IOConnectMapMemory returns the “mapped pointer” (in mUserClientSharedBlockPtr) to the User Client Library, which in turn provides it to the processing code. The processing code checks the pointer validity, and if valid, runs its processing. This worked fine with a kext implementation. This fails with dext implementation, because during the processing call (after validity check but during usage) the mapped pointer can become NULL, which seems to be against the design pattern, and causes the application to crash due to an access violation (dereferencing NULL). I assume I am doing something incorrect here, but I’m not seeing what it is. The memory was retained, so it should not be deleted until the User Client Library has released it, but the only release available would be IOConnectUnmapMemory, and that fails with “invalid argument” (0xE00002C2) after the device is hot-unplugged. I am not finding IOConnectMapMemory examples on developer.apple.com. I have verified via the forums that IOConnectMapMemory is still a recommended practice with DriverKit development: https://developer.apple.com/forums/thread/803947?answerId=862249022#862249022 . What’s the trick here for stability? The device is a peripheral which can be unplugged or turned off at any time, which would result in the dext and user client library code tearing down the structures and memory, but it should be able to do so safely without causing access violations. (Note, this has been simplified for the purpose of focusing the question, in reality there are 4 separate memory blocks which are shared in this fashion: two ring buffers, main engine status, and client status. They each use their own memory_type definition, but a general solution is needed and can be applied to all 4, and there can be multiple clients at any point in time).
Replies
1
Boosts
0
Views
997
Activity
3d
Network UPS?
I found some nice code that implements a NUT client, and now I want to take the next step -- I would like to get it to show up as a UPS for macOS. But I've never done anything with IOKit... and there don't seem to be a lot of examples of, maybe, IOPowerSources?
Replies
6
Boosts
0
Views
395
Activity
3d
HIDVirtualDevice digitizer pen: position, proximity and tip switch reach NSEvent, but tablet pressure is always 0 — is pen pressure supported at all?
I'm building a virtual pen digitizer with HIDVirtualDevice (CoreHID, macOS 26.2, com.apple.developer.hid.virtual.device entitlement granted, Developer ID signed with the provisioning profile embedding the entitlement). The device is created and activated fine and shows up as expected: hidutil list: 0xface 0xbeef UsagePage 13 Usage 2 Transport Virtual "Hej Stylus Virtual Pen" AppleUserHIDEventService / AppleUserHIDEventDriver Report descriptor (Digitizer/Pen application collection, Stylus physical collection, 7-byte input report): 05 0D Usage Page (Digitizer) 09 02 Usage (Pen) A1 01 Collection (Application) 09 20 Usage (Stylus) A1 00 Collection (Physical) 09 42 Usage (Tip Switch) 09 32 Usage (In Range) 15 00 25 01 75 01 95 02 81 02 ; 2 bits 95 06 81 03 ; 6 bits padding (Const) 05 01 09 30 09 31 ; Generic Desktop X, Y 16 00 00 26 FF 7F 75 10 95 02 81 02 ; 0..32767, 16 bit each 05 0D 09 30 ; Digitizer / Tip Pressure 16 00 00 26 FF 1F 75 10 95 01 81 02 ; 0..8191, 16 bit C0 C0 I feed it a synthetic stream at 60 Hz (X sweep, Y fixed, tip switch down, in range, pressure ramping 0→8191) via dispatchInputReport(data:timestamp:) and observe the results with a global NSEvent monitor (.tabletProximity, .tabletPoint, .leftMouseDown/Up/Dragged, .mouseMoved) plus the raw CGEvent fields. What works tabletProximity: isEnteringProximity=1, pointingDeviceType=.pen, vendorID=0xFACE, tabletID=0xBEEF, systemTabletID assigned. All movement arrives as tabletPoint / mouseMoved with subtype == .tabletPoint; positions are exact. Tip switch maps to leftMouseDown / leftMouseUp correctly (verified by toggling the tip bit with pressure held at max). capabilityMask on the proximity event is 0x407 = NX_TABLET_CAPABILITY_DEVICEIDMASK | ABSXMASK | ABSYMASK | PRESSUREMASK — so the system declares pressure capability for this device. What doesn't NSEvent.pressure, kCGTabletEventPointPressure and kCGMouseEventPressure are always 0.000, on every event type, including with a constant maximum pressure value (8191). NSEvent.buttonMask is 1 (pen tip) and kCGTabletEventPointButtons is 1, so the report is being parsed — the pressure field just never makes it into the tablet event data. Things I've established / tried The pressure value is parsed and does influence touch/click: with tip switch held down and pressure held at 0, no mouse down is ever generated. With pressure ramping, the click happens at exactly 75 % of the logical range. Reading the open-source IOHIDEventDriver::parseDigitizerTransducerElement explains this: Tip Pressure is read with kIOHIDValueScaleTypeCalibrated, but only X/Y/Z elements get a calibration, and an uncalibrated element scales to −1…+1 — so raw 0…8191 becomes −1…+1 and the touch threshold (+0.5) sits at 75 %. Changing Logical Minimum to −8191 (so raw 0…8191 maps to 0…1) moves the click to exactly 50 % — confirming the model. Pressure in the event data is still 0. Adding Physical Minimum/Maximum and a Unit to the pressure element: no change. hidutil monitor no longer exists on macOS 26, so I can't inspect the IOHIDEvent digitizer fields directly. This looks like the same behaviour reported for kext-based digitizers since macOS 10.12 (developer.apple.com/forums thread "IOHIPointing dispatchAbsolutePointerEvent not works" and its sibling: "the pressure information is there from the transducer, the OS doesn't respond to it on 10.12+"). The tablet-pressure dispatch in the open-source IOHIDEventService::dispatchDigitizerEventWithOrientation is commented out, and the userspace IOHIDEventTranslation isn't open source, so I can't tell where the value is dropped. Questions Is pen pressure from a HIDVirtualDevice (or any generic HID digitizer handled by AppleUserHIDEventDriver) expected to reach NSEvent.pressure / kCGTabletEventPointPressure at all on current macOS? Or is that path reserved for vendor drivers posting tablet events themselves? If it is supported: which descriptor properties does the digitizer→tablet translation require for pressure — specific usages (Transducer Index, Barrel Switch, Tilt, Twist), Report ID, Physical range/Unit on the pressure element, a Feature report, or a particular device property (e.g. something in HIDVirtualDevice.Properties / kIOHIDDigitizer* keys)? Is there a documented way to set element calibration for a virtual device so Tip Pressure scales 0…1 instead of −1…+1 without abusing Logical Minimum? Is there a supported diagnostic on macOS 26 to see the IOHIDEvent digitizer fields (pressure, touch, event mask) that the event system builds from my reports, now that hidutil monitor is gone? Happy to file a Feedback with the full project and a sysdiagnose if that helps.
Replies
2
Boosts
0
Views
82
Activity
5d
iPhone 17 Pro loses all touchscreen input on iOS 27 public 24A437 — reproducible on RC 24A435
Device: iPhone 17 Pro 256GB Affected builds: • iOS 27 RC — 24A435 • iOS 27 public release — 24A437 Known working version: • iOS 26.7 DESCRIPTION I am seeing a reproducible total loss of touchscreen input on this specific iPhone 17 Pro when running iOS 27. Before today's test, the device was running iOS 26.7 and the touchscreen was working normally. On September 14, I updated through the official OTA Software Update to iOS 27.0 public release, build 24A437. Beta Updates were disabled. After the update completed, the iPhone booted normally and reached the Hello screen. The display renders normally. Physical buttons respond normally. However, all touchscreen input is completely unavailable. No taps or swipes are recognized anywhere on the display, so it is not possible to proceed past the Hello screen. REPRODUCIBLE ON IOS 27 RC The exact same behavior previously occurred on iOS 27 RC build 24A435. To eliminate backup corruption, user data, apps and settings as possible variables, I performed a complete clean restore of 24A435 using Apple Configurator. No backup was restored. No apps were installed. No user data was restored. No previous settings were restored. Immediately after the clean restore, at the initial Hello screen, touchscreen input was still completely unavailable. Restoring the same device back to iOS 26 immediately restored touchscreen functionality. REPRODUCTION HISTORY iOS 26.7 → Touchscreen works normally iOS 27 RC 24A435 → Touchscreen completely unresponsive after boot Clean restore of 24A435 → Touchscreen still completely unresponsive at the initial Hello screen Restore back to iOS 26 → Touchscreen functionality returns iOS 27 public 24A437 → Touchscreen completely unresponsive again after boot DIAGNOSTICS Apple has already performed: • Remote diagnostics — passed • MRI — passed • Multi-Touch diagnostic — passed None of these diagnostics detected a hardware failure. The issue was reported through Feedback Assistant before the public release: Feedback ID: FB24728805 I also have an active Apple Support case, and the device is being evaluated by an Apple Authorized Service Provider. QUESTION / TECHNICAL OBSERVATION The particularly unusual aspect is the repeatability across OS versions on the same physical device: iOS 26 → touch works iOS 27 → touch does not work iOS 26 → touch works again iOS 27 → touch does not work again I am not assuming that the root cause is purely software or purely hardware. I am interested in whether this could involve touchscreen/HID initialization, digitizer-related firmware, or an interaction between iOS 27 and a particular hardware/display/controller revision. Has anyone observed a similar condition where: • the display continues rendering normally; • physical buttons continue working; • all touchscreen input is lost immediately after booting iOS 27; • a clean restore of iOS 27 does not resolve it; and • restoring the same device to iOS 26 restores touchscreen functionality? If anyone has reproduced this on another iPhone 17 Pro or 17 Pro Max, the exact model and iOS build would be particularly useful. RELATED PUBLIC DISCUSSIONS Apple Support Community: https://discussions.apple.com/thread/256356702 MacRumors: https://forums.macrumors.com/threads/iphone-17-pro-touchscreen-completely-dead-on-ios-27-public-24a437-same-issue-on-rc-24a435.2489323/
Replies
0
Boosts
0
Views
353
Activity
6d
Which virtual-HID entitlement path for a gamepad app — CoreHID or DriverKit? (Request H8Q3K9CK7Z stuck 2.5 months)
I'm building a macOS app that creates a virtual gamepad (Xbox-style HID device) so games can see input coming from a companion mobile app — similar in spirit to Karabiner-DriverKit-VirtualHIDDevice, but for a gamepad rather than keyboard/mouse. I submitted a Capability Request for "HID Virtual Device" (com.apple.developer.hid.virtual.device) under Capability Requests in Certificates, Identifiers & Profiles: Request ID: H8Q3K9CK7Z Submitted: June 30, 2026 Status: still shows "Submitted" with no change, ~2.5 months later Two questions I'd appreciate guidance on: Is this request queue still actively processed? I haven't received any request for more information, and there's been no status change since submission. Is 2.5 months a normal wait right now, or should I be following up through a different channel? Is the app-level CoreHID entitlement (com.apple.developer.hid.virtual.device) actually sufficient for a gamepad to be detected by GameController.framework (i.e. GCController.controllers()), or does that require wrapping the virtual device in a DriverKit driver extension instead, similar to how Karabiner ships com.apple.developer.driverkit + .transport.hid + .family.hid.device + .family.hid.eventservice alongside this same CoreHID key, rather than relying on the CoreHID entitlement standalone? Any clarity on the right entitlement combination, and on whether I should expect movement on H8Q3K9CK7Z, would be a big help.
Replies
1
Boosts
0
Views
660
Activity
6d
Lessons learned shipping an open-source NetworkingDriverKit NIC driver (Realtek RTL8127, 10GbE)
I've just shipped a signed NetworkingDriverKit driver for the Realtek RTL8127 10GbE PCIe NICs on Apple Silicon, source at https://github.com/stefb69/RTL812xLucy (directory RTL8127Dext). It runs at line rate (9.4 Gbit/s each way at MTU 1500, 9.9 with jumbo frames) with TSO, checksum offload and four TX queues by service class. Since there are very few public NetworkingDriverKit drivers to learn from, here is what cost me the most time, in case it saves someone else a week. Three of these are filed as feedback. TX packets from native Skywalk flows have a 2-byte data offset (FBxxxxxxxx). getDataVirtualAddress() / getDataIOVirtualAddress() return the buffer base; the frame starts at getDataOff(). BSD-path packets (ping, curl, ssh, DHCP) have offset 0, Network.framework flows (Safari, URLSession, App Store, codesign --timestamp) have offset 2. If you DMA from the base, everything "works" except every modern client, which sits in SYN_SENT. The headers don't mention it. getMaxTransferUnit() is the maximum MTU, not the current one (FBxxxxxxxx). It is read once at registerEthernetInterface() and becomes the hard ceiling for ifconfig mtu; return your current 1500 and jumbo frames fail with EINVAL before your dext is called. Don't call bpfAttach() on macOS 26.6 (FBxxxxxxxx). It worked once, then panicked the kernel inside IOSkywalkFamily when the dext was replaced while tcpdump was attached. Without it, tcpdump on your interface only sees host-path frames, not native flows, so debugging point 1 is done from the peer side. Smaller ones: the personality needs IOClass = IOUserNetworkEthernet and CFBundleIdentifierKernel = com.apple.iokit.IOSkywalkFamily, not IOUserService, or super::Start fails with 0xe00002bc. All queues are created disabled: setEnable(true) in setInterfaceEnable(), plus requestDequeue() on the TX queues when the link comes up. setMulticastAddresses() must be implemented or no multicast group is ever joined (mDNS and IPv6 solicited-node are silently dead). Release dispatch sources from the Cancel() completion block, not right after Cancel(), or the dext crashes at every upgrade. The dext bundle must be named .dext or the host app reports "Extension not found in App bundle". Dext os_log lines show up as kernel: messages with the .dext bundle as sender; use %{public}s. Performance question for Apple engineers: with eight or more parallel TCP senders at MTU 1500 the stack emits ~3 KB TSO packets at ~160k packets/s and the dext saturates one core around 4.5 Gbit/s (fine at MTU 9000, fine with one to four streams). Is IOUserNetworkPacketPoller the intended answer for per-packet cost in a NIC dext, and is there any guidance on batch sizes for IOUserNetworkTxSubmissionQueue dequeues?
Replies
1
Boosts
0
Views
205
Activity
1w
DriverKit USB Transport entitlement pending 6+ weeks (DNP + HiTi photo printers) - same VIDs already approved for another team
We build an iPad photo booth app and have a DriverKit USB transport driver for DNP/Citizen and HiTi dye-sub photo printers. These printers have no vendor drivers for iPadOS, so a dext is the only way to print from an iPad. The driver is complete and hardware-validated on both printer families under a development profile. The only thing blocking distribution is the entitlement. Our requests have been in "Submitted" state since July: 72B5P53K28 (July 24, 2026): DriverKit, USB Transport, UserClient Access, vendor IDs 4931 (0x1343) and 5202 (0x1452) 4Z76G958GF (July 25, 2026): amendment adding vendor ID 3350 (0x0D16, HiTi Digital) Developer Support case 20000136465729 was opened for this and acknowledged on September 1, but there has been no decision. I noticed in https://developer.apple.com/forums/thread/826658 that a DTS engineer confirmed the identical configuration (one USB dext, vendor IDs 3350, 4931, 5202) was approved for another team on May 5, so the scope itself is clearly something Apple grants. Is there anything further needed from us to move these along, or a way to get a status on them? Team ID: 7B3398CSQU
Replies
2
Boosts
0
Views
459
Activity
1w
DriverKit entitlement for USB transport - support all vendor id's
Hey, We are developing a dext that would like to match with all USB devices, no matter the vendor. We use VendorID = * in the plist of the Dext to help achieve this when running it locally without entitlements. I know that the transport.usb entitlement requires a list of Vendor id's, but is it possible to receive an entitlement which is suitable for all VID's? Kind of like this: <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <string>*</string> </dict> </array> Thanks
Replies
2
Boosts
1
Views
1.2k
Activity
1w
Guidance requested: DriverKit entitlement follow-up for DLP application (Endpoint Security entitlement already granted)
Entitlements requested: com.apple.developer.driverkit.userclient-access com.apple.developer.driverkit.transport.usb com.apple.developer.driverkit.transport.hid com.apple.developer.driverkit.family.hid.eventservice com.apple.developer.driverkit.family.serial com.apple.developer.driverkit.family.scsicontroller com.apple.developer.driverkit.family.networking com.apple.developer.driverkit.family.hid.device , and the base com.apple.developer.driverkit entitlement Hi all, We recently received a decline on the DriverKit entitlement set listed above. The response noted: "Technical details within DriverKit mean that it is not a viable solution for security block or broad-scale system modifications." I'd like to get some clarity on how to bring our request in line with what's approvable, and I'm hoping the forum (or a Code-Level Support engineer) can point us in the right direction. Context on what we're building: We develop a Data Loss Prevention (DLP) product for macOS. We already hold the Endpoint Security entitlement (com.apple.developer.endpoint-security.client) and use it in production today for our core monitoring and policy-enforcement functionality. Why we're requesting DriverKit specifically: ESF gives us visibility and the ability to authorize/deny many file and process events, but it does not give us the control we need over removable/peripheral hardware. Two concrete gaps in our DLP policy enforcement that we're trying to close: Blocking data exfiltration via USB-connected Android devices — when an Android phone is plugged in, it mounts as a USB mass-storage/MTP-style device, and our policy needs to be able to prevent it from mounting or being written to, on a per-policy basis (e.g., disable an endpoint's ability to copy files to a connected Android device). Camera blocking — disabling the built-in/USB camera device at the hardware transport level as part of a DLP policy, rather than a userspace toggle that a privileged process could bypass. Our understanding was that "com.apple.developer.driverkit.transport.usb" combined with the HID/USB family entitlements would let us implement a DriverKit-based USB filtering driver to enforce this. Given the decline language about "security block or broad-scale system modifications," it sounds like Apple's position is that DriverKit is not intended to be used to build a general device-blocking layer this way. What I'm hoping to learn: Is per-policy USB mass-storage/MTP mounting control (blocking a specific class of device, e.g., Android phones, from mounting or transferring files) something DriverKit is intended to support at all for third-party DLP vendors, or is this fundamentally out of scope regardless of how the request is written up? If it is in scope, what should we change in the entitlement request write-up (use case description, scoping of which entitlements we actually need vs. what we requested) to make it approvable? We may have over-requested — for example, do we need family.networking and family.serial at all for USB mass-storage/camera blocking, or should we narrow the request to just the USB transport + HID/SCSI entitlements? Is there a preferred way to demonstrate that our use case is a scoped, policy-driven enterprise DLP control (with IT/MDM deployment, not a consumer app) rather than "broad-scale system modification," or does the entitlement review not distinguish on that basis? Any pointers — either on scoping this request correctly, or on whether this is simply not achievable via DriverKit and we should be looking at a different API — would be much appreciated. Happy to provide more detail on our exact enforcement flow if that's useful for a Code-Level Support ticket. Thanks in advance
Replies
1
Boosts
0
Views
359
Activity
2w
DriverKit entitlement eligibility for independently supporting an EOL third-party USB audio device
I am developing an independent macOS compatibility driver for the Avid/Digidesign Eleven Rack, an EOL USB audio device that does not have an Apple-silicon-compatible OEM driver. The existing hardware identifies as: Vendor ID: 0x0DBA — Digidesign/Avid Product ID: 0xB011 — Eleven Rack Transport: USB 2.0 high-speed isochronous audio The proposed implementation uses AudioDriverKit and USBDriverKit. It consists of a DriverKit system extension packaged inside a macOS control application. The USB entitlement would be restricted to this exact VID/PID. I am an independent developer and do not own the Digidesign/Avid VID. I am not manufacturing hardware or attempting to use that VID for a new USB product. The driver would only match existing Eleven Rack devices. The implementation is independently written for interoperability, and no Avid executable code would be included. I currently have a working direct user-space USB proof of concept, but I cannot properly activate and test the AudioDriverKit extension with SIP enabled without the required entitlements. Before enrolling in the paid Apple Developer Program, I would appreciate clarification on the following: Does Apple consider DriverKit development and distribution entitlement requests from independent developers supporting existing EOL hardware when the developer does not own the device’s VID? Is written authorization from the VID owner always required, or are these requests evaluated individually? Would restricting the USB transport entitlement to the exact 0x0DBA:0xB011 device affect eligibility? Is there a way to obtain an initial eligibility determination before purchasing Apple Developer Program membership? The anticipated entitlements are: com.apple.developer.driverkit com.apple.developer.driverkit.family.audio com.apple.developer.driverkit.transport.usb com.apple.developer.system-extension.install for the host application Restricted user-client access between the host application and driver I understand that the forum cannot grant an entitlement. I am trying to determine the appropriate process and whether manufacturer authorization is a prerequisite before submitting a formal request.
Replies
5
Boosts
0
Views
725
Activity
2w
IOPCIFamily matching precedence and runtime behavior for unmatched PCIe functions
I'm working on diagnostic tooling for PCIe storage devices and I've run into a gap in my understanding of how IOKit resolves matching against a single PCIe function, and what the kernel continues to do with a function that nothing claims. The scenario I'm designing around: an NVMe controller that is degraded but still enumerable. It responds to config space reads and completes some admin commands, but intermittently times out — in the worst case on Identify — which surfaces as a kernel panic rather than a recoverable error. For test and triage purposes I want the ability to leave such a device physically installed while preventing the storage stack from binding to it, scoped to that one function rather than to NVMe generally. Questions on the matching side: When two personalities match on IOPCIPrimaryMatch for the same vendor/device ID, is IOProbeScore the only tiebreaker? I've seen suggestions that which kext collection a personality lives in (boot vs. auxiliary) also influences the outcome, and I'd like to know whether that's genuinely part of the matching algorithm or an artifact of load ordering. If a higher-scored driver's probe() returns NULL, does the nub reliably fall through to the next candidate, including a family driver? Is there a case where a failed probe leaves the nub unmatched rather than retrying lower-scored candidates? Are there properties on an IOPCIDevice nub that gate matching independently of score? IOPCITunnelCompatible clearly does something like this for tunneled devices, which suggests the general mechanism exists — is there a documented, per-function form of it? Questions on runtime behavior: If a PCIe function ends up with no driver attached, what does IOPCIFamily continue to do with it? Specifically, does it may issue config space accesses, participate in the IOKit power management tree, transition the function to D3 on system sleep or on idle, and save/restore config space across wake? Related: does an unmatched function may get a DART/VT-d mapping established, and does IOPCIFamily poll or act on link status or AER state for it? The distinction in 4 and 5 matters a lot for my case. If an unmatched nub is genuinely inert from the device's point of view, blocking driver attachment is a complete solution. If IOPCIFamily is may driving power state transitions on it, then a device that fails during D3 entry or exit will still take the system down, and I need a different approach. Finally — is any of this reachable from DriverKit, or does a per-device matching override necessarily mean a kext? I'd rather build on something supported if a supported path exists. Happy to be pointed at headers or open-source IOPCIFamily if the answers are best read from source; I'm mainly trying to confirm the intended behavior rather than infer it from observation.
Replies
1
Boosts
0
Views
329
Activity
2w
After upgrading to iOS 18 and iOS 26, the project encounters an error retrieving BOOL values in the simulator. It works fine on a physical device.
I have updated to the latest official release: Xcode 26.5 with iOS 26 Simulator runtime, unfortunately the exact same problem still 100% reproduces only on the iOS Simulator. Important background: The production app uploaded to App Store runs perfectly on all physical iOS devices and Mac Catalyst, no logic error at all. The defect is isolated exclusively to simulator Debug environment. Two concrete problematic code snippets: Case 1: BOOL property overflow from system API @property (nonatomic, assign) BOOL isRunningOnMacOSX; // Assign value from NSProcessInfo self.isRunningOnMacOSX = [NSProcessInfo processInfo].isMacCatalystApp; On simulator, BOOL is signed char, the return value is truncated to a negative number. Since any non-zero value evaluates to true in C if() check, the branch is always incorrectly triggered. Case 2: __block BOOL returns garbage value after dispatch_sync GCD call (BOOL)isConnected { __block BOOL result = NO; dispatch_block_t block = ^{ result = (self->flags & kConnected) ? YES : NO; }; if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) { block(); } else { dispatch_sync(socketQueue, block); } NSLog(@"Logged result = %d", result); // Prints clean 0 in log return result; // Returns huge negative garbage integer only on simulator } When calling if ([aSocket isConnected]), it incorrectly enters the true branch. My analysis: This stems from inconsistent ABI handling of signed char return value zero-extension between simulator runtime, real ARM device and Mac Catalyst. Even in Xcode 26.5 stable release, the simulator still does not zero out high bits when extending 1-byte signed char to full register in Debug -O0 mode, leading to heap garbage value after cross-thread dispatch_sync. Current temporary workaround: Replace BOOL type with int internally and strictly store only 0 or 1 to bypass all signed char overflow and register extension issues. Could you help confirm whether this simulator ABI discrepancy is a known runtime limitation, or if there is any compiler/build setting to unify the BOOL behavior across simulator and physical devices? Thanks a lot.
Replies
0
Boosts
0
Views
327
Activity
3w
Toggle to enable Driverkit Driver not appearing in App Settings in iPadOS
We have an app which uses a DriverKit-based driver to communicate with an external device. In multiple iPadOS versions, users have been facing this issue where the option/toggle to enable/disable the Driver is not appearing in the App Settings. As a result, users have to uninstall/install the app to get the option again. Ideally, the option should always appear in the App Settings so that users can freely toggle it according to their needs. Due to this, the external devices connected to the iPad will not be detected. I have not seen this happen during development or in any of the iPad(s) that I have tested the app on. Has anyone seen this happen with their apps and if so, what is the issue/workaround? Is this a known bug only in some specific versions of iPadOS? Also, I have raised a feedback for the same here but there has been no reply. Thanks, Abishek.
Replies
5
Boosts
0
Views
715
Activity
3w
Correcting a line item on an already-submitted DriverKit USB Transport request
We ship an iPadOS app with an embedded USBDriverKit extension that drives Citizen/DNP dye-sub photo printers. It works: on a development-provisioned iPad the dext registers, matches, opens its user client and prints, verified on two units in hand (DNP DS-RX1 0x1343:0x0005, DNP QW410 0x1452:0x9201). The extension declares twelve IOKitPersonalities, each pinned to one exact idVendor/idProduct pair plus bConfigurationValue and bInterfaceNumber. Those twelve span two vendor IDs — 4931 (0x1343, Citizen Systems) and 5202 (0x1452, Dai Nippon Printing) — because the same printer families ship Citizen-badged on one and DNP-badged on the other. We have one USB Transport – VendorID request per vendor ID, both currently Submitted. Thread 842748 already answered the scope question for us, so I'm not asking that one: at twelve devices we read vendor-level as the right ask rather than twelve VendorID+ProductID requests, and we've kept the personalities narrow so the entitlement is a ceiling rather than what actually matches. Please correct me if that's the wrong reading for two vendor IDs rather than one. My actual question is about a mistake in one of the submissions. The older request also asked for UserClient Access, which we now understand is macOS-only (com.apple.developer.driverkit.userclient-access lists DRIVER_KIT and MAC_OS, not IOS). We don't need it — on iPadOS the app opens the dext's user client with com.apple.developer.driverkit.communicates-with-drivers, which needs no approval. Does an inapplicable entitlement on a submitted request need to be formally withdrawn, or is it simply ignored during review? I'd rather not leave a macOS-only entitlement sitting on an iPadOS request if that's something a reviewer has to resolve. If it does need correcting, what's the mechanism? Re-filing would create a third request, and I'd rather not muddy the queue. (Developer Support told me request handling is outside their scope, which is what brings me here.) Is there any way to indicate that two requests belong to one driver extension and are only useful together? Happy to post the Info.plist personalities or the dext's entitlements if useful. Thank you.
Replies
1
Boosts
0
Views
386
Activity
3w
IOUserSCSIParallelInterfaceController: what triggers UserLogicalUnitResetRequest?
I am working on a DriverKit driver and we are subclassing IOUserSCSIParallelInterfaceController. I have implemented UserLogicalUnitResetRequest end-to-end and it sends a real Task management IU to the controller and returns the correct kSCSIServiceResponse_*. When I call the hook from within the dext manually it works but I am not able to invoke this UserLogicalUnitResetRequest from macOS. My question is, under what conditions does macOS itself invoke this hook (or the other five TMF hooks - abort/set, TargetReset, ClearACA/TaskSet)? I tried to insert a gate at the top of UserProcessParallelTask, which for one chosen target, swallows the incoming task without submitting it to the controller and without completing the OSAction. I then ran normal APFS filesystem IO against the target and observed following: Every stalled command arrives with SCSIUserParallelTask.fTimeoutInMilliSec = 0. The command hang indefinitely. None of the TMF hooks are ever invoked by the framework. I am not sure if I am doing something wrong here. Is fTimeoutInMilliSec = 0 on filesystem IO expected? Is there a way for the dext to surface a shorter deadline that the framework will watchdog? What actually invokes the TMF hooks- filesystem-IO timeout escalation, storage recovery, or is there an expectation that the dext runs its own per-command watchdog and invokes its reset code internally? Any help would be really appreciated! Thank you for your time!
Replies
2
Boosts
0
Views
399
Activity
3w
HID Entitlement Configuration Guide
HID Entitlement Configuration Guide: NOTE:The document assumes you're already familiar with the DEXT loading process, as described here. Here are the three core kernel support drivers and their corresponding HID entitlements: AppleUserHIDDevice-> com.apple.developer.driverkit.family.hid.device AppleUserHIDEventService-> com.apple.developer.driverkit.family.hid.eventservice IOHIDInterface-> com.apple.developer.driverkit.transport.hid When building a HID DEXT, you'll first determine your kernel support (IOClass) driver, then include that entitlement in your DEXT. Including any other HID entitlement is unnecessary. Additional Entitlements There are two other HID-related entitlements worth noting: com.apple.developer.driverkit.family.hid.virtual.device -> This entitlement is a defunct entitlement that has no function on any of our platforms. It should not be included in any product and will be removed from the documentation in the future (r.184046926). com.apple.developer.hid.virtual.device -> This entitlement controls access to the CoreHID virtual device API. This is NOT a DEXT entitlement and should never be included in a DEXT. Note that the concept of "virtual" devices in DriverKit is somewhat misleading. A DEXT can publish a "virtual" device, but that’s because a DEXT is the ultimate arbitrator that controls what's visible to the system AT ALL. Putting that in more concrete terms, the system itself doesn't really differentiate between: A standard USB HID device. A software-only HID device. A Thunderbolt mouse (hypothetical). A Ethernet mouse (hypothetical). Like most other IOKit families, the system makes no strong attempt to identify the transport bus[1], so, as far as the system is concerned, all of those are just "HID devices". Within that architecture, CoreHID virtual device API works by using an existing kernel driver to publish new HID devices to the system, duplicating exactly the same architecture a DEXT-based virtual HID driver would use. There's no reason to prefer a DEXT-based solution over CoreHID, as the DEXT simply requires more work without significant benefit. [1] Many places in the system do include information about "where" a device is located. In most cases, this is nothing more than a string directly published by the corresponding driver as an IORegistry key/value. In other words, a device labeled "USB" could easily have been labeled "FireWire", "PCI", "Nowhere", or anything else the driver chose to label it. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
0
Boosts
0
Views
290
Activity
3w