本指南將逐步介紹透過 DFv2 驅動程式庫提供 Banjo 通訊協定的工作,並從 DFv1 子項驅動程式庫程式連線至 Banjo 伺服器。
Banjo 通訊協定主要用於 DFv1 驅動程式,而在 FIDL 程式庫中會加上 @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 通訊協定,以設定與 DFv1 子項驅動程式之間的通訊。
從 DFv1 驅動程式連線至 Banjo 伺服器:從 DFv1 子驅動程式庫程式連線至 DFv2 父項驅動程式庫程式的 Banjo 伺服器,並開始使用 Banjo 通訊協定。
提供 DFv2 驅動程式庫提供的 Banjo 通訊協定
本節逐步說明如何在 DFv2 驅動程式庫中實作 Banjo 通訊協定,並將通訊協定提供給 DFv1 子項驅動程式庫程式。本逐步操作說明是以 Banjo Transport 範例為基礎,該範例實作 gizmo.test
FIDL 程式庫中的 Misc
Banjo 通訊協定。
步驟如下:
1. 設定 Banjo 通訊協定
如要在 DFv2 驅動程式中設定 Misc
Banjo 通訊協定,請按照下列步驟操作:
在
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", ... ] }
在驅動程式庫的 C++ 標頭檔案中,加入 Banjo 程式庫的 C++ 標頭,例如:
#include <fuchsia/examples/gizmo/cpp/banjo.h> ... namespace banjo_transport { ...
(資料來源:
parent-driver.h
)如要繼承 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
函式的 C++ 繫結如下所示:
zx_status_t ProtocolNameFunctionName(response_1_type* response_1, response_2_type* response_2);
您也可以在 Fuchsia 來源結帳的下列路徑中找到現有 Banjo 通訊協定的 C++ 繫結:
<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 通訊協定後,您需要使用以 Banjo 設定的相容裝置伺服器,將通訊協定提供給 DFv1 子節點。
如要這麼做,請完成「在 DFv2 驅動程式中設定 compat 裝置伺服器」指南中的工作:
從 DFv1 驅動程式庫連線至 Banjo 伺服器
本節使用 Banjo 傳輸範例,逐步說明如何將 DFv1 子項驅動程式庫連線至提供 Banjo 通訊協定的 DFv2 父項驅動程式庫。
步驟如下:
1. 將子項驅動程式庫連線至父項驅動程式庫
為了能夠使用 Banjo 通訊協定,將子項驅動程式庫連結至父項驅動程式庫,子項必須與父項位於相同的驅動程式代管程序相同,且兩個驅動程式都必須使用 Compat banjo_client
程式庫。
如要將子項驅動程式庫連線至父項驅動程式庫,請按照下列步驟操作:
在子驅動程式庫程式的元件資訊清單 (
.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
)在驅動程式庫的
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
)在驅動程式庫的 C++ 標頭檔案中,加入 Banjo 程式庫的 C++ 標頭,例如:
#include <fuchsia/examples/gizmo/cpp/banjo.h> ... namespace banjo_transport { ...
(資料來源:
child-driver.h
)在驅動程式庫的
BUILD.gn
檔案中,將 Compatbanjo_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
)在驅動程式庫的 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
)在驅動程式庫的 C++ 來源檔案中,使用
compat::ConnectBanjo()
函式設定 Banjo 用戶端,例如: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
的 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
函式的 C++ 繫結如下所示:
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
)
將 Banjo 用戶端儲存在 client_
物件中,並將 hardware_id_
變數定義為 uint32_t
後,您就可以透過下列方式呼叫 GetHardwareId()
函式:
zx_status_t status = client_.GetHardwareId(&hardware_id_);
if (status != ZX_OK) {
return status;
}
(資料來源:child-driver.cc
)