This troubleshooting guide provides debugging workflows for resolving some common errors in Fuchsia driver development.
- Debugging workflows - A list of debugging workflows for diagnosing and fixing known issues.
- Error messages - A list of common error messages related to driver development and how to fix them.
Debugging workflows
Debugging workflows for common issues:
- Driver fails to bring up
- Driver fails to communicate with a FIDL service (PEER_CLOSED error)
- Capability routing error
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:
- Verify that the driver is loaded successfully.
- Verify that the driver attempted to bind.
- Verify that the driver is started successfully.
1. Verify that the driver is loaded successfully
If the driver is loaded successfully, you see a message like below in the logs:
Found boot driver: fuchsia-boot:///#meta/ahci.cm
Or you can dump the list of all drivers using the following command:
ffx driver list
This command prints output similar to the following:
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: <...>: Missing bind path
Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND
2. 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:
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:
ffx driver list-devices -v
This command prints output similar to the following:
Name : pt
Moniker : dev.sys.platform.pt.acpi._SB_.PCI0.ISA_.RTC_.pt
Driver : unbound
6 Properties
[ 1/ 6] : Key fuchsia.BIND_ACPI_ID Value 0x000004
[ 2/ 6] : Key "fuchsia.acpi.HID" Value "PNP0B00"
[ 3/ 6] : Key fuchsia.BIND_PROTOCOL Value 0x00001e
[ 4/ 6] : Key "fuchsia.driver.compat.Service" Value "fuchsia.driver.compat.Service.ZirconTransport"
[ 5/ 6] : Key "fuchsia.hardware.acpi.Service" Value "fuchsia.hardware.acpi.Service.ZirconTransport"
[ 6/ 6] : Key "fuchsia.platform.DRIVER_FRAMEWORK_VERSION" Value 0x000002
2 Offers
Service: fuchsia.driver.compat.Service
Source: dev.sys.platform.pt
Instances: default
Service: fuchsia.hardware.acpi.Service
Source: dev.sys.platform.pt
Instances: default
However, if the driver is a composite driver, you need to verify that the 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:
ffx driver list-composite-node-specs -v
This command prints output similar to the following:
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:
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:
zx::result child_result =
AddChild("zircon_transport_child", {}, {fdf::MakeOffer2<fuchsia_examples_gizmo::Service>()});
3. Verify that the driver is started successfully
If the driver is loaded successfully, you see a message like below in the logs:
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:
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:
[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
Required service <...> was not available for target component
Driver fails to communicate with a FIDL service (PEER_CLOSED error)
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:
Plus, to see proper FIDL service setups in DFv2 drivers, check out these transport examples.
1. Verify the outgoing directory
Examine the setup where the parent driver adds the FIDL service to its outgoing directory, for example:
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
If the target driver is a composite driver, 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:
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:
auto platform_device = incoming->Connect<fuchsia_hardware_platform_device::Service::Device>("pdev");
3. Check for capability routing issues
See the Capability routing error section below.
Capability routing error
To use a service in Fuchsia, the service's capability 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:
ffx component doctor <DRIVER_URL>
This command prints output similar to the following:
$ 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:
Plus, to see how capabilities are routed in DFv2 drivers, check out these transport examples.
1. Expose the capability
If the parent driver does not expose the capability correctly, you may see a message like below in the logs:
[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:
{
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
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):
ffx driver list-devices -v
This command prints the details of all the services offered in each node, for example:
Name : RTC_-composite-spec
Moniker : dev.sys.platform.pt.acpi._SB_.PCI0.ISA_.RTC_.pt.RTC_-composite-spec
Driver : fuchsia-boot:///intel-rtc#meta/intel-rtc.cm
0 Properties
4 Offers
Service: fuchsia.driver.compat.Service
Source: dev.sys.platform.pt
Instances: default acpi
Service: fuchsia.hardware.acpi.Service
Source: dev.sys.platform.pt
Instances: default acpi
Service: fuchsia.driver.compat.Service
Source: dev.sys.platform.00_00_1b
Instances: sysmem
Service: fuchsia.hardware.sysmem.Service
Source: dev.sys.platform.00_00_1b
Instances: sysmem
Also, if the offer is not found in the child node, you may see a message like below in the logs:
[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:
// 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
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:
[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:
{
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
Common error messages in Fuchsia driver development:
Failed to load driver <...> driver note not found
Required service <...> was not available for target component
Driver-Loader: libdriver.so: Not in allowlist
__fuchsia_driver_registration__ symbol not available
Could not load driver: <...>: Failed to open bind file (or Missing bind path)
no member named 'destroy' in 'fdf_internal::DriverServer<...>
Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND
Failed to load driver <...> driver note not found
When migrating a DFv1 driver to DFv2, you may run into the following error message in the logs:
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.
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 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 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 from the compat device server.
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:
fx gn route <out_directory> //path/to/driver //path/to/libdriver
__fuchsia_driver_registration__ symbol not available
When migrating a DFv1 driver to DFv2, you may run into the following error message in the logs:
[driver_host,driver] ERROR: [src/devices/bin/driver_host/driver.cc(120)] __fuchsia_driver_registration__ symbol not available, falling back to __fuchsia_driver_lifecycle__.
[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.
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)
When migrating a DFv1 driver to DFv2, you may run into the following error message in the logs:
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
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:
{
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:
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:
{
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
When writing a DFv2 driver, you may run into the following error message in the logs:
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<...>'
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:
open protocol VirtualController {
...
};
Then this driver needs to include the following handle_unknown_method()
function:
void handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::VirtualController> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override;
Other resources
- View driver information - A reference page including how to
use
ffx driver
for debugging.