blob: 8575da3b223652b80ab81f5050e6aaf4773baeb9 [file] [log] [blame] [view] [edit]
# Troubleshoot common issues in DFv2 driver development
This troubleshooting guide provides debugging workflows for resolving
some common errors in Fuchsia driver development.
* [Debugging workflows](#debugging-workflows) - A list of debugging workflows
for diagnosing and fixing known issues.
* [Error messages](#error-messages) - A list of common error messages
related to driver development and how to fix them.
## Debugging workflows {:#debugging-workflows}
Debugging workflows for common issues:
- [Driver fails to bring up](#driver-fails-to-bring-up)
- [Driver fails to communicate with a FIDL service (PEER_CLOSED error)](#driver-fails-to-communicate-with-a-fidl-service)
- [Capability routing error](#capability-routing-error)
### Driver fails to bring up {:#driver-fails-to-bring-up}
A driver fails to "bring up" if it fails to load, bind, or start as
expected.
To debug this issue, try the following steps:
1. [Verify that the driver is loaded successfully](#verify-that-the-driver-is-loaded-successfully).
2. [Verify that the driver attempted to bind](#verify-that-the-driver-attempted-to-bind).
3. [Verify that the driver is started successfully](#verify-that-the-driver-is-started-successfully).
#### 1. Verify that the driver is loaded successfully {:#verify-that-the-driver-is-loaded-successfully}
If the driver is loaded successfully, you see a message like below in the logs:
```none {:.devsite-disable-click-to-copy}
Found boot driver: fuchsia-boot:///#meta/ahci.cm
```
Or you can dump the list of all drivers using the following command:
```posix-terminal
ffx driver list
```
This command prints output similar to the following:
```none {:.devsite-disable-click-to-copy}
fuchsia-boot:///adc#meta/adc.cm
fuchsia-boot:///ahci#meta/ahci.cm
fuchsia-boot:///alc5514#meta/alc5514.cm
fuchsia-boot:///alc5663#meta/alc5663.cm
```
If the driver is missing from the list, then it must have failed to load.
Here are some reasons to consider:
- The driver is not included in the build packages.
- There are issues with the driver's component manifest (`.cml`) file.
Common error messages related to component manifest files:
- [`Could not load driver: <...>: Failed to open bind file`](#could-not-load-driver-failed-to-open-bind-file)
- [`Could not load driver: <...>: Missing bind path`](#could-not-load-driver-failed-to-open-bind-file)
- [`Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND`](#could-not-start-driver-missing-binary)
#### 2. Verify that the driver attempted to bind {:#verify-that-the-driver-attempted-to-bind}
If the driver attempted to bind to a node, you see a message like below in the
logs:
```none {:.devsite-disable-click-to-copy}
Binding driver fuchsia-boot:///#meta/focaltech.cm
```
If you don't see this log message, there may be a mismatch between the driver's
bind rules and the node properties. To debug a mismatch, examine the driver's
bind rules and compare them to the node properties.
To view all node properties, run the following command:
```posix-terminal
ffx driver list-devices -v
```
This command prints output similar to the following:
```none {:.devsite-disable-click-to-copy}
Name : pt
Moniker : acpi._SB_.PCI0.ISA_.RTC_.pt
Driver : unbound
5 Properties
[ 1/ 5] : Key fuchsia.BIND_ACPI_ID Value 0x000004
[ 2/ 5] : Key "fuchsia.acpi.HID" Value "PNP0B00"
[ 3/ 5] : Key fuchsia.BIND_PROTOCOL Value 0x00001e
[ 4/ 5] : Key "fuchsia.driver.compat.Service" Value "fuchsia.driver.compat.Service.ZirconTransport"
[ 5/ 5] : Key "fuchsia.hardware.acpi.Service" Value "fuchsia.hardware.acpi.Service.ZirconTransport"
2 Offers
Service: fuchsia.driver.compat.Service
Source: board
Instances: default
Service: fuchsia.hardware.acpi.Service
Source: board
Instances: default
```
**However, if the driver is a composite driver**, you need to verify
that the [composite node spec][composite-node-spec] matches the
composite driver's bind rules and the node properties from the parent
nodes.
To view the composite node spec, run the following command:
```posix-terminal
ffx driver list-composite-node-specs -v
```
This command prints output similar to the following:
```none {:.devsite-disable-click-to-copy}
Name : COM1-composite-spec
Driver : fuchsia-boot:///uart16550#meta/uart16550.cm
Nodes : 3
Node 0 : "acpi" (Primary)
2 Bind Rules
[ 1/ 2] : Accept "fuchsia.BIND_PROTOCOL" { 0x00001e }
[ 2/ 2] : Accept fuchsia.BIND_ACPI_ID { 0x000007 }
3 Properties
[ 1/ 3] : Key "fuchsia.BIND_PROTOCOL" Value 0x00001e
[ 2/ 3] : Key fuchsia.BIND_ACPI_ID Value 0x000007
[ 3/ 3] : Key "fuchsia.acpi.HID" Value "PNP0501"
Node 1 : "sysmem"
1 Bind Rules
[ 1/ 1] : Accept "fuchsia.hardware.sysmem.Service" { "fuchsia.hardware.sysmem.Service.ZirconTransport" }
1 Properties
[ 1/ 1] : Key "fuchsia.hardware.sysmem.Service" Value "fuchsia.hardware.sysmem.Service.ZirconTransport"
Node 2 : "irq000"
3 Bind Rules
[ 1/ 3] : Accept "fuchsia.BIND_ACPI_ID" { 0x000007 }
[ 2/ 3] : Accept "fuchsia.BIND_PLATFORM_DEV_INTERRUPT_ID" { 0x000001 }
[ 3/ 3] : Accept "fuchsia.hardware.interrupt.Service" { "fuchsia.hardware.interrupt.Service.ZirconTransport" }
3 Properties
[ 1/ 3] : Key "fuchsia.BIND_ACPI_ID" Value 0x000007
[ 2/ 3] : Key "fuchsia.BIND_PLATFORM_DEV_INTERRUPT_ID" Value 0x000001
[ 3/ 3] : Key "fuchsia.hardware.interrupt.Service" Value "fuchsia.hardware.interrupt.Service.ZirconTransport"
```
The composite driver is not matched to the spec, the `Driver` field will say
`None`.
If there exist inconsistencies between the bind rules and node properties, you
need to adjust them until they match.
Additionally, if the bind rules use a FIDL-based node property, you need to add
an offer to the child so that the FIDL-based property is included.
For example, let's say the bind rules specify the following condition:
```none {:.devsite-disable-click-to-copy}
fuchsia.examples.gizmo.Service == fuchsia.examples.gizmo.Service.ZirconTransport;
```
Then the parent driver of the target node need to add the following offer to
the node:
```none {:.devsite-disable-click-to-copy}
zx::result child_result =
AddChild("zircon_transport_child", {}, {fdf::MakeOffer2<fuchsia_examples_gizmo::Service>()});
```
#### 3. Verify that the driver is started successfully {:#verify-that-the-driver-is-started-successfully}
If the driver is loaded successfully, you see a message like below in the logs:
```none {:.devsite-disable-click-to-copy}
Started driver url=fuchsia-boot:///ramdisk#meta/ramdisk.cm
```
But if this log message is missing, then the driver must have failed to start.
To debug this issue, first check if the driver's `Start()` function is called.
For this task, it's recommended to update the `Start()`function to print some
log messages.
If the `Start()` function is never even called, here are some possible reasons:
- [`__fuchsia_driver_registration__ symbol not available`](#fuchsia-driver-registration-symbol-not-available)
- [`Driver-Loader: libdriver.so: Not in allowlist`](#driver-loader-libdriver-so-not-in-allowlist)
However, if the `Start()` function is called but the driver still fails to
start, it may fail in one of the following ways:
- The driver's `Start()` function replies or returns an error.
- The driver overrides `void Start(StartCompleter completer)` and does not
reply to the completer.
If the driver's `Start()` function replies or returns an error, you see
messages similar to the following in the logs:
```none {:.devsite-disable-click-to-copy}
[driver_host,driver] ERROR: [src/devices/bin/driver_host/driver_host.cc(134)] Failed to start driver url=fuchsia-pkg://fuchsia.com/simple_driver#meta/simple.cm status_str=ZX_ERR_INTERNAL
[driver_manager.cm] ERROR: [src/devices/bin/driver_manager/driver_host.cc(152)] Failed to start driver 'driver/simple.so' in driver host: ZX_ERR_INTERNAL
```
At this point, start debugging the `Start()` function to identify
the cause of the error. Here are some possible reasons:
- [Driver fails to communicate with a FIDL service](#driver-fails-to-communicate-with-a-fidl-service)
- [`Required service <...> was not available for target component`](#required-service-was-not-available-for-target-component)
### Driver fails to communicate with a FIDL service (PEER_CLOSED error) {:#driver-fails-to-communicate-with-a-fidl-service}
If a FIDL service is not set up properly in the driver, you may get a
`PEER_CLOSED` error when the driver tries to send a request to the
FIDL service.
To debug a `PEER_CLOSED` error, try the following steps:
1. [Verify the outgoing directory](#verify-the-outgoing-directory).
2. [Check the instance name](#check-the-instance-name).
3. [Check for capability routing issues](#check-for-capability-routing-issues).
Plus, to see proper FIDL service setups in DFv2 drivers, check out
these [transport examples][transport-examples].
#### 1. Verify the outgoing directory {:#verify-the-outgoing-directory}
Examine the setup where the parent driver adds the FIDL service to its
outgoing directory, for example:
```none {:.devsite-disable-click-to-copy}
zx::result result = outgoing()->AddService<fuchsia_examples_gizmo::Service>(std::move(handler));
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add service", KV("status", result.status_string()));
return result.take_error();
}
```
#### 2. Check the instance name {:#check-the-instance-name}
If the target driver is a [composite driver][composite-drivers], it needs to pass
the parent node's name to the FIDL service instance.
For example, let's say a composite driver has the following bind rules:
```none {:.devsite-disable-click-to-copy}
composite mali;
using fuchsia.arm.platform;
using fuchsia.platform;
using fuchsia.hardware.gpu.mali;
primary node "mali" {
fuchsia.hardware.gpu.mali.Service == fuchsia.hardware.gpu.mali.Service.DriverTransport;
}
node "pdev" {
fuchsia.BIND_PROTOCOL == fuchsia.platform.BIND_PROTOCOL.DEVICE;
fuchsia.BIND_PLATFORM_DEV_VID == fuchsia.arm.platform.BIND_PLATFORM_DEV_VID.ARM;
fuchsia.BIND_PLATFORM_DEV_PID == fuchsia.platform.BIND_PLATFORM_DEV_PID.GENERIC;
fuchsia.BIND_PLATFORM_DEV_DID == fuchsia.arm.platform.BIND_PLATFORM_DEV_DID.MAGMA_MALI;
}
```
If we want to connect to the `fuchsia.hardware.platform.device` service from the
parent node named `pdev`, the driver needs to include the following code:
```none {:.devsite-disable-click-to-copy}
auto platform_device = incoming->Connect<fuchsia_hardware_platform_device::Service::Device>("pdev");
```
#### 3. Check for capability routing issues {:#check-for-capability-routing-issues}
See the [Capability routing error](#capability-routing-error) section below.
### Capability routing error {:#capability-routing-error}
To use a service in Fuchsia, the service's [capability][capabilities] must be
routed correctly to the driver at runtime. And to route the capability to
a child driver, the parent driver needs to expose the capability and offer
it to the child.
The following command can help diagnose capability routing issues:
```posix-terminal
ffx component doctor <DRIVER_URL>
```
Note: When you run this command, the driver must be running. This may require
you to modify the driver so that it still runs after capability routing fails.
This command prints output similar to the following:
```none {:.devsite-disable-click-to-copy}
$ ffx component doctor fuchsia-pkg://fuchsia.com/driver_transport#meta/driver_transport_child.cm
Moniker: bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child
Used Capability Result
[✓] fuchsia.logger.LogSink Success
[✗] fuchsia.examples.gizmo.Service `fuchsia.examples.gizmo.Service` was not offered to `bootstrap/full-pkg-
drivers:dev.driver_transport_parent.driver_transport_child`
by parent.
For further diagnosis, try:
$ ffx component route bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child fuchsia.examples.gizmo.Service
```
To resolve issues related to capability routing, try the following steps:
1. [Expose the capability](#expose-the-capability).
2. [Offer the capability](#offer-the-capability).
3. [Use the capability](#use-the-capability).
Plus, to see how capabilities are routed in DFv2 drivers,
check out these [transport examples][transport-examples].
#### 1. Expose the capability {:#expose-the-capability}
If the parent driver does not expose the capability correctly, you may see a
message like below in the logs:
```none {:.devsite-disable-click-to-copy}
[full-drivers:dev.driver_transport_parent.driver_transport_child] WARN: Required service `fuchsia.examples.gizmo.Service` was not available for target component `bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child`: could not find capability: `fuchsia.examples.gizmo.Service` was not exposed to `bootstrap` from child `#full-drivers:dev.driver_transport_parent`. For more, run `ffx component doctor bootstrap`.
To learn more, see https://fuchsia.dev/go/components/connect-errors
```
To fix this issue, examine how the capability is exposed in the parent
driver's component manifest (`.cml`) file, for example:
```none {:.devsite-disable-click-to-copy}
{
include: [ 'syslog/client.shard.cml' ],
program: {
runner: 'driver',
binary: 'driver/driver_transport_parent.so',
bind: 'meta/bind/parent-driver.bindbc',
},
capabilities: [
{ service: 'fuchsia.examples.gizmo.Service' },
],
expose: [
{
service: 'fuchsia.examples.gizmo.Service',
from: 'self',
},
],
}
```
#### 2. Offer the capability {:#offer-the-capability}
To check if the offer of the service exists in the child node, run the
following command (you may also use the `ffx component doctor` command):
```posix-terminal
ffx driver node list <child_node_name>
```
This command prints the details of all the services offered in
each node, for example:
```none {:.devsite-disable-click-to-copy}
Name: intel-hda-000
Moniker: PCI0.bus.00_01_0.00_01_0.intel-hda-000
Owner: parent
Node State: Bound
Host Koid:
Parent Count: 1
Child Count: 1
Bus Topology: Bus Type Stability Address
Pci Stable 0, 1, 0
Node Properties: Key Value
fuchsia.BIND_PROTOCOL 76
fuchsia.driver.compat.Service fuchsia.driver.compat.Service.ZirconTransport
Node Offers: Service Source Instances
fuchsia.driver.compat.Service PCI0.bus.00_01_0.00_01_0 default
```
Also, if the offer is not found in the child node, you may see
a message like below in the logs:
```none {:.devsite-disable-click-to-copy}
[00008.035682][full-drivers:dev.driver_transport_parent.driver_transport_child] WARN: Required service `fuchsia.examples.gizmo.Service` was not available for target component `bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child`: could not find capability: `fuchsia.examples.gizmo.Service` was not offered to `bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child` by parent.
To learn more, see https://fuchsia.dev/go/components/connect-errors
```
To fix this issue, examine the setup where the parent driver includes
the offer to the child node, for example:
```none {:.devsite-disable-click-to-copy}
// Add a child with a `fuchsia.examples.gizmo.Service` offer.
zx::result child_result =
AddChild("driver_transport_child", {}, {fdf::MakeOffer2<fuchsia_examples_gizmo::Service>()});
if (child_result.is_error()) {
return child_result.take_error();
}
```
#### 3. Use the capability {:#use-the-capability}
To use a capability, the driver needs to declare that it wants to use the
capability.
If this is not declared correctly, you may see a message like below
in the logs:
```none {:.devsite-disable-click-to-copy}
[00008.631682][full-drivers:dev.driver_transport_parent.driver_transport_child] WARN: No capability available at path /svc/fuchsia.examples.gizmo.Service/default/device for component bootstrap/full-drivers:dev.driver_transport_parent.driver_transport_child, verify the component has the proper `use` declaration.
```
To fix this issue, examine how the capability's use is declared in the
driver's component manifest (`.cml`) file, for example:
```none {:.devsite-disable-click-to-copy}
{
include: [ 'syslog/client.shard.cml' ],
program: {
runner: 'driver',
binary: 'driver/driver_transport_child.so',
bind: 'meta/bind/child-driver.bindbc',
colocate: 'true',
},
use: [
{ service: 'fuchsia.examples.gizmo.Service' },
],
}
```
## Error messages {:#error-messages}
Common error messages in Fuchsia driver development:
- [`Failed to load driver <...> driver note not found`](#failed-to-load-driver)
- [`Required service <...> was not available for target component`](#required-service-was-not-available-for-target-component)
- [`Driver-Loader: libdriver.so: Not in allowlist`](#driver-loader-libdriver-so-not-in-allowlist)
- [`__fuchsia_driver_registration__ symbol not available`](#fuchsia-driver-registration-symbol-not-available)
- [`Could not load driver: <...>: Failed to open bind file (or Missing bind path)`](#could-not-load-driver-failed-to-open-bind-file)
- [`no member named 'destroy' in 'fdf_internal::DriverServer<...>`](#no-member-named-destroy)
- [`Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND`](#could-not-start-driver-missing-binary)
### Failed to load driver <...> driver note not found {:#failed-to-load-driver}
When migrating a DFv1 driver to DFv2, you may run into the following error message
in the logs:
```none {:.devsite-disable-click-to-copy}
Failed to load driver <...> driver not found
```
When this error occurs, examine the driver's component manifest (`.cml`) file
for correctness. See [Driver fails to bring up](#driver-fails-to-bring-up).
### Required service <...> was not available for target component {:#required-service-was-not-available-for-target-component}
This error occurs if the driver does not have a service capability correctly exposed
and routed to it from the parent driver.
To fix this issue, try the [Capability routing error](#capability-routing-error)
workflow.
**However, if the required service is `fuchsia.driver.compat`, follow the
instructions below**:
The error occurs if the driver does not have a `fuchsia.driver.compat` service
routed to it from a DFv2 driver. To route this service, the DFv2 driver needs to
[set up a compat device server][compat-device-server] for each child.
To fix this issue, go through each parent driver starting from the affected driver.
For example, if the node topology shows `A->B->C->D` and `D` is the affected driver,
then go through `C`, `B`, and `A`. For each parent driver in the chain, if it's
written in DFv2, verify that its compat device server is set up properly.
Here are some common issues related to setting up a compat device server:
- The compat device server must be initialized with the correct child node name.
- The child must be [added with an offer][offer-compat-device-server] from the
compat device server.
### Driver-Loader: libdriver.so: Not in allowlist {:#driver-loader-libdriver-so-not-in-allowlist}
This error occurs if `libdriver` is in one of a DFv2 driver's dependencies, which
can be transitive.
To fix the issue, search and remove `//src/devices/lib/driver` from the dependencies.
To find the dependency, use the following command:
```posix-terminal
fx gn path <out_directory> //path/to/driver //path/to/libdriver
```
### \__fuchsia_driver_registration\_\_ symbol not available {:#fuchsia-driver-registration-symbol-not-available}
When migrating a DFv1 driver to DFv2, you may run into the following error message
in the logs:
```none {:.devsite-disable-click-to-copy}
[driver_host,driver] ERROR: [src/devices/bin/driver_host/driver.cc(120)] __fuchsia_driver_registration__ symbol not available_.
[driver_host,driver] ERROR: [src/devices/bin/driver_host/driver.cc(316)] Failed to start driver 'fuchsia-pkg://fuchsia.com/fake-battery#meta/fake_battery.cm', could not Load driver: ZX_ERR_NOT_FOUND
```
This error occurs when a DFv2 driver doesn't include the `FUCHSIA_DRIVER_EXPORT` macro.
To fix this issue, see [Add the driver export macro][driver-export-macro].
Also, make sure that the macro is defined in `.cc` files, not in header (`.h`) files.
### Could not load driver: <...>: Failed to open bind file (or Missing bind path) {:#could-not-load-driver-failed-to-open-bind-file}
When migrating a DFv1 driver to DFv2, you may run into the following error message
in the logs:
```none {:.devsite-disable-click-to-copy}
Could not load driver: fuchsia-pkg://fuchsia.com/fake-battery#meta/fake_battery.cm: Failed to open bind file 'meta/bind/fake-battery-driver_2.bindbc'
```
Or
```none {:.devsite-disable-click-to-copy}
Could not load driver: fuchsia-pkg://fuchsia.com/fake-battery#meta/fake_battery.cm: Missing bind path
```
This error occurs when the `bind` field is either missing or incorrect in
a DFv2 driver's component manifest (`.cml`) file, for example:
```none {:.devsite-disable-click-to-copy}
{
include: [
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/fake_battery.so",
bind: <incorrect bind file path>,
},
}
```
The `bind` field value needs to follow the format `meta/bind/<bind_output>` where
`bind_output` is a field with the same name in the `driver_bind_rules` target
in the build file, for example:
```none {:.devsite-disable-click-to-copy}
driver_bind_rules("fake_battery_bind") {
rules = "meta/fake-battery-driver.bind"
bind_output = "fake-battery-driver.bindbc"
deps = [ "//src/devices/bind/fuchsia.test" ]
deps += [ "//src/devices/bind/fuchsia.platform" ]
}
```
For this bind rule target example, the correct `bind` field in the component
manifest file looks like below:
```none {:.devsite-disable-click-to-copy}
{
include: [
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/fake_battery.so",
bind: "meta/bind/fake-battery-driver.bindbc",
},
}
```
However, if `bind_output` is not explicitly defined in a bind rule target,
the default value is the target name with `.bindbc` appended to it, which would
be `fake_battery_bind.bindbc` in the example above.
### Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND {:#could-not-start-driver-missing-binary}
When writing a DFv2 driver, you may run into the following error message
in the logs:
```none {:.devsite-disable-click-to-copy}
Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND
```
The `binary` field value needs to follow the format `driver/<driver_output>.so` where
`driver_output` is a field with the same name in the `fuchsia_driver` target in the
build file, for example:
```
fuchsia_cc_driver("driver") {
output_name = "simple"
sources = [ "simple_driver.cc" ]
deps = [
"//sdk/fidl/fuchsia.driver.compat:fuchsia.driver.compat_cpp",
"//sdk/lib/driver/compat/cpp",
"//sdk/lib/driver/component/cpp",
"//src/devices/bind/fuchsia.test:fuchsia.test_cpp",
"//src/devices/lib/driver:driver_runtime",
]
}
```
For this bind rule target example, the correct `binary` field in the component manifest file looks
like below:
```
{
include: [
"driver_component/driver.shard.cml",
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/simple.so",
bind: "meta/bind/simple_driver.bindbc",
},
}
```
### no member named 'destroy' in 'fdf_internal::DriverServer<...>' {:#no-member-named-destroy}
If a DFv2 driver implements an open FIDL protocol (that is,
`open protocol <PROTOCOL_NAME>`), the driver needs to override and implement
the `handle_unknown_method()` function.
For example, let's say a driver implements the following protocol:
```none {:.devsite-disable-click-to-copy}
open protocol VirtualController {
...
};
```
Then this driver needs to include the following `handle_unknown_method()` function:
```none {:.devsite-disable-click-to-copy}
void handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::VirtualController> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override;
```
## Other resources {:#other-resources}
* [View driver information][view-driver-information] - A reference page including how to
use `ffx driver` for debugging.
<!-- Reference links -->
[composite-drivers]: /docs/development/drivers/developer_guide/create-a-composite-node.md
[composite-node-spec]: /docs/development/drivers/developer_guide/create-a-composite-node.md#what-is-a-composite-node-specification
[dfv2-driver-transport]: https://cs.opensource.google/fuchsia/fuchsia/+/main:examples/drivers/transport/driver/v2/
[dfv2-zircon-transport]: https://cs.opensource.google/fuchsia/fuchsia/+/main:examples/drivers/transport/zircon/v2/
[transport-examples]: /docs/development/drivers/developer_guide/driver-examples.md#transport_examples
[capabilities]: /docs/concepts/components/v2/capabilities/README.md
[compat-device-server]: /docs/development/drivers/migration/set-up-compat-device-server.md#set-up-the-compat-device-server
[offer-compat-device-server]: /docs/development/drivers/migration/set-up-compat-device-server.md#offer-the-compat-device-server-to-the-target-child-node
[driver-export-macro]: /docs/development/drivers/developer_guide/write-a-minimal-dfv2-driver.md#add-the-driver-export-macro
[view-driver-information]: /docs/development/tools/ffx/workflows/view-driver-information.md