為驅動程式建立新的繫結程式庫

本指南將逐步說明在 Fuchsia SDK 開發環境 (使用 Bazel 建構系統) 中建立新繫結程式庫的相關工作。

在 Fuchsia 驅動程式庫開發中,繫結程式庫可讓以下工作更容易協調:

Fuchsia SDK 包含一組繫結程式庫,可用來撰寫驅動程式繫結規則。然而,有時僅使用現有的繫結程式庫可能不足以為驅動程式建構精確的建構規則。在這種情況下,您可能需要建立新的繫結程式庫,為驅動程式庫及其目標節點定義一組自訂繫結屬性。

本指南中的開發情境

新的繫結程式庫可供使用時,如果兩個群組具有兩項不同的責任,您就可以使用新的繫結程式庫:一個管理父項驅動程式,另一個則在子項驅動程式上運作。

alt_text

圖 1. 顯示兩個驅動程式之間父項與子項關係的節點拓撲。

圖 1 顯示具有兩個驅動程式的節點拓撲:parent-driverchild-driver。現在,假設有一群平台開發人員已為 Fuchsia 系統中內建的 ACPI 裝置編寫驅動程式庫 (parent-driver),以及一組裝置開發人員正在為新的 ACPI 裝置 (目標節點為 bindlib-child) 編寫驅動程式庫 (child-driver)。

在這種情況下,會發生下列事件:

  1. 建立新的繫結程式庫 - 建立新的繫結程式庫,定義新 ACPI 裝置的節點屬性。

  2. 這個新的自訂繫結程式庫會在兩個群組之間共用:

建立新的繫結程式庫

建立新的繫結程式庫,讓開發人員精確識別 Fuchsia 系統中的特定目標裝置。

如要建立新的繫結程式庫,請按照下列步驟操作:

  1. 編寫新的繫結程式庫
  2. 為新的繫結程式庫建立建構檔案

1. 編寫新的繫結程式庫

編寫繫結程式庫,用於定義一組新的自訂節點屬性。

新的繫結程式庫可能如下所示 (請參閱繫結程式庫範例lib 目錄中的 testlibrary.bind):

library examples.gizmo.bind;

// Include properties from other libraries
using fuchsia.acpi;

// Define new properties and values for this library
string ModelName;

enum GizmoType {
  MEM_64K,
  MEM_128K,
  MEM_256K,
};

// Extend values defined in other libraries
extend uint fuchsia.BIND_PCI_VID {
  GIZMOTRONICS = 0x314159,
};

這個新的繫結程式庫名稱定義在 library fuchsia.examples.gizmo.bind; 行的頂端。另請注意,using fuchsia.acpi; 行會建立依附元件至 fuchsia.acpi 繫結程式庫,並包含在 Fuchsia SDK 中。這項設定反映的是真實的開發情境,通常需要使用兩種繫結程式庫:現有程式庫和自訂程式庫。

2. 為新的繫結程式庫建立建構檔案

為新的繫結程式庫建立建構檔案 (即 BUILD.bazel),以便開發人員自動產生程式庫構件。

下列建構目標會在範例繫結程式庫的 BUILD.bazel 檔案中定義名為 fuchsia.example.gizmo.bind 的新 C++ 繫結程式庫:

# This is a bind library that we manually define.
fuchsia_bind_library(
    name = "examples.gizmo.bind",
    srcs = [
        "testlibrary.bind",
    ],
    visibility = ["//visibility:public"],
    deps = [
        "@fuchsia_sdk//bind/fuchsia.acpi",  # An SDK bind library.
    ],
)

# We have to create the C++ library for it manually as well.
fuchsia_bind_cc_library(
    name = "examples.gizmo.bind_cc",
    library = ":examples.gizmo.bind",
    visibility = ["//visibility:public"],
    # Has to have the C++ libraries of all the deps of the bind library.
    deps = [
        "@fuchsia_sdk//bind/fuchsia.acpi:fuchsia.acpi_cc",  # An SDK bind library's C++ lib.
    ],
)

