This guide provides instructions on how to set up devfs
in a DFv2 driver, which enables the driver's services to be discovered by other Fuchsia components in the system. This guide uses an example DFv2 driver to walk through the devfs
setup process.
Important: Setting up devfs
is no longer necessary. See Driver Communication for a guide on how to use services in your driver.
The steps are:
In the DFv2 driver's source code, identify the target FIDL protocol (which can be inherited from fidl::Server<>
or fidl::WireServer<>
) for this devfs
setup, for example:
class RetrieverDriver final : public fdf::DriverBase, public fidl::Server<fuchsia_examples_metadata::Retriever> { ... // fuchsia.hardware.test/Child implementation. void GetMetadata(GetMetadataCompleter::Sync& completer) override { ... } };
(Source: retriever-driver.cc
)
The examples in this guide use the Retriever
protocol defined in fuchsia.examples.metadata.fidl
.
Add a ServerBindingGroup
object to the driver class for binding the FIDL protocol, for example:
class RetrieverDriver final : public fdf::DriverBase, public fidl::Server<fuchsia_examples_metadata::Retriever> { ... fidl::ServerBindingGroup<fuchsia_examples_metadata::Retriever> bindings_;
(Source: retriever-driver.cc
)
Create a callback function, which will be invoked when a client tries to connect to the driver. In this callback function, add the binding from the ServerBindingGroup<>
object to a ServerEnd
object, for example:
class RetrieverDriver final : public fdf::DriverBase, public fidl::Server<fuchsia_examples_metadata::Retriever> { ... void Serve(fidl::ServerEnd<fuchsia_examples_metadata::Retriever> request) { bindings_.AddBinding(dispatcher(), std::move(request), this, fidl::kIgnoreBindingClosure); }
(Source: retriever-driver.cc
)
Initialize a devfs
connector object by passing the target FIDL protocol in step 1 and the callback function created in step 3, for example:
driver_devfs::Connector<fuchsia_examples_metadata::Retriever> devfs_connector_{ fit::bind_member<&RetrieverDriver::Serve>(this)};
(Source: retriever-driver.cc
)
Bind the devfs
connector to the driver's dispatcher, for example:
zx::result connector = devfs_connector_.Bind(dispatcher()); if (connector.is_error()) { FDF_SLOG(ERROR, "Failed to bind devfs connector.", KV("status", connector.status_string())); return connector.status_value(); }
(Source: retriever-driver.cc
)
When adding a child node, pass the bound devfs
connector from step 5 to the node's NodeAddArgs
object. To do so, create a DevfsAddArgs
object, which is defined in fuchsia.driver.framework/topology.fidl
, and set the connector
field to the devfs
connector, for example:
fuchsia_driver_framework::DevfsAddArgs devfs_args{ {.connector = std::move(connector.value())} }; zx::result owned_child = AddOwnedChild("retriever", devfs_args); if (owned_child.is_error()) { FDF_SLOG(ERROR, "Failed to add owned child.", KV("status", owned_child.status_string())); return owned_child.error_value(); }
(Source: retriever-driver.cc
)