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.
The steps are:
- Identify the target FIDL protocol
- Add a ServerBindingGroup object
- Create a callback function
- Initialize a devfs connector
- Bind the devfs connector to a dispatcher
- Add the devfs connector to a child node
1. Identify the target FIDL protocol
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.
2. Add a ServerBindingGroup object
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)
3. Create a callback function
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)
4. Initialize a devfs connector
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)
5. Bind the devfs connector to a dispatcher
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)
6. Add the devfs connector to a child node
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)