Re: The future of /dev?

22 views
Skip to first unread message

Seth Ladd

unread,
Feb 17, 2021, 11:35:32 AM2/17/21
to Suraj Malhotra, Hunter Freyer, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
- tq-driver-framework-team


On Wed, Feb 17, 2021 at 8:23 AM 'Suraj Malhotra' via component-framework-dev <component-f...@fuchsia.dev> wrote:

On Wed, Feb 17, 2021 at 8:22 AM Hunter Freyer <hjfr...@google.com> wrote:
Hey Suraj and Abdulla,

Adam and I have been talking recently about Unified Services (and Adam's suggested tweak in the form of Capability Sets), and I'm wondering whether y'all think there are improvements to be made with respect to how higher-level components connect to driver components. 

If I understand correctly, the current model is that the device topology is reflected in /dev/. Opening a path under /dev/ opens a connection into that device's driver, specific to that device. Applications that want to use drivers generally watch the path for the driver they want, and open the connection as soon as it pops up. Many/most drivers only support a single client for each device, so they need to implement a "one-at-a-time" policy, and as a result, if there are multiple clients, there's a race to see who opens it up first. Since connections go directly to the drivers, any policy for selecting the "best" client has to be implemented by the driver, which practically speaking means there isn't really any policy.

Furthermore (if I understand correctly), the plan of record isn't to change this all that much. Instead of using devfs, clients will use service capabilities, but the watch-a-path, race-for-a-connection, talk-directly-to-the-driver method is still the plan, yeah?

I wasn't here for a lot of the history, so, honest question: do we feel good about this model? Have we considered/should we consider a model wherein there is some "device access layer" to handle listing devices, maybe pre-queueing for access, establishing client priority, etc? Is there enough interesting policy that could go on there? Or does the current model work pretty much well enough?

Hunter


--
All posts must follow the Fuchsia Code of Conduct https://fuchsia.dev/fuchsia-src/CODE_OF_CONDUCT or may be removed.
---
You received this message because you are subscribed to the Google Groups "component-framework-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to component-framewo...@fuchsia.dev.
To view this discussion on the web visit https://groups.google.com/a/fuchsia.dev/d/msgid/component-framework-dev/CAFFy6-DAvgfQivub9JJje_rC3awJsOzVF1z9n1afee1aNv-kYg%40mail.gmail.com.

Alice Neels

unread,
Feb 17, 2021, 1:06:15 PM2/17/21
to Seth Ladd, David Gilhooley, Suraj Malhotra, Hunter Freyer, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
+David Gilhooley thought about this a bit in the context of user input devices and our test strategy. We wound up concluding that we needed dedicated APIs to inject fake "driver events" rather than having some kind of test driver due to the timing issues. 

Suraj Malhotra

unread,
Feb 17, 2021, 1:19:35 PM2/17/21
to Hunter Freyer, Ruchira Ravoori, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
I've had a lot of ideas here and written about them before, but I'll try to summarize them here:
  • Policy for who should have access to a driver should not live in the driver.
  • The agent which is usually best suited for making informed policy decisions is something with access to information about all related devices.
  • There are typically aggregation components that already exist for many stacks which nicely serve as a point of mediation. It would be nice if we can ensure only they have access to the device.
    • Examples include:
      • fshost for block devices
      • netstack / network-manager for network devices
      • bt-host / bt-gap for bluetooth devices (a bit complicated because bt-host is a driver currently)
      • modem-manager? for telephony devices (the documentation doesn't match existing implementation, but I believe the design 
  • One way to achieve this is to have non-driver components "bind" to devices by supplying bind programs to the driver runtime.
    • Bind programs themselves will have some notion of priority, but typically are sufficient by themselves to implement policy (but maybe are for simpler device stacks?)
    • The problem is that if we subvert filesystem based discovery in favor of bind programs, how does that map to capabilities? The ability to specify your bind program is overly permissive.
+Ruchira Ravoori has taken up the duty of understanding this problem and driving a solution from the DF side.

Hunter Freyer

unread,
Feb 17, 2021, 1:43:41 PM2/17/21
to Suraj Malhotra, Ruchira Ravoori, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Wed, Feb 17, 2021 at 1:19 PM Suraj Malhotra <surajm...@google.com> wrote:
I've had a lot of ideas here and written about them before, but I'll try to summarize them here:
  • Policy for who should have access to a driver should not live in the driver.
  • The agent which is usually best suited for making informed policy decisions is something with access to information about all related devices.
  • There are typically aggregation components that already exist for many stacks which nicely serve as a point of mediation. It would be nice if we can ensure only they have access to the device.
    • Examples include:
      • fshost for block devices
      • netstack / network-manager for network devices
      • bt-host / bt-gap for bluetooth devices (a bit complicated because bt-host is a driver currently)
      • modem-manager? for telephony devices (the documentation doesn't match existing implementation, but I believe the design 
  • One way to achieve this is to have non-driver components "bind" to devices by supplying bind programs to the driver runtime.
    • Bind programs themselves will have some notion of priority, but typically are sufficient by themselves to implement policy (but maybe are for simpler device stacks?)
    • The problem is that if we subvert filesystem based discovery in favor of bind programs, how does that map to capabilities? The ability to specify your bind program is overly permissive.
+Ruchira Ravoori has taken up the duty of understanding this problem and driving a solution from the DF side.

Hey Ruchira! I saw your comment on my quick Drivers vs Elements doc and I meant to respond after I felt like I understood composite devices and... well I'm still not sure I understand composite devices :P.

Who is your point of contact in CF? Is there a Drivers/Components Boundary Working Group? If not, should there be? :D

Ruchira Ravoori

unread,
Feb 17, 2021, 2:05:47 PM2/17/21
to Hunter Freyer, Suraj Malhotra, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
Hey Hunter,

No worries! I was reading about the session framework migration plan to get parallels between elements and drivers too. A boundary working group sounds great. It will be helpful to bump ideas across each other. I can brief you about composite devices.

I am still investigating exclusivity/concurrency, there are 2 issues, as I see here.
1. When drivers bind to services(banjo protocol today) that another driver exposes (this is how the driver stack gets built). When there is a driver sitting on top of the driver, any services that the driver exposes, should not affect the drivers on top.
2. Multiple clients trying to access the same device at the same time. Today, we solve this by creating different device instances each time a client opens the device and the driver manages the instances.

Once we move away from devfs and use services for discovery of devices, I am wondering/exploring if #2 is/will be a unique problem for devices and if it's always the service's servers' duty to deal with multiple clients.

Aaron Wood

unread,
Feb 17, 2021, 2:39:58 PM2/17/21
to Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Hunter Freyer, Suraj Malhotra, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
I was thinking about this today (from another context:  system assembly).

And how some systems ('nix flavors) use the ambient authority and global file system namespace route to find/open devices, and the ways that we've decided to go in a different direction, has led us without a couple features:
 - device enumeration
 - device driver "registration"

I think the abstraction that best fits our platform may be a provider / registrar.  Which I think is the abstraction type that Suraj was suggesting with fshost, netstack, etc.

From a system- and product-assembly point of view, at one level, I can brute-force through the issue by just producing a product-specific topology and using that in bootfs/blobfs instead of the current `core.cml` and `boot.cml`.  But I don't think that really scales past a static, single-purpose product.  For more dynamic products, where the devices and topology are less known in advance, I've been thinking we need some composable registrar / provider interface.  Models like dependency injection and class-path searches come to mind.  But we have a framework gap where we don't want the platform to be scanning through pkgfs to see if any matching packages are on the local system, but not framework or way to ask pkgfs a question like "tell me all the block device drivers" that would take the place of a platform component talking directly to pkgfs.

+Dan Johnson+Erick Tryzelaar - Maybe we should think about this aspect of packages and package metadata, and a framework for exposing enumerable results?

Hunter Freyer

unread,
Feb 17, 2021, 3:17:05 PM2/17/21
to Aaron Wood, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Suraj Malhotra, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Wed, Feb 17, 2021 at 2:38 PM Aaron Wood <aaro...@google.com> wrote:
I was thinking about this today (from another context:  system assembly).

And how some systems ('nix flavors) use the ambient authority and global file system namespace route to find/open devices, and the ways that we've decided to go in a different direction, has led us without a couple features:
 - device enumeration
 - device driver "registration"

I think the abstraction that best fits our platform may be a provider / registrar.  Which I think is the abstraction type that Suraj was suggesting with fshost, netstack, etc.

The pattern that's been in my head is: the driver component is offered a protocol like "fuchsia.drivers.BlockRegistrar". The driver calls "BlockRegistrar/RegisterBlockDevice(...)" and passes a channel that the BlockRegistrar uses to control the Driver. Since the Driver is the one calling "Register", it can know that it only has one client per device, by construction. (Whether the BlockRegistrar would pass this channel onto another component, or actually proxy requests, I dunno.)

Not sure if that's a good model or not, but as a consequence of CF's design decision that parents can't use capabilities their children expose, capabilities tend to get routed "down" the tree, and calls tend to go "up", so it kinda aligns with that.
 
From a system- and product-assembly point of view, at one level, I can brute-force through the issue by just producing a product-specific topology and using that in bootfs/blobfs instead of the current `core.cml` and `boot.cml`.  But I don't think that really scales past a static, single-purpose product.  For more dynamic products, where the devices and topology are less known in advance, I've been thinking we need some composable registrar / provider interface.  Models like dependency injection and class-path searches come to mind.  But we have a framework gap where we don't want the platform to be scanning through pkgfs to see if any matching packages are on the local system, but not framework or way to ask pkgfs a question like "tell me all the block device drivers" that would take the place of a platform component talking directly to pkgfs.

Can you elaborate on what you mean by "tell me all the block device drivers"? Do you mean, like, all the components that contain driver SOs that expose block interfaces? Or like, all the block devices on the system? There's a connection here I'm not seeing.
 
+Dan Johnson+Erick Tryzelaar - Maybe we should think about this aspect of packages and package metadata, and a framework for exposing enumerable results?

I'm sure I don't understand the full implications of what you're suggesting, and maybe this is a naive question, but: does there really need to be framework support for enumerating devices? Couldn't every type of Registrar (Block, Network, etc) have its own protocol for its particular use case?

Hunter
 

On Wed, Feb 17, 2021 at 11:05 AM 'Ruchira Ravoori' via component-framework-dev <component-f...@fuchsia.dev> wrote:
Hey Hunter,

No worries! I was reading about the session framework migration plan to get parallels between elements and drivers too. A boundary working group sounds great. It will be helpful to bump ideas across each other. I can brief you about composite devices.

I am still investigating exclusivity/concurrency, there are 2 issues, as I see here.
1. When drivers bind to services(banjo protocol today) that another driver exposes (this is how the driver stack gets built). When there is a driver sitting on top of the driver, any services that the driver exposes, should not affect the drivers on top.

Hehe too many "the driver"s, I can't keep track :). Can you reiterate?

Ruchira Ravoori

unread,
Feb 17, 2021, 4:11:54 PM2/17/21
to Hunter Freyer, Aaron Wood, Dan Johnson, Erick Tryzelaar, Suraj Malhotra, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
Sure, let me reiterate.

Let's say we have a driver_A. driver_A  adds a device_A that offers 2 services. service_A, service_B. While there are other drivers looking for devices that offer service_A, there are no clients outside the driver world, looking for service_A.
Let's say we have driver_B looking for devices that offer service_A. driver_B is bound to device_A, and in the driver stack we have driver_B on top of driver_A. driver_B talks to device_A using the service_A. 

On the other hand, there are no drivers looking for service_B, but there are multiple clients outside the driver world looking for service_B.
The driver needs to take care of 2 things.
1. service_A not interfering with service_B, because both are operations on device_A.
2. Multiple clients trying to access service_B. 

While I think #1 is somewhat specific to the driver world, #2 is a generic problem that should arise elsewhere? Multiple components trying to access single service. Is the onus of dealing with this always upon the server? or is there something in the component framework that would aid in handling this? (Like creating multiple instances of service each time the service is open)

Aaron Wood

unread,
Feb 17, 2021, 4:54:01 PM2/17/21
to Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Suraj Malhotra, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Wed, Feb 17, 2021 at 12:14 PM Hunter Freyer <hjfr...@google.com> wrote:
On Wed, Feb 17, 2021 at 2:38 PM Aaron Wood <aaro...@google.com> wrote:
I was thinking about this today (from another context:  system assembly).

And how some systems ('nix flavors) use the ambient authority and global file system namespace route to find/open devices, and the ways that we've decided to go in a different direction, has led us without a couple features:
 - device enumeration
 - device driver "registration"

I think the abstraction that best fits our platform may be a provider / registrar.  Which I think is the abstraction type that Suraj was suggesting with fshost, netstack, etc.

The pattern that's been in my head is: the driver component is offered a protocol like "fuchsia.drivers.BlockRegistrar". The driver calls "BlockRegistrar/RegisterBlockDevice(...)" and passes a channel that the BlockRegistrar uses to control the Driver. Since the Driver is the one calling "Register", it can know that it only has one client per device, by construction. (Whether the BlockRegistrar would pass this channel onto another component, or actually proxy requests, I dunno.)

That's similar to what I've been thinking about as a registrar or provider.
 
Not sure if that's a good model or not, but as a consequence of CF's design decision that parents can't use capabilities their children expose, capabilities tend to get routed "down" the tree, and calls tend to go "up", so it kinda aligns with that.

I actually like that parents can't use childrens' capabilities, because it allows us to have more-narrowly focused CMs for each component (maybe just use/expose), and then "glue" components which wire children together.  Those glue, or topology-only components are nice degrees of freedom within the system, in that they let us get better composability at product assembly time.
 

From a system- and product-assembly point of view, at one level, I can brute-force through the issue by just producing a product-specific topology and using that in bootfs/blobfs instead of the current `core.cml` and `boot.cml`.  But I don't think that really scales past a static, single-purpose product.  For more dynamic products, where the devices and topology are less known in advance, I've been thinking we need some composable registrar / provider interface.  Models like dependency injection and class-path searches come to mind.  But we have a framework gap where we don't want the platform to be scanning through pkgfs to see if any matching packages are on the local system, but not framework or way to ask pkgfs a question like "tell me all the block device drivers" that would take the place of a platform component talking directly to pkgfs.

Can you elaborate on what you mean by "tell me all the block device drivers"? Do you mean, like, all the components that contain driver SOs that expose block interfaces? Or like, all the block devices on the system? There's a connection here I'm not seeing.

So, in the case above, how does the driver component get started, such that it can be offered the `fuchsia.drivers.BlockRegistrar` protocol?  Is it referenced in the topology of the platform as a child?  (that's the easy case)  Or is it composed into the system later, or ephemerally?

I think the parallel operations, from linux, are:
- A driver component that's directly referenced in the topology is similar at startup to a compiled-in kernel driver on Linux.  It's always available, and is started at boot by dint of existing in the kernel
- A driver component that's added later needs to have an equivalent for `insmod`, or `modprobe`, and that's what I think people are looking for a way to solve.

I think there are easy cases where an application component knows that it needs driver A, and can just start that driver (or have it started as part of the session).  But then there are situations like Ruchira is describing, where the application components want some service (B), and they don't really care which driver is used to provide that, but the driver isn't known a-priori at system assembly time.  How do we bridge that gap?  How do we get driver A started, if it's not started at boot, and isn't part of the product's topology as a known-in-advance item?
 
+Dan Johnson+Erick Tryzelaar - Maybe we should think about this aspect of packages and package metadata, and a framework for exposing enumerable results?

I'm sure I don't understand the full implications of what you're suggesting, and maybe this is a naive question, but: does there really need to be framework support for enumerating devices? Couldn't every type of Registrar (Block, Network, etc) have its own protocol for its particular use case?

I think my question is:  How are the drivers found for offering the Registrar protocol to them?

Suraj Malhotra

unread,
Feb 17, 2021, 10:06:59 PM2/17/21
to Aaron Wood, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
Drivers registering themselves with some entity implementing a particular protocol seems backwards to me. Drivers already have a way to describe what they have enumerated and what services they offer, via device properties. Needing to duplicate that information depending on whether the service it offers needs to get routed to something other than a driver seems not optimal.

Also, fwiw, rather than come up with hypothetical situations, I think it may be more useful to work through specific use cases we plan to support one day. A few examples (these may not be good group showing all edges worth considering):
  • How the FVM gets mounted
  • How a webUSB use case may work when there is a driver already bound to the device (it's identified as a HID device which has a generic driver, but there are capabilities not exposed by the driver which the website wants to make use of).
  • How wlan devices are enumerated
  • How a vendor proprietary technology might get exposed to the rest of the system without the OS standing in the way
    • The ability to program a keyboard to emit specific RGB lights based application loaded
    • A special camera ability some camera app might be able to make use of
  • How a manufacturing tool may calibrate hw while the rest of the system is using it
We don't currently just start drivers just because drivers exist on the system. We enumerate all drivers known at system assembly time, query them to find out under what conditions they should be loaded, and then only load them under those conditions. This system is known as driver binding. Although we've not really tried to tackle the problem of drivers known at system assembly time in earnest (ephemeral/universe drivers), I strongly suspect our binding system will hold up quite well for them.

insmod and modprobe equivalents are really necessary given our architecture. Rather we only need a way to announce the existence of a driver to the driver framework at runtime, and that's a fairly tractable problem. Reloading a driver is something we've recently added support for, and while we don't have support for disabling/enabling drivers dynamically (thereby triggering unloading/loading), just yet, when we have a use case, we can add such support.

Aaron Wood

unread,
Feb 17, 2021, 11:48:59 PM2/17/21
to Suraj Malhotra, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Wed, Feb 17, 2021 at 7:06 PM Suraj Malhotra <surajm...@google.com> wrote:
Drivers registering themselves with some entity implementing a particular protocol seems backwards to me. Drivers already have a way to describe what they have enumerated and what services they offer, via device properties. Needing to duplicate that information depending on whether the service it offers needs to get routed to something other than a driver seems not optimal.

Also, fwiw, rather than come up with hypothetical situations, I think it may be more useful to work through specific use cases we plan to support one day. A few examples (these may not be good group showing all edges worth considering):
  • How the FVM gets mounted
  • How a webUSB use case may work when there is a driver already bound to the device (it's identified as a HID device which has a generic driver, but there are capabilities not exposed by the driver which the website wants to make use of).
  • How wlan devices are enumerated
  • How a vendor proprietary technology might get exposed to the rest of the system without the OS standing in the way
    • The ability to program a keyboard to emit specific RGB lights based application loaded
    • A special camera ability some camera app might be able to make use of
  • How a manufacturing tool may calibrate hw while the rest of the system is using it
We don't currently just start drivers just because drivers exist on the system. We enumerate all drivers known at system assembly time, query them to find out under what conditions they should be loaded, and then only load them under those conditions. This system is known as driver binding. Although we've not really tried to tackle the problem of drivers known at system assembly time in earnest (ephemeral/universe drivers), I strongly suspect our binding system will hold up quite well for them.

This is the bit that I'm referring to.  How do we find/load drivers that aren't known at system assembly time?  How do we query them?  This is why I was asking about something like "how do we ask pkgfs for drivers that Foo?"
 

insmod and modprobe equivalents are really necessary given our architecture.

You meant "aren't", correct?  Maybe my view of what insmod and modprobe do in this case is different.  I can insmod/probe a driver that's not known at kernel compilation time, and that works.  I don't believe that's the case for Fuchsia at this point in time.

Suraj Malhotra

unread,
Feb 17, 2021, 11:49:16 PM2/17/21
to Aaron Wood, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
From the driver framework side, we have a mechanism planned for registering a driver with the framework. Figuring out who calls that and how is another matter, but providing a register mechanism is enough to be at parity with linux.

Aaron Wood

unread,
Feb 18, 2021, 12:07:55 AM2/18/21
to Suraj Malhotra, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Wed, Feb 17, 2021 at 8:49 PM Suraj Malhotra <surajm...@google.com> wrote:
From the driver framework side, we have a mechanism planned for registering a driver with the framework.

::nods::
 
Figuring out who calls that and how is another matter, but providing a register mechanism is enough to be at parity with linux.

That's the bit that I'm trying to get further into (especially since I've been deep into system/product assembly and seeing how we're piecing this together, and trying to think of how to make it work out of tree, and especially for dev workflows where while it's possible to just reassemble the topology and ota the device, it would be nice to just ephemerally install a package with a driver, and then have it become visible.  So I'm trying to talk about ways we might be able to do that.

Suraj Malhotra

unread,
Feb 18, 2021, 12:42:04 AM2/18/21
to Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, Abdulla Kamar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
Makes sense. We seem to be okay with an out of band mechanism for now for out of tree workflows (developer invokes registration via shell tool/ffx), but I'm sure the ux can improve with better tools at our disposal, along the lines you're driving at. 

Abdulla Kamar

unread,
Feb 18, 2021, 4:26:29 AM2/18/21
to Suraj Malhotra, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
P.S. It looks like everyone else has you covered, so I'm keeping quiet. I'm not ignoring you, I promise. :)

David Gilhooley

unread,
Feb 18, 2021, 11:08:04 AM2/18/21
to drivers-dev, Abdulla Kamar, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev, Suraj Malhotra
These conversations are great! At the risk of making the conversation even longer here are some of my thoughts:

- +Alice Neels -- Any of the solutions here that move driver discovery away from /devfs/ will fix the E2E input problem of adding a test input driver.
   - The problem today of writing a test driver for an E2E test is there's no well-defined way to "inject" that driver into the test component namespace so that it shows up at /dev/class/XXX. This would be solved if there's a FIDL Register function or if CF does the driver service routing.

- I would be really happy with a Drivers + CF working group and/or meetings. I always have questions about how things happen on the CF side and I think this could be helpful.

> How do we find/load drivers that aren't known at system assembly time?

I'm also interested in this question and I'm working on giving the DriverManager more structured ways to find drivers rather than globbing the /boot/driver/ and /system/driver directories. I think Fuchsia currently only needs to load unknown drivers for testing/debugging, so a simple API to register a driver will be fine for our needs. If anyone wants to talk more about this feel free to send me an email/message.

- Hunter originally mentioned a "device access layer". My initial thought to this is that we want to try and keep architecting our system in a "Capability" oriented way rather than use ACLs. Hunter's later suggestions of Provider/Registrar APIs sounded like they might work well though.

Suraj Malhotra

unread,
Feb 18, 2021, 11:19:15 AM2/18/21
to Hunter Freyer, Abdulla Kamar, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
Yes, binding is always performed eagerly once a device is discovered (and re-evaluated globally once new drivers are discovered).

As of today, the driver framework will be upset if more than two drivers match against a single device. Adding priority to evaluation is planned and there is a design doc describing some approaches we can take.

That said, bind programs themselves will never be sufficient for completely determining the correct party who should have access to a device. This is because there is sometimes information outside of it's purview. There are often cases where the the correct party is dynamically determined based on user workflow - webusb taking ownership of a device due to a website requesting it, the partitioner taking ownership of a device to reformat it (in both of these cases I think bind programs *can* work if applications could dynamically register themselves with bind programs that have higher priority triggering reevaluation). Policy for bind decisions also needs to be modifiable for product specific needs. If you're interested in how linux handles this, I suggest you read up on udev.

This is why we currently provide the ability for outside parties to manually bind and unbind drivers, altering decisions made by the framework. I'm not very happy with this at the moment and would prefer to have something where outside agent instead influence bind decisions by way of modifying device properties, or having device aggregators bind to devices and correctly determine the next course if action based on stack-specific knowledge.

On Thu, Feb 18, 2021, 7:16 AM Hunter Freyer <hjfr...@google.com> wrote:


On Thu, Feb 18, 2021 at 4:26 AM Abdulla Kamar <abd...@google.com> wrote:
P.S. It looks like everyone else has you covered, so I'm keeping quiet. I'm not ignoring you, I promise. :)

On Thu, 18 Feb 2021 at 16:42, Suraj Malhotra <surajm...@google.com> wrote:
Makes sense. We seem to be okay with an out of band mechanism for now for out of tree workflows (developer invokes registration via shell tool/ffx), but I'm sure the ux can improve with better tools at our disposal, along the lines you're driving at. 


On Wed, Feb 17, 2021, 9:06 PM Aaron Wood <aaro...@google.com> wrote:
On Wed, Feb 17, 2021 at 8:49 PM Suraj Malhotra <surajm...@google.com> wrote:
From the driver framework side, we have a mechanism planned for registering a driver with the framework.

::nods::
 
Figuring out who calls that and how is another matter, but providing a register mechanism is enough to be at parity with linux.

That's the bit that I'm trying to get further into (especially since I've been deep into system/product assembly and seeing how we're piecing this together, and trying to think of how to make it work out of tree, and especially for dev workflows where while it's possible to just reassemble the topology and ota the device, it would be nice to just ephemerally install a package with a driver, and then have it become visible.  So I'm trying to talk about ways we might be able to do that.
 

On Wed, Feb 17, 2021, 8:40 PM Aaron Wood <aaro...@google.com> wrote:
On Wed, Feb 17, 2021 at 7:06 PM Suraj Malhotra <surajm...@google.com> wrote:
Drivers registering themselves with some entity implementing a particular protocol seems backwards to me. Drivers already have a way to describe what they have enumerated and what services they offer, via device properties. Needing to duplicate that information depending on whether the service it offers needs to get routed to something other than a driver seems not optimal.

Also, fwiw, rather than come up with hypothetical situations, I think it may be more useful to work through specific use cases we plan to support one day. A few examples (these may not be good group showing all edges worth considering):
  • How the FVM gets mounted
  • How a webUSB use case may work when there is a driver already bound to the device (it's identified as a HID device which has a generic driver, but there are capabilities not exposed by the driver which the website wants to make use of).
  • How wlan devices are enumerated
  • How a vendor proprietary technology might get exposed to the rest of the system without the OS standing in the way
    • The ability to program a keyboard to emit specific RGB lights based application loaded
    • A special camera ability some camera app might be able to make use of
  • How a manufacturing tool may calibrate hw while the rest of the system is using it
We don't currently just start drivers just because drivers exist on the system. We enumerate all drivers known at system assembly time, query them to find out under what conditions they should be loaded, and then only load them under those conditions. This system is known as driver binding. Although we've not really tried to tackle the problem of drivers known at system assembly time in earnest (ephemeral/universe drivers), I strongly suspect our binding system will hold up quite well for them.

Point of clarification: am I correct that once a device has been discovered (i.e., added to the topology), we immediately go looking for a driver that wants to bind to it and do the binding eagerly? Is it ever the case that there are multiple drivers that could bind to a device? How is the "correct" one selected?

I put "correct" in quotes because, at least based on your webUSB use case, it seems like the "correct" behavior isn't necessarily well defined; we may want to rearrange driver binding based on user input. Is it at all clear to you how that user intent (e.g., "stop treating this USB keyboard as a keyboard, and instead connect it to Chromium") would get communicated to the driver framework?

Hunter Freyer

unread,
Feb 18, 2021, 1:37:22 PM2/18/21
to Abdulla Kamar, Suraj Malhotra, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, Adam Lesinski, drive...@fuchsia.dev
On Thu, Feb 18, 2021 at 4:26 AM Abdulla Kamar <abd...@google.com> wrote:
P.S. It looks like everyone else has you covered, so I'm keeping quiet. I'm not ignoring you, I promise. :)

On Thu, 18 Feb 2021 at 16:42, Suraj Malhotra <surajm...@google.com> wrote:
Makes sense. We seem to be okay with an out of band mechanism for now for out of tree workflows (developer invokes registration via shell tool/ffx), but I'm sure the ux can improve with better tools at our disposal, along the lines you're driving at. 


On Wed, Feb 17, 2021, 9:06 PM Aaron Wood <aaro...@google.com> wrote:
On Wed, Feb 17, 2021 at 8:49 PM Suraj Malhotra <surajm...@google.com> wrote:
From the driver framework side, we have a mechanism planned for registering a driver with the framework.

::nods::
 
Figuring out who calls that and how is another matter, but providing a register mechanism is enough to be at parity with linux.

That's the bit that I'm trying to get further into (especially since I've been deep into system/product assembly and seeing how we're piecing this together, and trying to think of how to make it work out of tree, and especially for dev workflows where while it's possible to just reassemble the topology and ota the device, it would be nice to just ephemerally install a package with a driver, and then have it become visible.  So I'm trying to talk about ways we might be able to do that.
 

On Wed, Feb 17, 2021, 8:40 PM Aaron Wood <aaro...@google.com> wrote:
On Wed, Feb 17, 2021 at 7:06 PM Suraj Malhotra <surajm...@google.com> wrote:
Drivers registering themselves with some entity implementing a particular protocol seems backwards to me. Drivers already have a way to describe what they have enumerated and what services they offer, via device properties. Needing to duplicate that information depending on whether the service it offers needs to get routed to something other than a driver seems not optimal.

Also, fwiw, rather than come up with hypothetical situations, I think it may be more useful to work through specific use cases we plan to support one day. A few examples (these may not be good group showing all edges worth considering):
  • How the FVM gets mounted
  • How a webUSB use case may work when there is a driver already bound to the device (it's identified as a HID device which has a generic driver, but there are capabilities not exposed by the driver which the website wants to make use of).
  • How wlan devices are enumerated
  • How a vendor proprietary technology might get exposed to the rest of the system without the OS standing in the way
    • The ability to program a keyboard to emit specific RGB lights based application loaded
    • A special camera ability some camera app might be able to make use of
  • How a manufacturing tool may calibrate hw while the rest of the system is using it
We don't currently just start drivers just because drivers exist on the system. We enumerate all drivers known at system assembly time, query them to find out under what conditions they should be loaded, and then only load them under those conditions. This system is known as driver binding. Although we've not really tried to tackle the problem of drivers known at system assembly time in earnest (ephemeral/universe drivers), I strongly suspect our binding system will hold up quite well for them.

Point of clarification: am I correct that once a device has been discovered (i.e., added to the topology), we immediately go looking for a driver that wants to bind to it and do the binding eagerly? Is it ever the case that there are multiple drivers that could bind to a device? How is the "correct" one selected?

I put "correct" in quotes because, at least based on your webUSB use case, it seems like the "correct" behavior isn't necessarily well defined; we may want to rearrange driver binding based on user input. Is it at all clear to you how that user intent (e.g., "stop treating this USB keyboard as a keyboard, and instead connect it to Chromium") would get communicated to the driver framework?

 

Adam Lesinski

unread,
Feb 18, 2021, 4:26:37 PM2/18/21
to David Gilhooley, Abdulla Kamar, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, drive...@fuchsia.dev, Suraj Malhotra
On Thu, Feb 18, 2021 at 8:08 AM David Gilhooley <dgilh...@google.com> wrote:
These conversations are great! At the risk of making the conversation even longer here are some of my thoughts:

- +Alice Neels -- Any of the solutions here that move driver discovery away from /devfs/ will fix the E2E input problem of adding a test input driver.
   - The problem today of writing a test driver for an E2E test is there's no well-defined way to "inject" that driver into the test component namespace so that it shows up at /dev/class/XXX. This would be solved if there's a FIDL Register function or if CF does the driver service routing.

- I would be really happy with a Drivers + CF working group and/or meetings. I always have questions about how things happen on the CF side and I think this could be helpful.
Yes this would be helpful. I find that as I get into the actual implementation of FTP-041 (Unified Services or just "services") a lot of small decisions are popping up that will be well informed by driver use-cases.

I'm happy to be POC for CF.

Gary Bressler

unread,
Feb 19, 2021, 7:54:51 PM2/19/21
to Adam Lesinski, David Gilhooley, Abdulla Kamar, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, drive...@fuchsia.dev, Suraj Malhotra
Also apologies for extending a very long thread, but a thought for contemplation: if CF supported limits on how many consumers were allowed for a service, would that be useful?

Justin Mattson

unread,
Feb 19, 2021, 8:25:41 PM2/19/21
to Gary Bressler, Adam Lesinski, David Gilhooley, Abdulla Kamar, Aaron Wood, Jocelyn Dang, Renato Mangini Dias, Hunter Freyer, Ruchira Ravoori, Dan Johnson, Erick Tryzelaar, component-framework-dev, drive...@fuchsia.dev, Suraj Malhotra
I think I also heard a request for something like a capability being provided by a component and each time a new client tries to connect a new instance of a component is started. This seems to me like we could build a library or reusable component which owns a collection in which it creates a new instance of a particular component for each incoming request.

Reply all
Reply to author
Forward
0 new messages