透過建構 fuchsia.example.gizmo.bind library 產生的其中一個程式庫構件是下列 C++ 標頭檔案 (對此來說,該檔案並未包含在範例中):

// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// WARNING: This file is machine generated by bindc.

#ifndef BIND_FUCHSIA_EXAMPLES_GIZMO_BIND_BINDLIB_
#define BIND_FUCHSIA_EXAMPLES_GIZMO_BIND_BINDLIB_

#include <string>

#include <bind/fuchsia/acpi/cpp/bind.h>

namespace bind_fuchsia_examples_gizmo_bind {

static const std::string MODELNAME = "fuchsia.examples.gizmo.bind.ModelName";

static const std::string GIZMOTYPE = "fuchsia.examples.gizmo.bind.GizmoType";
static const std::string GIZMOTYPE_MEM_64K = "fuchsia.examples.gizmo.bind.GizmoType.MEM_64K";
static const std::string GIZMOTYPE_MEM_128K = "fuchsia.examples.gizmo.bind.GizmoType.MEM_128K";
static const std::string GIZMOTYPE_MEM_256K = "fuchsia.examples.gizmo.bind.GizmoType.MEM_256K";

static constexpr uint32_t BIND_PCI_VID_GIZMOTRONICS = 3227993;

}  // namespace bind_fuchsia_examples_gizmo_bind

#endif  // BIND_FUCHSIA_EXAMPLES_GIZMO_BIND_BINDLIB_

開發人員現在可以使用這個 C++ 標頭檔案中的節點屬性進行以下工作:

更新父項驅動程式的子節點

在 Fuchsia 中,部分驅動程式會建立子節點,讓其他驅動程式能夠繫結。建立子節點的驅動程式稱為父項驅動程式。使用新的繫結程式庫時,主要工作是更新父項驅動程式的子項節點,使其從新的繫結程式庫接收節點屬性。

如要更新父項驅動程式的子節點,請按照下列步驟操作:

  1. 在建構檔案中加入新的繫結程式庫
  2. 指派節點屬性給子節點

1. 在建構檔案中加入新的繫結程式庫

更新父項驅動程式庫的建構檔案,加入新繫結程式庫的依附元件。

下方父項驅動程式的 BUILD.bazel 檔案顯示 cc_binary 目標有自訂繫結程式庫 fuchsia.example.gizmo.bind_cc 的依附元件:

fuchsia_cc_driver(
    name = "parent_driver",
    srcs = [
        "gizmo_server.h",
        "parent-driver.cc",
        "parent-driver.h",
    ],
    deps = [
        # This is a C++ lib from our manually created bind library.
        "//src/bind_library/lib:examples.gizmo.bind_cc",
        # This is a C++ lib from our manually created FIDL based bind library.
        "//src/bind_library/lib:examples.gizmo_bindlib_cc",
        "//src/bind_library/lib:examples.gizmo_cc",
        # This is a C++ lib from an SDK FIDL based bind library.
        "@fuchsia_sdk//fidl/fuchsia.device.fs:fuchsia.device.fs_bindlib_cc",
        "@fuchsia_sdk//pkg/driver_component_cpp",
    ],
)

請注意,依附元件的前置字串是 //src/bind_library/lib (而非 @fuchsia_sdk//),表示它來自範例中的本機目錄。

2. 將節點屬性指派給子節點

更新父項驅動程式庫的原始碼,以便將新繫結程式庫中的某些節點屬性向下傳遞至子節點。

使用 parent-driver.cc 中新繫結程式庫的自動產生的 C++ 標頭檔案,此驅動程式庫現在可以讀取新的繫結程式庫的節點屬性:

#include <bind/examples/gizmo/bind/cpp/bind.h>
#include <bind/examples/gizmo/cpp/bind.h>
#include <bind/fuchsia/device/fs/cpp/bind.h>

...

