本问题排查指南提供了调试工作流,用于解决 Fuchsia 驱动程序开发中的一些常见错误。
调试工作流
针对常见问题调试工作流:
驱动程序无法启动
驱动程序无法“启动”如果未能加载、绑定或启动 符合预期。
如需调试此问题,请尝试执行以下步骤:
1. 验证驱动程序是否已成功加载
如果驱动程序成功加载,您会在日志中看到如下所示的消息:
Found boot driver: fuchsia-boot:///#meta/ahci.cm
或者,您可以使用以下命令转储所有驱动程序的列表:
ffx driver list此命令会输出类似于以下内容的输出:
fuchsia-boot:///adc#meta/adc.cm
fuchsia-boot:///ahci#meta/ahci.cm
fuchsia-boot:///alc5514#meta/alc5514.cm
fuchsia-boot:///alc5663#meta/alc5663.cm
如果列表中缺少该驱动程序,则肯定是未能加载该驱动程序。
以下是您应考虑的一些原因:
- 该驱动程序未包含在 build 软件包中。
 - 驱动程序的组件清单 (
.cml) 文件存在问题。 
与组件清单文件相关的常见错误消息:
Could not load driver: <...>: Failed to open bind fileCould not load driver: <...>: Missing bind pathFailed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND
2. 验证驱动程序是否尝试绑定
如果驱动程序尝试绑定到节点,您会在 日志:
Binding driver fuchsia-boot:///#meta/focaltech.cm
如果您没有看到此日志消息,可能是驾驶员的 绑定规则和节点属性。如需对不匹配问题进行调试,请检查驱动程序的 绑定规则,并将其与节点属性进行比较。
如需查看所有节点属性,请运行以下命令:
ffx driver list-devices -v此命令会输出类似于以下内容的输出:
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
但是,如果驱动程序是复合驱动程序,则您需要验证 复合节点规范与 复合驱动程序的绑定规则和来自父节点的节点属性 节点。
如需查看复合节点规范,请运行以下命令:
ffx driver list-composite-node-specs -v此命令会输出类似于以下内容的输出:
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"
复合驱动程序不符合规范,Driver 字段将显示
None。
如果绑定规则和节点属性之间存在不一致, 您需要对它们进行调整,直到它们一致为止。
此外,如果绑定规则使用基于 FIDL 的节点属性,则需要将 子项的优惠,以便将基于 FIDL 的媒体资源包含在内。
例如,假设绑定规则指定了以下条件:
fuchsia.examples.gizmo.Service == fuchsia.examples.gizmo.Service.ZirconTransport;
然后,目标节点的父级驱动程序需要将以下优惠添加到 节点:
zx::result child_result =
    AddChild("zircon_transport_child", {}, {fdf::MakeOffer2<fuchsia_examples_gizmo::Service>()});
