在 DFv2 驅動程式中連結及提供 Banjo 通訊協定

本指南會逐步說明在 DFv2 驅動程式庫中提供 Banjo 通訊協定的工作 並透過 DFv1 子項驅動程式庫程式連線至 Banjo 伺服器

請在 FIDL 程式庫中定義主要用於 DFv1 驅動程式的 Banjo 通訊協定 含有 @transport("Banjo")@banjo_layout("ddk-protocol") 註解 行,例如:

/// The protocol provides access to functions of the driver.
@transport("Banjo")
@banjo_layout("ddk-protocol")
closed protocol Misc {
    /// Returns a unique identifier for this device.
    strict GetHardwareId() -> (struct {
        status zx.Status;
        response uint32;
    });

    /// Returns the current device firmware version
    strict GetFirmwareVersion() -> (struct {
        status zx.Status;
        major uint32;
        minor uint32;
    });
};

(資料來源:gizmo.test.fidl)

如要讓 DFv2 驅動程式庫使用 Banjo 通訊協定,請參閱下列工作:

透過 DFv2 驅動程式提供 Banjo 通訊協定

本節逐步說明在 DFv2 驅動程式中實作 Banjo 通訊協定 並向子項驅動程式提供通訊協定這份逐步操作說明是根據 的 Banjo Transport 範例,這個範例會導入 gizmo.test FIDL 程式庫中的 Misc Banjo 通訊協定。

步驟如下:

  1. 設定 Banjo 通訊協定
  2. 實作 Banjo 通訊協定
  3. 提供 Banjo 協定

1. 設定 Banjo 通訊協定

