如要編寫繫結規則,請參閱繫結規則教學課程。
在 Fuchsia 中,驅動程式庫架構會維護系統中的驅動程式和裝置樹狀結構。在本 樹狀結構,裝置是指存取 OS 可用的部分硬體。駕駛人包括 繫結至裝置。舉例來說,USB 驅動程式庫可能會繫結至 PCI 裝置 (其父項),然後發布 乙太網路裝置 (其子項)。以便決定驅動程式庫能夠繫結的裝置,每個驅動程式庫都會 都有繫結規則,而每部裝置都有一組屬性。繫結規則定義了一項條件 指定其對應的屬性。
繫結規則及其參照的條件是由特定網域語言所定義。繫結 編譯器會使用這種語言,並產生繫結規則的位元碼。語言共有兩種 包括規則和程式庫程式庫可用來共用屬性定義 相同的驅動程式和繫結規則編譯器也會從繫結的程式庫產生 FIDL 檔案, 驅動程式可能會參照程式碼中的裝置屬性
關於遷移階段,請注意,這個階段不支援定義裝置
屬性鍵 (參閱下方說明)。而是使用舊版驅動程式庫繫結系統的按鍵
(lib/ddk/binding.h) 尚可擴充。
這些金鑰會以硬式編碼的方式寫入繫結編譯器,並可在 fuchsia
命名空間下使用。
例如 PCI 供應商 ID 金鑰為 fuchsia.BIND_PCI_VID
。經過硬式編碼的鍵最終會
會從這個命名空間中移除,並在繫結程式庫中定義所有節點屬性鍵。
編譯器
編譯器會採用程式庫來源清單和一個規則來源。例如:
fx bindc compile \
--include src/devices/bind/fuchsia.usb/fuchsia.usb.bind \
--output tools/bindc/examples/gizmo.h \
tools/bindc/examples/gizmo.bind
目前,它會產生 C 標頭檔案,可由驅動程式庫包含。標頭檔案會定義 巨集:
ZIRCON_DRIVER(Driver, Ops, VendorName, Version);
Driver
是驅動程式庫的名稱。Ops
是zx_driver_ops
,這是驅動程式庫作業掛鉤VendorName
是代表驅動程式庫供應商名稱的字串。Version
是代表驅動程式庫版本的字串。
詳情請參閱 驅動程式庫開發說明文件。
繫結規則
繫結規則定義了呼叫驅動程式庫 bind()
掛鉤的條件。繫結中每個陳述式
規則是指裝置屬性必須符合的條件,
驅動程式庫進行繫結。如果繫結規則執行完畢,且所有條件都符合,則裝置
協調器會呼叫驅動程式庫 bind()
掛鉤。
繫結規則應視為宣告式規則的 驅動程式庫應繫結。因此,條件運算式的執行順序與 以及最終評估結果建議將繫結規則視為布林公式。
陳述式分為四種類型:
- 條件陳述式是形式的等式 (或不相等) 運算式
<key> == <value>
(或<key> != <value>
)。 - 接受陳述式是指特定鍵允許的值清單。
- 「If statement」提供簡單的分支版本。
- True 和 false 陳述式可用來明確評估繫結規則。
範例
您可以在 //tools/bindc/examples/gizmo.bind 中找到這個繫結規則範例。
using fuchsia.usb;
// The device must be a USB device.
fuchsia.BIND_PROTOCOL == fuchsia.usb.BIND_PROTOCOL.INTERFACE;
if fuchsia.BIND_USB_VID == fuchsia.usb.BIND_USB_VID.INTEL {
// If the device's vendor is Intel, the device class must be audio.
fuchsia.BIND_USB_CLASS == fuchsia.usb.BIND_USB_CLASS.AUDIO;
} else if fuchsia.BIND_USB_VID == fuchsia.usb.BIND_USB_VID.REALTEK {
// If the device's vendor is Realtek, the device class must be one of the following values:
accept fuchsia.BIND_USB_CLASS {
fuchsia.usb.BIND_USB_CLASS.COMM,
fuchsia.usb.BIND_USB_CLASS.VIDEO,
}
} else {
// If the vendor is neither Intel or Realtek, do not bind.
false;
}
語言限制
為提升可讀性, 繫結規則是驅動程式庫所繫結條件的簡單示意圖。
不允許空白區塊。 空一個區塊是否代表驅動程式庫會繫結或取消,這點不明確。 作者應使用明確的
true
或false
陳述式。如果陳述式必須有其他區塊,且為終端機, 這項限制會明確地做出執行作業分支,藉此提高可讀性。因為沒有 陳述式可能會遵循
if
陳述式,因此可以透過繫結規則輕鬆追蹤路徑。真陽性和偽陳述必須是相關範圍內的唯一陳述。 繫結規則並非強制性的計畫,且評估順序並不重要。攪拌 具有其他條件的布林陳述式 (尤其是
true
) 可能導致下列情況 不是清楚的。
文法
rule = using-list , ( statement )+ ;
using-list = ( using , ";" )* ;
using = "using" , compound-identifier , ( "as" , IDENTIFIER ) ;
statement = condition , ";" | accept | if-statement | true | false ;
condition = compound-identifier , condition-op , value ;
condition-op = "==" | "!=" ;
accept = "accept" , compound-identifier , "{" ( value , "," )+ "}" ;
if-statement = "if" , condition , "{" , ( statement )+ , "}" ,
( "else if" , "{" , ( statement )+ , "}" )* ,
"else" , "{" , ( statement )+ , "}" ;
true = "true" , ";" ;
false = "false" , ";" ;
compound-identifier = IDENTIFIER ( "." , IDENTIFIER )* ;
value = compound-identifier | STRING-LITERAL | NUMERIC-LITERAL | "true" | "false" ;
ID 與規則運算式 [a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?
相符,但不得與任何 ID 相符
字詞。關鍵字清單如下:
accept
as
else
false
if
true
using
字串常值與規則運算式 ”[^”]*”
相符,且數值常值與規則運算式 [0-9]+
相符,或
0x[0-9A-F]+
。
繫結編譯器會忽略任何以 //
開頭的行 (以空白字元表示),
以 /*
和 */
分隔的線條。
複合繫結
除了將驅動程式與裝置繫結外,Fchsia 的驅動程式也能使用繫結規則。 從節點建立複合裝置繫結規則會依循相同語言 視為非複合繫結,但會分離包含 名稱和陳述式集合
繫結規則中只能有一個主要節點。複合驅動程式庫會 啟動與主要節點相同的驅動程式代管程序。
如需複合繫結規則檔案的範例,請前往 //tools/bindc/examples/composite-gizmo.bind.
composite gizmo_pci;
using fuchsia.pci;
using fuchsia.platform;
using fuchsia.tee;
primary node "pci" {
fuchsia.BIND_PROTOCOL == fuchsia.pci.BIND_PROTOCOL.DEVICE;
}
node "tee" {
if fuchsia.BIND_PROTOCOL == fuchsia.tee.BIND_PROTOCOL.DEVICE {
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;
}
}
複合繫結的文法如下:
composite-bind-rules = [composite-device], using-list , ( node )+ ;
composite-device = “composite” , IDENTIFIER;
node = [ "primary" ], "node" , STRING-LITERAL , "{" , ( statement )+ , "}"
建立目標
如要在 Fuchsia 建構系統中宣告繫結規則,請使用下列建構目標:
driver_bind_rules("bind") {
rules = <bind rules filename>
bind_output = <generated bind binary filename>
deps = [ <list of bind library targets> ]
}
詳情請參閱 //build/繫結/bind.gni。
測試
繫結編譯器支援適用於繫結規則的資料導向單元測試架構,可讓您 獨立測試您的繫結規則。繫結規則的測試案例包含 裝置規格和預期結果,即繫結或中止。測試案例會傳遞到繫結狀態 而編譯器會以 JSON 規格檔案的形式,執行每個測試案例。 執行偵錯工具
JSON 規格必須是測試案例物件清單,其中每個物件都包含以下內容:
name
測試案例名稱的字串。expected
預期的結果。必須為“match”
或“abort”
。device
字串鍵/值組合清單,用於說明裝置屬性。這是 與偵錯工具的裝置規格類似 (請參閱 這個例子)。
如果測試是針對複合裝置,則裝置中的每個節點都可以 測試案例物件清單。單元測試的 JSON 規格會是 列出節點物件每個節點物件都包含:
node
節點名稱的字串。必須與繫結規則中的節點相符 測試。tests
測試案例物件清單。
範例
這是測試案例範例,完整的測試位於 //tools/bindc/examples/test.json
。這個
保護殼會檢查繫結規則是否符合所列屬性的裝置,例如 Intel USB 音訊
裝置。
[
{
"name": "Intel",
"expected": "match",
"device": {
"fuchsia.BIND_PROTOCOL": "fuchsia.usb.BIND_PROTOCOL.INTERFACE",
"fuchsia.BIND_USB_VID": "fuchsia.usb.BIND_USB_VID.INTEL",
"fuchsia.BIND_USB_CLASS": "fuchsia.usb.BIND_USB_CLASS.AUDIO"
}
}
]
以下示例呈現包含測試案例的複合繫結節點。完整的測試位於
`//tools/bindc/examples/composite-tests.json
。每個測試案例都會檢查節點是否
繫結規則會比對具備所列屬性的裝置。
[
{
"node": "pci",
"tests": [
{
"name": "Match",
"expected": "match",
"device": {
"fuchsia.BIND_PROTOCOL": "fuchsia.pci.BIND_PROTOCOL.DEVICE"
}
},
{
"name": "Abort pci",
"expected": "abort",
"device": {
"fuchsia.BIND_PROTOCOL": "fuchsia.tee.BIND_PROTOCOL.DEVICE"
}
}
]
}
]
建構
定義測試建構目標,如下所示:
bind_test("example_bind_test") {
rules = <bind rules filename>
tests = <test specification filename>
deps = [ <list of bind library targets> ]
}
或者,您也可以在現有的 bind_rules
中新增 tests
引數來產生
測試目標這個名稱會是原始目標的名稱加上 _test
。例如,下列
就會產生 example_bind_test
driver_bind_rules("example_bind") {
rules = "meta/gizmo.bind"
bind_output = “gizmo.bindbc”
tests = "meta/tests.json"
deps = [ "//src/devices/bind/fuchsia.usb" ]
}
執行
如果您已為測試定義建構目標,則可使用 fx 測試照常執行測試。
fx test example_bind_test
或者,您也可以直接執行繫結工具。例如:
fx bindc test \
tools/bindc/examples/gizmo.bind \
--test-spec tools/bindc/examples/tests.json \
--include src/devices/bind/fuchsia.usb/fuchsia.usb.bind
繫結程式庫
繫結程式庫會定義驅動程式可指派給其子項的一組屬性。另外, 繫結規則可能是指繫結程式庫
名稱間距
繫結程式庫一開始會定義其命名空間:
library <vendor>.<library>;
每個命名空間均須以廠商開頭,且每個廠商都必須確保彼此之間不會有衝突
各自的命名空間然而,此語言可讓一個廠商
另一個例子。Google 會將 fuchsia
用於公開程式庫。
程式庫引入的任何值均為命名空間。舉例來說,下列程式庫會定義
新的 PCI 裝置 ID GIZMO_VER_1
。
library gizmotronics.gizmo;
using fuchsia.pci as pci;
extend uint pci.device_id {
GIZMO_VER_1 = 0x4242,
};
如要參照這個值,驅動程式庫作者應使用完整名稱,如下所示。
using fuchsia.pci as pci;
using gizmotronics.gizmo;
pci.device_id == gizmotronics.gizmo.device_id.GIZMO_VER_1
鍵和值
裝置屬性定義類似於其他語言中的變數宣告。
<type> <name>;
Or:
<type> <name> {
<value>,
<value>,
…
};
繫結程式庫也可以擴充其他程式庫的屬性。
extend <type> <name> {
<value>,
…
};
每個鍵都有一個類型,而對應該鍵的所有值都必須屬於該類型。語言
支援原始類型:uint
、string
或 bool
之一。和列舉 (enum
)。時間
定義索引鍵時,您應該偏好使用列舉,但值會由外部提供
例如硬體
定義原始值時,請使用 <identifier> = <literal>
形式和列舉
只要提供 ID 即可使用相同的值定義多個原始值是有效的
常值。
文法
library = library-header , using-list , declaration-list ;
library-header = "library" , compound-identifier , ";" ;
using-list = ( using , ";" )* ;
using = "using" , compound-identifier , ( "as" , IDENTIFIER ) ;
compound-identifier = IDENTIFIER ( "." , IDENTIFIER )* ;
declaration-list = ( declaration , ";" )* ;
declaration = primitive-declaration | enum-declaration ;
primitive-declaration = ( "extend" ) , type , compound-identifier ,
( "{" primitive-value-list "}" ) ;
type = "uint" | "string" | "bool";
primitive-value-list = ( IDENTIFIER , "=" , literal , "," )* ;
enum-declaration = ( "extend" ) , "enum" , compound-identifier ,
( "{" , enum-value-list , "}" ) ;
enum-value-list = ( IDENTIFIER , "," )* ;
literal = STRING-LITERAL | NUMERIC-LITERAL | "true" | "false" ;
ID 與規則運算式 [a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?
相符,但不得與任何 ID 相符
字詞。關鍵字清單如下:
as
bool
enum
extend
library
string
uint
using
字串常值與規則運算式 ”[^”]*”
相符,且數值常值與規則運算式 [0-9]+
相符,或
0x[0-9A-F]+
。
繫結編譯器會忽略任何以 //
開頭的行 (以空白字元表示),
以 /*
和 */
分隔的線條。
建立目標
如要在 Fuchsia 建構系統中宣告繫結程式庫,請使用下列建構目標:
bind_library(<library name>) {
source = <bind library filename>
public_deps = [ <list of bind library targets> ]
}
詳情請參閱 //build/繫結/bind.gni。