3. 验证驱动程序是否已成功启动
如果驱动程序成功加载,您会在日志中看到如下所示的消息:
Started driver url=fuchsia-boot:///ramdisk#meta/ramdisk.cm
但如果找不到这条日志消息,说明驾驶员可能无法启动。
如需调试此问题,请先检查是否调用了驱动程序的 Start() 函数。
对于此任务,建议更新 Start() 函数以输出一些
日志消息。
如果系统甚至从未调用 Start() 函数,则可能是以下一些原因:
不过,如果调用了 Start() 函数,但驱动程序仍无法
启动,它可能会通过以下某种方式失败:
- 驱动程序的 
Start()函数会回复或返回错误。 - 驱动程序会替换 
void Start(StartCompleter completer),不会 回复完成者。 
如果驱动程序的 Start() 函数回复或返回错误,您会看到
类似于以下内容的消息:
[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
此时,请开始调试 Start() 函数,以确定
出错的原因。以下是一些可能的原因:
驱动程序无法与 FIDL 服务通信(PEER_CLOSED 错误)
如果在驱动程序中未正确设置 FIDL 服务,您可能会收到
PEER_CLOSED 错误(如果驾驶员尝试向
FIDL 服务。
如需调试 PEER_CLOSED 错误,请尝试执行以下步骤:
另外,如需了解 DFv2 驱动程序中的正确 FIDL 服务设置,请参阅 这些传输示例。
1. 验证外发目录
检查父级驱动程序将 FIDL 服务添加到 传出目录,例如:
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. 检查实例名称
如果目标驱动程序是复合驱动程序,则需要通过 FIDL 服务实例的父节点名称。
例如,假设某个复合驱动程序具有以下绑定规则:
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;
}
如果我们想从 fuchsia.hardware.platform.device 服务连接到
父节点 pdev,驱动程序需要包含以下代码:
auto platform_device = incoming->Connect<fuchsia_hardware_platform_device::Service::Device>("pdev");
3. 检查功能路由问题
请参阅下面的功能路由错误部分。
功能路由错误
要在 Fuchsia 中使用某项服务,该服务的 capability 必须为 在运行时正确路由到驱动程序。将功能 子驱动程序,那么父驱动程序需要公开相应功能并提供 子节点。
以下命令有助于诊断功能路由问题:
ffx component doctor <DRIVER_URL>此命令会输出类似于以下内容的输出:
$ 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
如需解决与功能路由相关的问题,请尝试执行以下步骤:
此外,要了解功能在 DFv2 驱动程序中的路由方式, 请查看这些传输示例。
1. 公开该 capability
如果父级驱动程序未正确公开该功能,您可能会看到 如下所示:
[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
如需解决此问题,请检查该功能如何在父级中公开
驱动程序的组件清单 (.cml) 文件,例如:
{
    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. 提供相应功能
要检查子节点中是否存在所提供的服务,请运行
(您也可以使用 ffx component doctor 命令):
ffx driver list-devices -v此命令会输出 例如:
Name     : RTC_-composite-spec
Moniker  : 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: board
  Instances: default acpi
Service: fuchsia.hardware.acpi.Service
  Source: board
  Instances: default acpi
Service: fuchsia.driver.compat.Service
  Source: 00_00_1b
  Instances: sysmem
Service: fuchsia.hardware.sysmem.Service
  Source: 00_00_1b
  Instances: sysmem
此外,如果在子节点中找不到相应优惠,您可能会看到 如下所示的消息:
[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
如需解决此问题,请检查父级驱动程序包含的设置 提供给子节点的优惠,例如:
// 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. 使用功能
如需使用某项功能,驱动程序需要声明它要使用 功能。
如果未正确声明,您可能会看到如下所示的消息 在日志中:
[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.
要解决此问题,请检查在
驱动程序的组件清单 (.cml) 文件,例如:
{
    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' },
    ],
}
错误消息
Fuchsia 驱动程序开发中的常见错误消息:
Failed to load driver <...> driver note not foundRequired service <...> was not available for target componentDriver-Loader: libdriver.so: Not in allowlist__fuchsia_driver_registration__ symbol not availableCould 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
无法加载驱动程序<...>未找到驾驶员备注
将 DFv1 驱动程序迁移到 DFv2 时,您可能会遇到以下错误消息 在日志中:
Failed to load driver <...> driver not found
发生此错误时,请检查驱动程序的组件清单 (.cml) 文件
以确保正确性。请参阅驱动程序无法启动。
所需服务 <...>无法用于目标组件
如果驱动程序未正确公开服务功能,则会出现此错误 并从父驱动程序路由到它。
若要解决此问题,请尝试查看功能路由错误。 工作流。
不过,如果所需的服务是 fuchsia.driver.compat,请遵循
操作说明:
如果驱动程序没有 fuchsia.driver.compat 服务,则会发生此错误
从 DFv2 驱动程序路由到它要路由此服务,DFv2 驱动程序需要
为每个子级设置一个兼容型设备服务器。
如需解决此问题,请从受影响的驱动程序开始逐一检查各个家长驱动程序。
例如,如果节点拓扑显示 A->B->C->D 且 D 是受影响的驱动程序,
然后再经过C、B和A。对于链中的每个父级驱动程序,如果
使用 DFv2 编写,请验证其兼容设备服务器的设置是否正确。
以下是与设置兼容型设备服务器相关的一些常见问题:
- 必须使用正确的子节点名称初始化兼容型设备服务器。
 - 子发布商必须通过优惠添加 兼容型设备服务器
 
驱动程序加载器:libdriver.so:不在许可名单中
如果 libdriver 位于某个 DFv2 驱动程序的依赖项中,而该依赖项
具有传递性。
如需解决此问题,请搜索 //src/devices/lib/driver 并将其从依赖项中移除。
如需查找依赖项,请使用以下命令:
fx gn path <out_directory> //path/to/driver //path/to/libdriver__fuchsia_driver_registration__ 符号不可用
将 DFv1 驱动程序迁移到 DFv2 时,您可能会遇到以下错误消息 在日志中:
[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
当 DFv2 驱动程序不包含 FUCHSIA_DRIVER_EXPORT 宏时,就会出现此错误。
如需解决此问题,请参阅添加驱动程序导出宏。
此外,请确保在 .cc 文件(而不是头文件 (.h) 文件)中定义该宏。
无法加载驱动程序:<...>:无法打开绑定文件(或缺少绑定路径)
将 DFv1 驱动程序迁移到 DFv2 时,您可能会遇到以下错误消息 在日志中:
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'
或
Could not load driver: fuchsia-pkg://fuchsia.com/fake-battery#meta/fake_battery.cm: Missing bind path
当以下字段中的 bind 字段缺失或不正确时,就会出现此错误
DFv2 驱动程序的组件清单 (.cml) 文件,例如:
{
    include: [
        "syslog/client.shard.cml",
    ],
    program: {
        runner: "driver",
        binary: "driver/fake_battery.so",
        bind: <incorrect bind file path>,
    },
}
bind 字段值需要遵循 meta/bind/<bind_output> 格式,其中
bind_output 是 driver_bind_rules 目标中具有相同名称的字段
,例如:
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" ]
}
对于此绑定规则目标示例,组件中的正确 bind 字段
清单文件如下所示:
{
    include: [
        "syslog/client.shard.cml",
    ],
    program: {
        runner: "driver",
        binary: "driver/fake_battery.so",
        bind: "meta/bind/fake-battery-driver.bindbc",
    },
}
不过,如果未在绑定规则目标中明确定义 bind_output,
默认值是附加了 .bindbc 的目标名称,
为 fake_battery_bind.bindbc。
无法启动驱动程序,缺少“二进制文件”参数:ZX_ERR_NOT_FOUND
在编写 DFv2 驱动程序时,您可能会遇到以下错误消息 在日志中:
Failed to start driver, missing 'binary' argument: ZX_ERR_NOT_FOUND
binary 字段值需要遵循 driver/<driver_output>.so 格式,其中
driver_output 是 fuchsia_driver 目标中与
build 文件,例如:
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",
  ]
}
对于此绑定规则目标示例,组件清单文件中正确的 binary 字段如下所示
如下所示:
{
    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",
    },
}
没有名为“destroy”的成员在“fdf_internal::DriverServer<...>”中
如果 DFv2 驱动程序实现了开放式 FIDL 协议(即
open protocol <PROTOCOL_NAME>),则驱动程序需要替换和实现
handle_unknown_method() 函数。
例如,假设驱动程序实现了以下协议:
open protocol VirtualController {
    ...
};
然后,此驱动程序需要包含以下 handle_unknown_method() 函数:
void handle_unknown_method(
    fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::VirtualController> metadata,
    fidl::UnknownMethodCompleter::Sync& completer) override;
其他资源
- 查看驱动程序信息 - 包含操作方法的参考页面
使用 
ffx driver进行调试。