Building SimpleAudioDriver example

Hi there,

I am trying to build the Apple SimpleAudioDriver example but fail with codesign and/or provisioning.

I would be ok for now with the local option, but XCode 16.4 doesn't show the option "build to run locally" (SIP is disabled). When using "Automatically manage signing" it ends in a "Please file a bug report".

I found that having two different development teams tripped it up, so I deleted all certificates and keys and made sure to be only signed into one account in Xcode.

Can anyone give advice? Thanks a ton!

Here is the URL to the sample: https://developer.apple.com/documentation/coreaudio/building-an-audio-server-plug-in-and-driver-extension

macOS: 15.6.1 XCode: 16.4 Hardware: MacBook Pro M2 Max SIP: disabled

look in ~/Library/Developer/Xcode/UserData/Provisioning Profiles for the Xcode-generated profile. You can use QuickLook to inspect the profile. If you added the DriverKit USB (development) Capability, your profile should have idVendor='*'. This wildcard value will only work for development builds.

Your entitlements.plist should have an entry called com.apple.developer.driverkit.transport.usb or "DriverKit USB Transport' which is an array, containing one or more items, each of which is a dictionary. Each dictionary should have an item with key idVendor and value a decimal number equal to the vendor ID of the device you're driving.

Can anyone give advice? Thanks a ton!

Unfortunately, this is actually the first time I've looked at "Building an Audio Server Plug-in and Driver Extension" and, to be honest, that is not great sample code. Using darwinup in a shell script is not something any one should actually "do". I've already filed a bug on this (r.163226098), but you're going to need to do a bit of work to end up with something "reasonable".

SO, what I would actually suggest is the following:

  1. Start with the sample "Communicating between a DriverKit extension and a client app" and get it building and running. That's our simplest sample and will let you sort out the basic build and install process.

  2. Once that's working, replace the DEXT inside that sample with the DEXT from "Building an Audio Server Plug-in and Driver Extension".

Once that's done, you'll have an installer app with an embedded DEXT, which is what ALL DEXT need to be shipped as anyway.

Shifting to the codesign front:

I would be ok for now with the local option, but XCode 16.4 doesn't show the option "build to run locally" (SIP is disabled).

The old "disable SIP" process is no longer necessary. The "modern" approach uses the "Development Only" entitlement variants, which allow your DEXT to match against "any" hardware, but can ONLY be used in Development builds. Those use this configuration described above:

If you added the DriverKit USB (development) Capability, your profile should have idVendor='*'. This wildcard value will only work for development builds.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you for the information.

The Communicating example says in the readme to disable SIP, so which one is right?

Building the Communicating example yields the same error, saying "file a bug report" like in the screenshot above.

And the provisioning profile is missing the "driverkit.allow-any-userclient-access" entitlement.

How should I add that? I cannot see that in the checkboxes below the error.

Thanks in advance

The Communicating example says in the readme to disable SIP, so which one is right?

Technically, we're both right as the old "disable SIP" flow does still work (at least theoretically). However, the new flow is so much easier that I wouldn't bother with the SIP flow.

And the provisioning profile is missing the "driverkit.allow-any-userclient-access" entitlement. How should I add that?

Don't bother, just delete it from your Entitlement.plist. This forum thread outlines exactly how the user client entitlements work and, with that context, what you'll actually end up doing is:

  1. In the long run, you'll eventually request the "right" user client entitlements based on your needs, using the forum post above to figure out which one is right for you.

  2. In the short run, you can sidestep the entire problem. Your DEXT will already allow connections from code that's signed by your team and your app can get past its restrictions by either disabling the app sandbox and/or adding the "IOKit User Client Class Temporary Exception". See this forum post for a detailed rundown of that as well as some additional guidance.

Building the Communicating example yields the same error, saying "file a bug report" like in the screenshot above.

Deleting "com.apple.developer.driverkit.userclient-access" should clear this issue. Quoting myself on this particular Xcode error (r.163506095):

"One thing to be aware of here is that Xcode has a "bias" in the way it presents codesign errors where it assumes the Entitlement.plist is "correct" and the profile is "wrong". However, in practice that's basically "never" the case with DriverKit entitlements and tends to lead to a lot of "flailing" trying to somehow "fix" the provisioning profile. This error ALWAYS means that "the entitlement.plist doesn't match the profile". You fix that by:..."

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Empty post

Hi Kevin,

Deleting "com.apple.developer.driverkit.userclient-access" should clear this issue.

Thank you, that helped indeed the compilation to succeed. The connection fails though:

The log shows:

sysex didFailWithError: extension category returned error

I was wondering now, if I should try to fix the Driver Communication example or straight move on to adapt the SimpleAudioDriver example.

Unfortunately I don't know where to start. I am a C++ developer by trade and the os specific toolchains are hard to grasp for me.

Thank you for all the help so far!

Daniel

Thank you, that helped indeed in the compilation to succeed. The connection fails though: The log shows: sysex didFailWithError: extension category returned error

