本指南說明如何編寫驅動程式庫的繫結規則,讓驅動程式繫結至所需裝置。本文說明如何找出節點屬性,然後使用繫結語言為該屬性編寫繫結規則。
本指南假設您熟悉司機繫結。
節點屬性的目前狀態
目前,節點屬性是在繫結程式庫和 C++ 標頭檔案中定義。過去,節點屬性是以整數為基礎的鍵/值組合,以 C++ 結構體的形式說明。所有屬性都是在 C++ 標頭檔案中定義,繫結規則則是驅動程式庫原始碼的一部分。
不過,繫結系統最近經過翻新,因此繫結規則會使用繫結語言在個別檔案中定義,且節點屬性可支援具有布林值、字串、整數或列舉值的字串型索引鍵。
我們正在進行遷移作業,將所有驅動程式從舊的繫結系統移至新系統。C++ 標頭中的節點屬性正在繫結程式庫中重新定義。舉例來說,所有裝置通訊協定 ID 繫結值都硬式編碼在 protodefs.h 中。現在,每個裝置通訊協定都在各自的繫結程式庫中定義,其中包含通訊協定 ID 的定義,以及與通訊協定相關聯的其他節點屬性。繫結程式庫都位於 src/devices/bind。
在遷移完成前,必須同時支援新舊繫結系統。
節點屬性的未來狀態
繫結遷移作業完成後,我們就能停止支援舊的整數型節點屬性,並移除 C++ 定義,例如 protodefs.h 和 binding_priv.h。所有屬性都會在繫結程式庫中定義,且索引鍵會完全以字串為基礎。
您可以更新現有資源,以便使用新系統的功能。舉例來說,BIND_COMPOSITE 屬性是僅針對複合裝置設定的旗標。不過,由於舊系統僅支援整數值,因此屬性值會以整數表示,而非布林值。移除舊的繫結系統後,屬性值可以變更為布林值。
您也可以變更 VID 的表示方式。我們可以改用 VID 名稱,不必為 VID 指派不重複的整數。舉例來說,Intel VID 目前以整數值 0x8 表示:
library fuchsia.intel.platform;
extend uint fuchsia.BIND_PLATFORM_DEV_VID {
INTEL = 0x8,
};
有了新的繫結系統,VID 可能會以字串值或列舉表示。
查詢節點屬性
使用 ffx 驅動程式庫 list-devices
ffx driver list-devices -v 指令會列印樹狀結構中每個裝置的屬性,格式如下:
Name : _TZ_
Moniker : root.sys.platform.pt.acpi._TZ_
Driver : None
5 Properties
[ 1/ 5] : Key fuchsia.BIND_PROTOCOL Value 0x1F
[ 2/ 5] : Key fuchsia.BIND_PCI_VID Value 0x1AF4
[ 3/ 5] : Key fuchsia.BIND_PCI_DID Value 0x1052
[ 4/ 5] : Key fuchsia.COMPOSITE_BIND Value 1
[ 5/ 5] : Key "fuchsia.acpi.HID" Value "GFSH0005"
驅動程式庫原始碼中的驅動程式屬性
新增子節點時,驅動程式可以提供繫結規則相符的屬性。因此,您可以透過驅動程式庫原始碼找到要繫結的屬性。
節點屬性以 fuchsia.driver.framework FIDL 程式庫中的 NodeProperty2 結構表示,內含以字串為基礎的鍵和值,這些值可以是整數、布林值、字串或列舉:
std::vector<fuchsia_driver_framework::NodeProperty2> properties = {
fdf::MakeProperty2(bind_fuchsia::PROTOCOL, bind_fuchsia_pci::BIND_PROTOCOL_DEVICE),
fdf::MakeProperty2("ENABLED_TEST", true),
};
zx::result result = AddChild("sample-child", properties, {});
在繫結程式庫中定義屬性
當我們將驅動程式從舊的繫結系統遷移到新系統時,會在新的系統上重新定義繫結程式庫中的舊屬性。這些繫結程式庫位於 src/devices/bind 目錄。
任何新屬性都應在繫結程式庫中定義。
舊繫結系統的屬性
大部分舊節點屬性鍵和值都定義在 binding_priv.h 和 protodefs.h 中。
binding_priv.h 包含硬式編碼屬性鍵。每個屬性鍵都會指派一個不重複的整數值。在新繫結系統中,這些鍵會以 fuchsia.BIND_ 前置字元重新定義。舉例來說,BIND_PROTOCOL 會變成 fuchsia.BIND_PROTOCOL,BIND_COMPOSITE 則會變成 fuchsia.BIND_COMPOSITE。
protodefs.h 含有裝置通訊協定的硬式編碼 ID 值。
裝置通訊協定繫結程式庫
protodefs.h 中的每個裝置通訊協定都應有專屬繫結程式庫,其中包含通訊協定 ID 和相關屬性。例如 fuchsia.i2c 繫結程式庫,不僅定義通訊協定 ID 值,也定義其他 i2c 相關屬性:
library fuchsia.i2c;
extend uint fuchsia.BIND_PROTOCOL {
DEVICE = 24,
IMPL = 25,
};
extend uint fuchsia.BIND_I2C_CLASS {
HID = 0x01,
};
extend uint fuchsia.BIND_I2C_ADDRESS {
BACKLIGHT = 0x2C,
ETH = 0x18,
FOCALTECH_TOUCH = 0x38,
AMBIENTLIGHT = 0x39,
};
通訊協定 ID 值與 protodefs.h 中定義的值相符:
DDK_PROTOCOL_DEF(I2C, 24, "i2c", 0)
DDK_PROTOCOL_DEF(I2C_IMPL , 25, "i2c-impl", 0)
IMPL 值代表實作及提供 i2c 通訊協定的驅動程式庫。DEVICE 代表使用 IMPL 通訊協定並提供 DEVICE 通訊協定的核心驅動程式。
編寫繫結規則
本節說明如何針對目前的驅動程式庫繫結狀態編寫繫結規則。如要繫結規則,只須繫結至上述屬性集,您需要撰寫:
using fuchsia.acpi;
using fuchsia.pci;
fuchsia.BIND_PROTOCOL == fuchsia.pci.BIND_PROTOCOL.DEVICE;
fuchsia.BIND_PCI_VID == fuchsia.pci.BIND_PCI_VID.VIRTIO;
fuchsia.BIND_PCI_DID == fuchsia.pci.BIND_PCI_DID.VIRTIO_DEV_TYPE_INPUT;
fuchsia.BIND_COMPOSITE == 1;
fuchsia.acpi.HID == "GFSH0005";
屬性鍵
整數鍵名稱定義於 binding_priv.h,並以「fuchsia」為前置字元。舉例來說,dm dump 中的鍵 0x03 會判定為 fuchsia.BIND_COMPOSITE,因為 binding_priv.h 包含下列內容:
#define BIND_FLAGS 0x0000 // value of the flags register
#define BIND_PROTOCOL 0x0001 // primary protocol of the device
#define BIND_AUTOBIND 0x0002 // if this is an automated bind/load
#define BIND_COMPOSITE 0x003 // Whether this is a composite device
屬性值
由於屬性與 PCI 相關聯,因此相符的值位於 fuchsia.pci.bind 程式庫中。系統會比對 0x001af4 和 fuchsia.BIND_PCI_VID 中的值,找出 fuchsia.pci.BIND_PCI_VID.VIRTIO。
extend uint fuchsia.BIND_PCI_VID {
TEST = 0x0eff,
AMD = 0x1002,
REALTEK = 0x10ec,
NVIDIA = 0x10de,
GOOGLE = 0x1ae0,
VIRTIO = 0x1af4,
BROADCOM = 0x14e4,
ATHEROS = 0x168c,
INTEL = 0x8086,
};
如果繫結程式庫缺少值,您需要在新的或現有的繫結程式庫中新增缺少的定義。或者,您也可以直接為值編寫繫結規則:
fuchsia.BIND_PCI_VID == 0x1af4;
不過,建議您在繫結程式庫中定義值。
複合繫結規則
複合繫結規則也採用相同程序。如要為節點編寫繫結規則,可以列印節點屬性,並為其編寫繫結規則。
假設您想編寫複合繫結規則,其中包含繫結至上述範例的節點,以及繫結至下列項目的另一個節點:
Name : I2C2
Moniker : root.sys.platform.pt.acpi.I2C2
Driver : None
5 Properties
[ 1/ 5] : Key fuchsia.BIND_ACPI_ID Value 0x000034
[ 2/ 5] : Key fuchsia.BIND_PCI_TOPO Value 0x0000aa
[ 3/ 5] : Key fuchsia.BIND_ACPI_BUS_TYPE Value 0x000001
[ 4/ 5] : Key "fuchsia.hardware.acpi.Device" Value true
[ 5/ 5] : Key fuchsia.BIND_PROTOCOL Value 0x00001e
接著,您可以編寫以下內容:
using fuchsia.acpi;
using fuchsia.pci;
primary parent "pci_sample" {
fuchsia.BIND_PROTOCOL == fuchsia.pci.BIND_PROTOCOL.DEVICE;
fuchsia.BIND_PCI_VID == fuchsia.pci.BIND_PCI_VID.VIRTIO;
fuchsia.BIND_PCI_DID == fuchsia.pci.BIND_PCI_DID.VIRTIO_DEV_TYPE_INPUT;
fuchsia.BIND_COMPOSITE == 1;
fuchsia.acpi.HID == "GFSH0005";
}
parent "acpi" {
fuchsia.driver.framework.dfv2 == true;
fuchsia.BIND_ACPI_ID == 0x000034;
fuchsia.BIND_PCI_TOPO == 0x0000aa;
fuchsia.BIND_ACPI_BUS_TYPE == 0x000001;
}
選用節點
選用節點是指裝置群組中不一定要存在的節點,以便與複合驅動程式庫比對。只有在使用裝置群組時才支援這項功能,在拓撲中的節點與複合式驅動程式庫相符時,選用節點不會在舊版複合式中相符。
在繫結規則中,將 optional 放在 parent 關鍵字前面,會將節點標示為選用。按照慣例,所有選用節點都應寫在一般額外節點之後。
選用節點用於編寫更通用的複合驅動程式庫規則。舉例來說,HID 按鈕驅動程式支援 9 種不同的按鈕類型 (調高音量、相機靜音等),但並非所有硬體裝置都會有這些按鈕。有了選用節點,繫結規則可以寫成與平台無關,因此主機板驅動程式可以建立複合裝置,其中包含 HID 按鈕驅動程式庫支援的任意按鈕組合。
繫結規則範例
分支繫結規則
繫結語言支援透過 if 陳述式進行分支,但有一些限制。
If 陳述式必須有 else 區塊,且為終端。這項限制可明確指出執行分支,提高可讀性。由於 if 陳述式後面不能有任何陳述式,因此可以輕鬆追蹤繫結規則的路徑。
if fuchsia.Service == "fuchsia.hardware.tee.Service" {
fuchsia.BIND_PLATFORM_DEV_VID == fuchsia.platform.BIND_PLATFORM_DEV_VID.GENERIC;
} else {
fuchsia.BIND_PLATFORM_DEV_VID == fuchsia.platform.BIND_PLATFORM_DEV_VID.QEMU;
}
只要符合限制,即可使用巢狀 if 陳述式。例如:
if fuchsia.driver.framework.dfv2 == true {
if fuchsia.acpi.hid == "PNP0303" {
true;
} else {
fuchsia.acpi.first_cid == "PNP0303";
}
} else {
fuchsia.BIND_PROTOCOL == fuchsia.acpi.BIND_PROTOCOL.DEVICE;
}
排除多個屬性值
如要拒絕鍵的多個屬性值,可以將不等式條件陳述式串連在一起。舉例來說,如要拒絕多個 fuchsia.BIND_PCI_DID 值,可以執行下列操作:
fuchsia.BIND_PCI_DID != 0x191b;
fuchsia.BIND_PCI_DID != 0x1912;
fuchsia.BIND_PCI_DID != 0x191d;
fuchsia.BIND_PCI_DID != 0x1902;
fuchsia.BIND_PCI_DID != 0x1916;
fuchsia.BIND_PCI_DID != 0x191e;