本指南說明如何編寫驅動程式庫繫結規則,使其繫結至所需裝置。其中會說明如何找出節點屬性,然後使用繫結語言撰寫節點屬性。
本指南假設您已熟悉驅動程式繫結。
節點屬性目前的狀態
目前,繫結程式庫和 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 驅動程式庫清單裝置
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"
驅動程式庫原始碼中的驅動程式屬性
新增子裝置時,駕駛人可以提供繫結規則相符的屬性。因此,您可以找到透過驅動程式庫原始碼繫結的屬性。
在 DFv1 中,原始碼中的節點屬性是以「屬性」和「字串屬性」表示,屬性則包含整數型鍵和值。但是,字串屬性包含字串型鍵和值,可以是整數、布林值、字串或列舉。
以下程式碼片段可讓驅動程式庫新增具有 BIND_PROTOCOL
屬性和「ENABLE_TEST」字串屬性的裝置。
device_add_args_t args = {};
args.version = DEVICE_ADD_ARGS_VERSION;
args.name = "parent";
args.ops = &dev_ops;
zx_device_prop_t props[] = {
{BIND_PROTOCOL, 0, ZX_PROTOCOL_PCI},
}
args.props = props;
args.prop_count = std::size(props);
zx_device_str_prop_t str_props[] = {
zx_device_str_prop_t{.key = "ENABLE_TEST",
.property_value = str_prop_bool_val(true)}
};
args.str_props = str_props;
args.str_prop_count = std::size(str_props);
device_add(parent, &args, &dev);
在 DFv2 中,節點屬性會以 fuchsia.driver.framework FIDL 程式庫中的 NodeProperty
結構表示:
auto properties = fidl::VectorView<fdf::wire::NodeProperty>(arena, 2);
properties[0] = fdf::MakeProperty(arena, BIND_PROTOCOL, ZX_PROTOCOL_PCI);
properties[1] = fdf::MakeProperty(arena, "ENABLED_TEST", true);
auto args = fdf::wire::NodeAddArgs::Builder(arena)
.name(arena, "sample-child")
.properties(properties)
.Build();
在繫結的程式庫中定義屬性
隨著驅動程式從舊版繫結系統遷移至新系統時,我們會在新系統的繫結程式庫中重新定義舊屬性。這些繫結程式庫位於 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 繫結 Library,這個程式庫不僅定義通訊協定 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
6 Properties
[ 1/ 6] : Key fuchsia.BIND_ACPI_ID Value 0x000034
[ 2/ 6] : Key fuchsia.BIND_PCI_TOPO Value 0x0000aa
[ 3/ 6] : Key fuchsia.BIND_ACPI_BUS_TYPE Value 0x000001
[ 4/ 6] : Key "fuchsia.hardware.acpi.Device" Value true
[ 5/ 6] : Key fuchsia.BIND_PROTOCOL Value 0x00001e
[ 6/ 6] : Key "fuchsia.platform.DRIVER_FRAMEWORK_VERSION" Value 0x000002
接著,您就可以編寫以下內容:
using fuchsia.acpi;
using fuchsia.pci;
primary node "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";
}
node "acpi" {
fuchsia.driver.framework.dfv2 == true;
fuchsia.BIND_ACPI_ID == 0x000034;
fuchsia.BIND_PCI_TOPO == 0x0000aa;
fuchsia.BIND_ACPI_BUS_TYPE == 0x000001;
}
選用節點
選用節點是指不需要存在於裝置群組中,用來與複合驅動程式庫比對的節點。這項功能僅適用於使用裝置群組。選用節點時,系統不會在純舊的複合元件中比對選用節點,其中拓撲的節點會與複合式驅動程式庫進行比對。
在繫結規則中,在 node
關鍵字前方放置 optional
,會將該節點標示為選用項目。一般而言,所有選用節點都應在一般額外節點之後寫入。
選用節點可用來編寫較通用的複合驅動程式庫規則。例如 HID 按鈕驅動程式支援 9 種不同的按鈕類型 (調高音量、攝影機靜音等),但並非所有硬體裝置都會有這些按鈕。如選用節點,則可將繫結規則寫入跨平台通用,以便板型驅動程式使用 HID 按鈕驅動程式庫支援的任意按鈕組合建立複合元件。
繫結規則範例
分支版本繫結規則
繫結語言支援透過 if 陳述式執行分支,但具有一些限制。
如果陳述式必須包含其他區塊,且為終端機,這項限制會透過明確的執行作業分支版本來提高可讀性。由於沒有任何陳述式遵守 if 陳述式,因此您可以輕鬆透過繫結規則追蹤路徑。
if fuchsia.hardware.tee.Service == fuchsia.hardware.tee.Service.ZirconTransport {
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 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;