blob: b4e7177713a83ed6b10b5be977df7aae43fa2d53 [file] [log] [blame] [view]
# Driver utilities
Caution: This page may contain information that is specific to the legacy
version of the driver framework (DFv1).
Driver utilities are Fuchsia applications that communicate with devices used for
diagnostics and exported by drivers. For example Inter-Integrated Circuit (I2C)
devices can be scanned and communicated through the [i2cutil](/src/devices/i2c/bin)
command line utility. For example:
```
i2cutil ping
/dev/class/i2c/000: OK
[00164.657] 04506:05266> i2c: error on bus
Error -1
/dev/class/i2c/001: ERROR
/dev/class/i2c/002: OK
/dev/class/i2c/003: OK
/dev/class/i2c/004: OK
```
## API
The communication mechanism between between drivers and applications is
[FIDL](/docs/development/languages/fidl/README.md), and hence the FIDL API
exported by any given driver fully defines what diagnostics can be performed on
it. For instance for I2C, from
[i2c.fidl](/sdk/fidl/fuchsia.hardware.i2c/i2c.fidl), there is a
`Transfer()` FIDL method that allows for writes and reads from I2C devices.
Note: Banjo should not be used for driver utilities application to driver
communication.
TODO(https://fxbug.dev/42122211): Add inspect usage description.
## Discovery
Drivers advertise services which can be routed to non-driver components. When
a service capability is routed to a non-driver component, that component will
see an aggregated list of all instances of that service. (see
[Driver Communication][driver-communication].) As a user, you can navigate the
component framework to see what services are advertised and where they are
routed using the `fx component` commands.
## Creating new driver utilities
### Discovery
You can discover existing drivers with `devfs`. New devices become discoverable
when their driver performs a `DdkAdd()` (for C++ drivers) operation.
### API
Existing utilities like `spiutil` make use of currently existing FIDL APIs. To
extend the functionality exported by an existing driver, the FIDL API the
existing driver exports can be extended/evolved by following
[FIDL ABI and API compatibility guide][abi-api-compat].
In cases when there is no existing FIDL API, you need to add new FIDL files to
a folder within [/sdk/fidl](/sdk/fidl).
To enable FIDL communication in C++ drivers that do not already offer a FIDL
API, complete the following steps:
1. Make the device messagable by deriving from `ddk::Messageable`.
2. Add methods for the FIDL protocol methods of the given FIDL API.
For instance for [SPI](/src/devices/spi/drivers/spi/spi.h):
```
using SpiChildType =
ddk::Device<SpiChild, ddk::Messageable<fuchsia_hardware_spi::Device>::Mixin>;
class SpiChild : public SpiChildType,
public ddk::SpiProtocol<SpiChild, ddk::base_protocol> {
...
// FIDL methods.
void Transmit(fidl::VectorView<uint8_t> data, TransmitCompleter::Sync completer) override;
...
```
### Utility
To implement the Fuchsia application that would communicate with the device,
call into the FIDL API. For this utilize the FIDL bindings for your language of
choice, for C++:
* [New C++ bindings](/docs/reference/fidl/bindings/cpp-bindings.md)
For example for I2C in [i2cutil](/src/devices/i2c/bin) using the new C++ bindings
we have:
```
fidl::WireSyncClient<fuchsia_hardware_i2c::Device2> client(zx::channel(channel));
auto read = client.Transfer(...);
```
This calls the `Transfer()` method to write and read from an I2C device.
<!-- xrefs -->
[abi-api-compat]: /docs/development/languages/fidl/guides/compatibility/README.md
[driver-communication]: /docs/concepts/drivers/driver_communication.md