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
)