如要在 DFv2 驅動程式中設定 Misc Banjo 通訊協定,請按照下列步驟操作:

  1. BUILD.gn 檔案中,將 Banjo 程式庫新增為 fuchsia_driver 目標,例如:

    fuchsia_driver("parent_driver") {
      output_name = "banjo_transport_parent"
      sources = [ "parent-driver.cc" ]
      deps = [
        "//examples/drivers/bind_library:gizmo.example_cpp",
        "//examples/drivers/transport/banjo:fuchsia.examples.gizmo_banjo_cpp",
         ...
      ]
    }
    
  2. 在驅動程式庫的 C++ 標頭檔案中,加入 Banjo 程式庫的 C++ 標頭, 範例:

    #include <fuchsia/examples/gizmo/cpp/banjo.h>
    ...
    
    namespace banjo_transport {
    ...
    

    (資料來源:parent-driver.h)

  3. 如要繼承 Banjo 通訊協定繫結,請使用以下程式碼更新驅動程式庫類別: 格式如下:

    ddk::<PROTOCOL_NAME>Protocol<<YOUR_DRIVER_CLASS>>
    

    PROTOCOL_NAME 替換為 Banjo 通訊協定的名稱,然後 YOUR_DRIVER_CLASS 是駕駛人的類別,這兩者都是駝峰式大小寫 例如:

    class ParentBanjoTransportDriver : public fdf::DriverBase,
        public ddk::MiscProtocol<ParentBanjoTransportDriver>  {
        ...
    };
    

    (資料來源:parent-driver.h)

2. 實作 Banjo 通訊協定

在驅動程式庫類別中,定義與實作 Banjo 中的每個函式 因此效能相當卓越

例如,以下範例顯示名為 ProtocolName 的 Banjo 通訊協定:

@transport("Banjo")
@banjo_layout("ddk-protocol")
closed protocol ProtocolName {
   /// Returns a unique identifier for this device.
   strict FunctionName() -> (struct {
       status zx.Status;
       response_1 response_1_type;
       response_2 response_2_type;
   });
};

針對這個 ProtocolName Banjo 通訊協定, FunctionName 函式如下所示:

zx_status_t ProtocolNameFunctionName(response_1_type* response_1, response_2_type* response_2);

您可以透過應用程式找出現有 Banjo 通訊協定的 C++ 繫結 使用下列 Fuchsia 來源結帳路徑:

<OUT_DIRECTORY>/fidling/gen/<PATH_TO_THE_FIDL_LIBRARY>/banjo

舉例來說,如果 out 目錄是 out/default 且 FIDL 程式庫位於 examples/drivers/transport 目錄 則 C++ 繫結位於以下目錄中:

out/default/fidling/gen/examples/drivers/transport/banjo

請參閱 Banjo Transport 範例中的實作方式:

  • Misc 通訊協定包含下列函式:

    /// Returns a unique identifier for this device.
    strict GetHardwareId() -> (struct {
     status zx.Status;
     response uint32;
    });
    
    /// Returns the current device firmware version
    strict GetFirmwareVersion() -> (struct {
     status zx.Status;
     major uint32;
     minor uint32;
    });
    
  • ParentBanjoTransportDriver 類別會將這些函式定義為 如下:

    class ParentBanjoTransportDriver : public fdf::DriverBase,
                                      public ddk::MiscProtocol<ParentBanjoTransportDriver> {
    public:
    ...
    
     // MiscProtocol implementation.
     zx_status_t MiscGetHardwareId(uint32_t* out_response);
     zx_status_t MiscGetFirmwareVersion(uint32_t* out_major, uint32_t* out_minor);
    ...
    };
    

    (資料來源:parent-driver.h)

  • 函式的實作方式如下:

    zx_status_t ParentBanjoTransportDriver::MiscGetHardwareId(uint32_t* out_response) {
     *out_response = 0x1234ABCD;
     return ZX_OK;
    }
    
    zx_status_t ParentBanjoTransportDriver::MiscGetFirmwareVersion(uint32_t* out_major,
                                                                  uint32_t* out_minor) {
     *out_major = 0x0;
     *out_minor = 0x1;
     return ZX_OK;
    }
    

    (資料來源:parent-driver.cc)

3. 提供 Banjo 通訊協定

在 DFv2 驅動程式中實作 Banjo 通訊協定後,您需要 使用相容裝置伺服器向 DFv1 子節點提供通訊協定 套用了 Banjo 設定

若要這樣做,請在 在 DFv2 驅動程式中設定 Compat 裝置伺服器 指南:

  1. 設定 Compat 裝置伺服器
  2. 為子系 DFv1 驅動程式提供 Banjo 服務

從 DFv2 驅動程式連線至 Banjo 伺服器

本節使用 Banjo 傳輸範例。 ,逐步說明如何將 DFv2 子項驅動程式庫連線至父項 是 Banjo 通訊協定的驅動程式庫

步驟如下:

  1. 將兒童驅動程式庫與家長驅動程式連線
  2. 使用 Banjo 通訊協定

1. 將兒童驅動程式庫接上家長驅動程式庫

要能將兒童驅動程式庫與父母連線,以便使用 Banjo 通訊協定,子項必須與父項位於同一驅動程式代管程序 兩個驅動程式都必須使用 Compat banjo_client 程式庫

如要將子項驅動程式庫與家長驅動程式庫連接,請按照下列步驟操作:

  1. 在子項驅動程式庫程式的元件資訊清單 (.cml) 中設定 colocate 欄位變更為 true,例如:

    {
        include: [ 'syslog/client.shard.cml' ],
        program: {
            runner: 'driver',
            binary: 'driver/banjo_transport_child.so',
            bind: 'meta/bind/child-driver.bindbc',
    
            // Run in the same driver host as the parent driver
            colocate: 'true',
        },
        use: [
            { service: 'fuchsia.driver.compat.Service' },
        ],
    }
    

    (資料來源:child-driver.cml)

  2. 在子項驅動程式庫 BUILD.gn 檔案中,將 Banjo 程式庫新增為 某個依附元件是位於 fuchsia_driver 目標中的依附元件,例如:

    fuchsia_driver("child_driver") {
      output_name = "banjo_transport_child"
      sources = [ "child-driver.cc" ]
      deps = [
        "//examples/drivers/transport/banjo:fuchsia.examples.gizmo_banjo_cpp",
        "//sdk/lib/driver/component/cpp:cpp",
        "//src/devices/lib/driver:driver_runtime",
      ]
    }
    

    (資料來源:BUILD.gn)

  3. 在子項驅動程式庫的 C++ 標頭檔案中,加入 Banjo 程式庫的 C++ 標頭,例如:

    #include <fuchsia/examples/gizmo/cpp/banjo.h>
    ...
    
    namespace banjo_transport {
    ...
    

    (資料來源:child-driver.h)

  4. 在子項驅動程式的 BUILD.gn 檔案中,新增相容性 banjo_client 將程式庫做為 fuchsia_driver 目標中的依附元件,例如:

    fuchsia_driver("child_driver") {
      output_name = "banjo_transport_child"
      sources = [ "child-driver.cc" ]
      deps = [
        "//examples/drivers/transport/banjo:fuchsia.examples.gizmo_banjo_cpp",
        "//sdk/lib/driver/compat/cpp",
        "//sdk/lib/driver/component/cpp:cpp",
        "//src/devices/lib/driver:driver_runtime",
      ]
    }
    

    (資料來源:BUILD.gn)

  5. 在子項驅動程式庫的 C++ 來源檔案中,加入 Compat banjo_client 程式庫的 C++ 標頭,例如:

    #include "examples/drivers/transport/banjo/v2/child-driver.h"
    
    #include <lib/driver/compat/cpp/compat.h>
    #include <lib/driver/component/cpp/driver_export.h>
    #include <lib/driver/logging/cpp/structured_logger.h>
    
    namespace banjo_transport {
    
    zx::result<> ChildBanjoTransportDriver::Start() {
    ...
    

    (資料來源:child-driver.cc)

  6. 在子項驅動程式庫程式的 C++ 來源檔案中,使用 compat::ConnectBanjo() 函式,例如:

    zx::result<Client> ConnectBanjo(const std::shared_ptr<fdf::Namespace>& incoming,
                                    std::string_view parent_name = "default") {
    

    Banjo Transport 範例中, 驅動程式庫會執行下列作業來連線至 Misc 通訊協定:

    zx::result<ddk::MiscProtocolClient> client =
          compat::ConnectBanjo<ddk::MiscProtocolClient>(incoming());
    
    if (client.is_error()) {
        FDF_SLOG(ERROR, "Failed to connect client", KV("status",
             client.status_string()));
        return client.take_error();
    }
    

    (資料來源:child-driver.cc)

2. 使用 Banjo 通訊協定

在子項驅動程式庫中,使用通訊協定用戶端叫用 Banjo 函式。

例如,以下範例顯示一個名為 ProtocolName:

@transport("Banjo")
@banjo_layout("ddk-protocol")
closed protocol ProtocolName {
   /// Returns a unique identifier for this device.
   strict FunctionName() -> (struct {
       status zx.Status;
       response_1 response_1_type;
       response_2 response_2_type;
   });
};

針對這個 ProtocolName Banjo 通訊協定, FunctionName 函式如下所示:

zx_status_t ProtocolNameFunctionName(response_1_type* response_1, response_2_type* response_2);

Banjo Transport 範例中, GetHardwareId() 函式的定義如下:

/// Returns a unique identifier for this device.
strict GetHardwareId() -> (struct {
 status zx.Status;
 response uint32;
});

(資料來源:gizmo.test.fidl)

使用儲存在 client_ 物件中的 Banjo 用戶端 而 hardware_id_ 變數定義為 是 uint32_t,您可以呼叫 GetHardwareId() 函式 包括:

zx_status_t status = client_.GetHardwareId(&hardware_id_);
if (status != ZX_OK) {
 return status;
}

(資料來源:child-driver.cc)