OK, so that's an install error, not an IOKit issue. Have you configured everything to be signed by the same team? What, if anything, is being printed in the system log?

Also, keep in mind that you DO need to add the “com.apple.security.temporary-exception.iokit-user-client-class” entitlement to your app (NOT the DEXT), as described in this forum post.

I was wondering now, if I should try to fix the Driver Communication example or straight move on to adapt the SimpleAudioDriver example.

That's ultimately up to you, but I would stick with the Driver Communication example and get it working first. One of the lessons I've learned over and over again is that it's MUCH easier to "expand" on something that works vs. making something work from "scratch". This is basically our simplest sample, so I think your best bet is to get it working first.

Unfortunately I don't know where to start. I am a C++ developer by trade and the os specific toolchains are hard to grasp for me.

Welcome to the party... So, a few general pointers and warnings here:

(1)
DriverKit is not well documented and, to be blunt, fairly "weird". It's basically written using the C++ variant IOKit uses (which is straightforward), with a number of complex macros layered on top of it. The result of all that is not always as readable as it could be.

(2).
Using and understanding DriverKit basically requires understanding IOKit, something our documentation never actually says. 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:

__
Kevin Elliott
DTS Engineering, CoreOS/Hardware

Hi Kevin,

Thanks for all the pointers. Trying to debug into the Dext example:

DriverLoadingViewModel+macOS request yields error 9: "extension category returned error". Where do I find more information and how do I fix that?

Thanks!

DriverLoadingViewModel+macOS request yields error 9: "extension category returned error".

That would be "OSSystemExtensionError.Code.validationFailed", which basically means the system didn't like "something" about the construction of your DEXT bundle. That's means it's either how your app is signed or what's in your Info.plist.

Where do I find more information and how do I fix that?

The system would have logged additional data to the system log before it returned an error to your app.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Ok, I found this in dmesg/syslog:

[46147.634755]: DriverKitSampleA[6170] triggered unnest of range 0x1fc000000->0x1fe000000 of DYLD shared region in VM map 0x853f7106fc70fc7d. While not abnormal for debuggers, this increases system memory footprint until the target exits.
[46147.634762]: DriverKitSampleA[6170] triggered unnest of range 0x1fe000000->0x200000000 of DYLD shared region in VM map 0x853f7106fc70fc7d. While not abnormal for debuggers, this increases system memory footprint until the target exits.
[46148.219526]: Sandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.appSandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/ContentsSandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/Contents/Info.plistSandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.appSandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/Contents/MacOS/DriverKitSampleApp1 duplicate report for Sandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/Contents/MacOS/DriverKitSampleAppSandbox: ContextStoreAgent(448) allow file-read-xattr /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/Contents/MacOS/DriverKitSampleAppSandbox: ContextStoreAgent(448) allow file-read-data /Users/daniel/Library/Developer/Xcode/DerivedData/DriverKitUserClientSample-haxyygamobxzqybcidlsjqhbccev/Build/Products/Debug/DriverKitSampleApp.app/Contents/Info.plistSandbox: nsattributedstringagent(5875) deny(1) mach-lookup com.apple.CARenderServerSandbox: nsattributedstringagent(878) deny(1) mach-lookup com.apple.CARenderServerwlan0:com.apple.p2p: isInfraRealtimePacketThresholdAllowed allowed:1 option:32 threshold:50 noRegistrations:1 cachedPeerCount:0 fastDiscoveryInactive:1 fastDiscoveryOnSince:46148792

The app is automatically signed with a valid dev team and uses Managed provisioning.

Ok, I found this in dmesg/syslog:

You're not looking at the right data yet. The actual loading/validation of your DEXT happens outside your process, so any error logging will come from relevant daemon not "your" code. The best way to track this down is to:

  1. Add logging immediately before OSSystemExtensionManager.submitRequest(_:)

  2. Add logging at the beginning of request(_:didFinishWithResult:) and request(_:didFailWithError:).

  3. Make sure all of that logging is written all the way out to the system console by checking Console.app.

Those to log point create "bookends" where any logging the system did must be between those two logs messages. That makes investigating the issue a relatively simple matter of finding message #1 and then skimming through the log until you find any activity relevant to your app.

A few other points/suggestions that might be helpful:

  • I avoid working out of the "live" system log. That means either triggering a sysdiagnose or using "sudo log collect" to generate a log archive. The log archive is generally faster and, more importantly, if something goes wrong you don't have redo your test.

  • "Your Friend the System Log" and "Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem" are both good resources for tips/tricks/suggestions on this process.

  • In Console.app, you can right click on entry to hide/show specific entries or values, which can make it easy to quickly filter out "noise". Also, not the "showing" button in the lower left of the Window, which controls the time range your viewing.

  • Particularly when you're new to this kind of investigation, I would strongly recommend skim reading through the log list instead of trying to aggressively search or "filter". There are daemons and processes you can immediately dismiss/hide (for example, mDNSResponder and Finder are unlikely to be relevant), but also easy to accidentally hide exactly the data you needed to see.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Building SimpleAudioDriver example
 
 
Q