properties[0] =
    fdf::MakeProperty(arena, 1 /* BIND_PROTOCOL */, bind_fuchsia_acpi::BIND_PROTOCOL_DEVICE);
properties[1] = fdf::MakeProperty(arena, bind_fuchsia_acpi::HID, "GOOG");
properties[2] = fdf::MakeProperty(arena, bind_examples_gizmo_bind::MODELNAME, "GIZMO3000");
properties[3] = fdf::MakeProperty(arena, bind_examples_gizmo_bind::GIZMOTYPE,
                                  bind_examples_gizmo_bind::GIZMOTYPE_MEM_64K);

請注意,bind_fuchsia_examples_gizmo_bind 命名空間中的部分字串變數 (請參閱「自動產生的 C++ 標頭」檔案) 會用來初始化子項節點的節點屬性。

更新子項駕駛員的繫結規則

繫結到現有驅動程式庫子節點的驅動程式稱為子驅動程式庫。使用新的繫結程式庫時,主要工作是更新子項驅動程式的繫結規則,以使用新繫結程式庫中的節點屬性。其主要目標是為驅動程式庫編寫更精準的繫結規則,保證能符合 Fusia 系統中的目標節點。

如要更新子駕駛員的繫結規則,請按照下列步驟操作:

  1. 在建構檔案中加入新的繫結程式庫
  2. 使用新節點屬性編寫繫結規則

1. 在建構檔案中加入新的繫結程式庫

更新子項驅動程式庫的建構檔案,加入新繫結程式庫的依附元件

下方子項驅動程式的 BUILD.bazel 檔案顯示 fuchsia_driver_bytecode_bind_rules 目標有自訂繫結程式庫 fuchsia.example.gizmo.bind 的依附元件:

fuchsia_driver_bind_bytecode(
    name = "bind_bytecode",
    output = "child-driver.bindbc",
    rules = "child-driver.bind",
    deps = [
        # This bind library is one we created manually.
        "//src/bind_library/lib:examples.gizmo.bind",
        # This bind library is from a FIDL library that we created manually.
        "//src/bind_library/lib:examples.gizmo_bindlib",
        # This bind library is from an SDK FIDL library.
        "@fuchsia_sdk//fidl/fuchsia.device.fs:fuchsia.device.fs_bindlib",
    ],
)

請注意,依附元件的前置字串是 //src/bind_library/lib (而非 @fuchsia_sdk//),表示它來自範例中的本機目錄。

2. 使用新的節點屬性編寫繫結規則

寫入 (或更新) 子項驅動程式的繫結規則,以便使用新繫結程式庫的節點屬性。

子項驅動程式繫結規則 (child-driver.bind) 顯示,規則中使用的是自訂繫結程式庫 fuchsia.example.gizmo.bindModelNameGizmoType 屬性,可縮小驅動程式庫的目標裝置範圍:

using fuchsia.acpi;
using examples.gizmo.bind;

...

fuchsia.BIND_PROTOCOL == fuchsia.acpi.BIND_PROTOCOL.DEVICE;
fuchsia.acpi.hid == "GOOG";
examples.gizmo.bind.ModelName == "GIZMO3000";
examples.gizmo.bind.GizmoType == examples.gizmo.bind.GizmoType.MEM_64K;

如要進一步瞭解繫結規則,請參閱「編寫驅動程式的繫結規則」。

附錄

原始碼與 SDK 之間產生繫結程式庫程式碼的差異

Bind 程式庫程式碼產生教學課程中的大部分概念和範例皆適用於 Fuchsia SDK 開發環境。

不過,兩者的差異如下:

  • 無法在 SDK 中產生 Rust 目標。
  • C++ 程式庫的目標 cc_library 是 SDK 中的 :{target_name}_cc (而非 :{target_name}_cpp)。
  • 如果 SDK 不包含 C++ 程式庫 fuchsia_bind_cc_library 的目標,則須手動在 BUILD.bazel 中新增目標。