One Driver talking to another Driver.

One of the possible solutions to a problem that I'm working on is to have two Drivers loading in one DriverKit dext, an IOUserHIDEventService and an IOUserHIDDevice. For this to work, however, I need to have the event service send a message to the Device. IOKit has the service and connection objects that I can use just like an app would (just like the app the driver communication example). But DriverKit complains whenever I try to add the IOKit framework, saying that it is not supported. Is there another way that I can send a message directly from one driver to another?

Answered by DTS Engineer in 889734022

So, let me start with what WON'T work:

IOKit has the service and connection objects that I can use just like an app would (just like the app in the driver communication example).

DriverKit isn't a framework, it's a platform. It's designed this way to enforce a HARD isolation between your DEXT and the rest of the system. For example, a DEXT cannot write to a file— not simply because the system won't "let" it, but because the "open" system call DOESN'T exist within the DriverKit platform. Similarly, the only frameworks available in DriverKit are frameworks specifically included in the DriverKit platform.

IOKit deserves special mention here:

But DriverKit complains whenever I try to add the IOKit framework, saying that it is not supported.

...because "IOKit" actually refers to two different technology stacks:

  1. The collection of C++ classes which are used to implement IOKit drivers within the kernel.

  2. The IOKit framework which applications use to communicate with #1.

This distinction matters because DriverKit's basic architecture largely copies #1, as well as being built on the kernel support IOKit provides. To a large extent, DriverKit is best understood as an extension of #1 into user space, not as a truly "separate" architecture. This is also why DriverKit doesn't have its own user space API— DriverKit and IOKit (#1) are so heavily entangled that the way you communicate with a DEXT is by using IOKit.framework.

That then leads to here:

One of the possible solutions to a problem that I'm working on is to have two Drivers loading in one DriverKit dext, an IOUserHIDEventService and an IOUserHIDDevice.

Sort of but not exactly. As was posted here:

Consider that each driver runs in its own (kernel) process, talking to the app via its own (kernel) UserClient.

...DEXTs (typically) run in their own processes which, in the standard configuration, would mean that the DEXT would need to communicate with each other through separate user clients, as described here:

The only way I found is to do this: Driver1->UserClient1->App->UserClient2->Driver2.

One minor comment here is that this doesn't necessarily mean that all communication is going through all of those layers or that it's necessarily "slow". There are a few high-end audio products that need to consolidate data from multiple source and driver layers in real time through multiple user clients, and the way they do that is by using the user client to share memory, not just messages. Coordination is done by defining how all of the components will interact with that shared memory buffer, which then removes all of the latency that simple message passing would otherwise introduce.

Having said that...

Is there another way that I can send a message directly from one driver to another?

Yes, there is another way assuming they share a common provider. That approach is to use the "IOUserServerOneProcess" to consolidate the two driver instances into the same process. This forum post has a more extended write-up on how this works.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I wanted to do this for my driver, that when multiple devices are plugged, the second USB driver instance changes its behaviour.

Consider, that each driver runs in its own (kernel) process, talking to the app via its own (kernel) UserClient. The answer is right there = its not possible, because the address space is isolated as each driver runs in a sperate process (observe with ps). The only way I found, is to do this Driver1->UserClient1->App->UserClient2->Driver2.

The app watches the plug/unplug in any case, and I created a special call that on the Device#2 plug = calls into driver2 and activates the feature.

my 10 cents... PS: if this is a use-case then the app should handle this case (multiple devices plugged) anyways.

Accepted Answer

So, let me start with what WON'T work:

IOKit has the service and connection objects that I can use just like an app would (just like the app in the driver communication example).

DriverKit isn't a framework, it's a platform. It's designed this way to enforce a HARD isolation between your DEXT and the rest of the system. For example, a DEXT cannot write to a file— not simply because the system won't "let" it, but because the "open" system call DOESN'T exist within the DriverKit platform. Similarly, the only frameworks available in DriverKit are frameworks specifically included in the DriverKit platform.

IOKit deserves special mention here:

But DriverKit complains whenever I try to add the IOKit framework, saying that it is not supported.

...because "IOKit" actually refers to two different technology stacks:

  1. The collection of C++ classes which are used to implement IOKit drivers within the kernel.

  2. The IOKit framework which applications use to communicate with #1.

This distinction matters because DriverKit's basic architecture largely copies #1, as well as being built on the kernel support IOKit provides. To a large extent, DriverKit is best understood as an extension of #1 into user space, not as a truly "separate" architecture. This is also why DriverKit doesn't have its own user space API— DriverKit and IOKit (#1) are so heavily entangled that the way you communicate with a DEXT is by using IOKit.framework.

That then leads to here:

One of the possible solutions to a problem that I'm working on is to have two Drivers loading in one DriverKit dext, an IOUserHIDEventService and an IOUserHIDDevice.

Sort of but not exactly. As was posted here:

Consider that each driver runs in its own (kernel) process, talking to the app via its own (kernel) UserClient.

...DEXTs (typically) run in their own processes which, in the standard configuration, would mean that the DEXT would need to communicate with each other through separate user clients, as described here:

The only way I found is to do this: Driver1->UserClient1->App->UserClient2->Driver2.

One minor comment here is that this doesn't necessarily mean that all communication is going through all of those layers or that it's necessarily "slow". There are a few high-end audio products that need to consolidate data from multiple source and driver layers in real time through multiple user clients, and the way they do that is by using the user client to share memory, not just messages. Coordination is done by defining how all of the components will interact with that shared memory buffer, which then removes all of the latency that simple message passing would otherwise introduce.

Having said that...

Is there another way that I can send a message directly from one driver to another?

Yes, there is another way assuming they share a common provider. That approach is to use the "IOUserServerOneProcess" to consolidate the two driver instances into the same process. This forum post has a more extended write-up on how this works.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

One Driver talking to another Driver.
 
 
Q