How to deliver a USBDriverKit driver in an SDK or Framework for sale to third parties?

I have a product that currently communicates to a piece of proprietary Medical hardware via USB. We have a driver created with USBDriverKit that is a hard requirement for this product to function.

Currently, we are delivering an iPadOS application that utilizes the driver. Our next step is to create an SDK that includes all of the Frameworks and the driver utilized by the application.

Since the driver is a system extension that lives in the application, how do we bundle it with our SDK and make it available for use by third-parties?

Answered by DTS Engineer in 893113022

Currently, we are delivering an iPadOS application that utilizes the driver.

Note that my answer here is specifically about only iPadOS, NOT macOS. My answer on macOS would be very different and more complicated.

Since the driver is a system extension that lives in the application, how do we bundle it with our SDK and make it available for use by third parties?

So, my first question here is what the software usage patterns around this hardware are going to look like. Is it:

  1. A single device will be "owned" by a single app install (or set of apps from the same team), with that app handling everything related to that device.

  2. Multiple apps, particularly from different vendors, may be interacting with the device.

The problem here is primarily about driver versioning and how those apps interact with each other and different driver versions. If multiple apps from different vendors are all embedding the same driver, then exactly which DEXT will ultimately control the device isn't well defined (I suspect it will "newest version" but it might be last installed), making the entire situation quite chaotic.

The simplest way to sidestep that issue is exactly what was suggested here:

Can you make installation of your iPadOS application a requirement for use of the driver?

...since now there is only one app that's actually managing the DEXT installation.

Unfortunately, if you want to ship the app embedded in individual apps then I'm afraid that's going to be somewhat complicated. The team that is shipping the app will need to sign the DEXT "themselves", which means:

  • They'll need all of the same DriverKit entitlements as your team.

  • They'll also need to at least partially build your DEXT "from scratch", since they'll need to be able to configure and sign it with their own bundle ID (not "yours").

Finally, this may significantly complicate #2, as the different bundle IDs mean the system considers each of those DEXTs to be independent of each other (not different versions of the same thing). I think they could all still use the same driver, but only if you were careful to change just the bundle ID without making any other changes.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Can you make installation of your iPadOS application a requirement for use of the driver?

The delivery system for your dext would be your own app (which I think the user has to run once to install your driver). Once installed, any app can communicate with your driver if the driver has the com.apple.developer.driverkit.allow-third-party-userclients entitlement.

Your app (or your customer's app) needs the com.apple.developer.driverkit.communicates-with-drivers entitlement.

Currently, we are delivering an iPadOS application that utilizes the driver.

Note that my answer here is specifically about only iPadOS, NOT macOS. My answer on macOS would be very different and more complicated.

Since the driver is a system extension that lives in the application, how do we bundle it with our SDK and make it available for use by third parties?

So, my first question here is what the software usage patterns around this hardware are going to look like. Is it:

  1. A single device will be "owned" by a single app install (or set of apps from the same team), with that app handling everything related to that device.

  2. Multiple apps, particularly from different vendors, may be interacting with the device.

The problem here is primarily about driver versioning and how those apps interact with each other and different driver versions. If multiple apps from different vendors are all embedding the same driver, then exactly which DEXT will ultimately control the device isn't well defined (I suspect it will "newest version" but it might be last installed), making the entire situation quite chaotic.

The simplest way to sidestep that issue is exactly what was suggested here:

Can you make installation of your iPadOS application a requirement for use of the driver?

...since now there is only one app that's actually managing the DEXT installation.

Unfortunately, if you want to ship the app embedded in individual apps then I'm afraid that's going to be somewhat complicated. The team that is shipping the app will need to sign the DEXT "themselves", which means:

  • They'll need all of the same DriverKit entitlements as your team.

  • They'll also need to at least partially build your DEXT "from scratch", since they'll need to be able to configure and sign it with their own bundle ID (not "yours").

Finally, this may significantly complicate #2, as the different bundle IDs mean the system considers each of those DEXTs to be independent of each other (not different versions of the same thing). I think they could all still use the same driver, but only if you were careful to change just the bundle ID without making any other changes.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you Kevin and ssmith_c. It seems like there is a lot to unpack here. Let me see if I can short-circuit this discussion. Here is what I think is being suggested; Kevin, please correct me if I'm wrong or this will not work.

  1. Create an app owned by our organization that contains the shared DEXT. Publish this app in the AppStore.
  2. Sell the SDK with our XCFrameworks that talk to the DEXT.
  3. The customer needs to have the proper entitlements to talk to the DEXT and must also link in our SDK frameworks, which handle our IP and protocols for talking to the device.

This means our SDK App is a simple DEXT delivery vehicle, which must be installed in order for any third-party application built with our SDK to have access to the DEXT. With this arrangement, the customer can build as many applications using our SDK as they like as long as only one of them is installed and operating at a time.

Handling multiple apps installed and trying to communicate with our DEXT is out of scope for the time being.

I think your summary is correct, aside from this part: "as long as only one of them is installed and operating at a time".

That's up to you. You've written a driver, and the driver can elect to support only one client, or multiple clients.

You can even get the com.apple.application-identifier from the client's entitlements dictionary, using CopyClientEntitlements in your user client's Start_Impl. The application-identifier is of the form <teamID>.<bundle ID>, so if you're called by a regular app, you can figure out which app it is and what team signed it.

I've never tried more than one client. I assume that each user-space client's Open() causes a new call to your NewUserClient_Impl in your driver, and you can decide there whether to reject the call if you already have a client, replace the client, or make a new client.

That's up to you. You've written a driver, and the driver can elect to support only one client, or multiple clients.

Yes. More specifically, your driver can basically be "arbitrarily capricious", accepting or rejecting connections whenever it wants for any reason (only want to work on Mondays? Not a problem...). The most basic "support" for multiple apps is trivial— if a client is already connected, reject any new connection attempts. That's the basic level EVERY driver should implement as part of basic “self-protection". However, you can "build up" from there anything you want. For example, you can accept any and all connections but only allow one connection to "own" the device (meaning, use the part of your user client that actually “does stuff") at any given time. This is basically how the "seize" semantics work in the IOUSBHost framework.

You can even get the com.apple.application-identifier from the client's entitlements dictionary, using CopyClientEntitlements in your user client's Start_Impl. The application-identifier is of the form <teamID>.<bundle ID>, so if you're called by a regular app, you can figure out which app it is and what team signed it.

Yes, and this is also useful since it allows you to provide different behavior to different connecting clients. For example, device firmware updates are another role your "main" app can serve and this allows you to ensure that only your apps can install new firmware.

I assume that each user-space client's Open() causes a new call to your NewUserClient_Impl in your driver, and you can decide there whether to reject the call if you already have a client, replace the client, or make a new client.

Yes, that's what happens.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

How to deliver a USBDriverKit driver in an SDK or Framework for sale to third parties?
 
 
Q