排解 DFv2 驅動程式庫開發常見問題

這份疑難排解指南提供工作流程偵錯,方便您解決 開發 Fuchsia 驅動程式庫時常見的錯誤。

為工作流程偵錯

針對常見問題偵錯工作流程:

駕駛無法啟動

駕駛未「啟動」應用程式無法載入、繫結或以 。

如要偵錯這個問題,請按照下列步驟操作:

  1. 確認驅動程式庫已成功載入
  2. 確認驅動程式庫是否嘗試繫結
  3. 確認驅動程式庫已成功啟動

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

如果清單中沒有該驅動程式庫,就必須載入該驅動程式。

請考慮以下幾個原因:

  • 建構套件不包含驅動程式。
  • 驅動程式庫的元件資訊清單 (.cml) 檔案有問題。

與元件資訊清單檔案相關的常見錯誤訊息:

2. 確認驅動程式庫嘗試繫結

如果驅動程式庫嘗試繫結至節點,您會在 記錄檔:

Binding driver fuchsia-boot:///#meta/focaltech.cm

如果您沒有看到這則記錄訊息,可能是因為驅動程式庫的 繫結規則和節點屬性如要針對不相符的問題進行偵錯,請檢查驅動程式庫 繫結規則並與節點屬性進行比較

如要查看所有節點屬性,請執行下列指令:

ffx driver list-devices -v

這個指令會輸出類似以下的輸出內容:

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

不過,如果驅動程式庫是複合驅動程式,則您必須驗證 複合節點規格與 複合驅動程式庫繫結規則和父項節點屬性 節點。

如要查看複合節點規格,請執行下列指令:

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 錯誤,請按照下列步驟操作:

  1. 驗證傳出目錄
  2. 查看執行個體名稱
  3. 檢查是否有能力轉送問題

此外,如要查看 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 中使用服務,該服務的功能必須符合下列條件: 可在執行階段正確轉送給驅動程式庫如要將能力 父項驅動程式庫,則需由父母驅動程式庫揭露 然後把它寄給孩子

下列指令有助於診斷能力轉送問題:

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

如要解決能力轉送相關問題,請嘗試下列步驟:

  1. 公開功能
  2. 提供功能
  3. 使用功能

此外,我們也將一同瞭解 DFv2 驅動程式如何轉送功能 請參考這些交通範例

1. 公開能力

如果父項驅動程式庫未正確公開這項能力,您可能會看到 記錄訊息,如下所示:

[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  : 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

此外,如果子節點中沒有該優惠,您也可能會看到 記錄檔中會顯示類似下方的訊息:

[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 驅動程式庫時常見的錯誤訊息:

無法載入驅動程式庫 <...>找不到驅動程式庫附註

將 DFv1 驅動程式庫遷移至 DFv2 時,您可能會遇到以下錯誤訊息 記錄:

Failed to load driver <...> driver not found

發生這個錯誤時,請檢查驅動程式庫的元件資訊清單 (.cml) 檔案 確保正確性請參閱「驅動程式無法啟動」。

必要服務 <...>不適用於目標元件

如果驅動程式庫未正確公開服務能力,就會發生這個錯誤 並透過父母驅動程式庫轉送

如要修正這個問題,請嘗試按照功能轉送錯誤 工作流程

不過,如果所需的服務是 fuchsia.driver.compat,請遵循 操作說明如下

如果驅動程式庫沒有 fuchsia.driver.compat 服務,就會發生錯誤 並以 DFv2 驅動程式庫如要轉送這項服務,DFv2 驅動程式庫必須 為每位孩子設定相容裝置伺服器

如要修正這個問題,請從受影響的驅動程式庫逐一執行所有家長驅動程式庫。 舉例來說,如果節點拓撲顯示 A->B->C->DD 是受影響的驅動程式庫, 然後經過 CBA。針對鏈結中的每個父項驅動程式庫 (如有) 以檢查其 Compat 裝置伺服器是否已正確設定。

以下是與設定相容裝置伺服器相關的常見問題:

  • 必須使用正確的子節點名稱初始化 Compat 裝置伺服器。
  • 購買子發布商必須透過 Compat 裝置伺服器

Driver-Loader:libdriver.so:不在許可清單中

如果 libdriver 位於 DFv2 驅動程式庫的其中一個依附元件中,就會發生這項錯誤, 可以是遞移性質

如要修正這個問題,請搜尋並從依附元件中移除 //src/devices/lib/driver

如要找出依附元件,請使用下列指令:

fx gn route <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, 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

如果 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 目標中同名的欄位 建構檔案,例如:

fuchsia_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;

其他資源