本指南将逐步介绍如何使用
i2c_temperature示例驱动程序编写绑定规则。
如需让驱动程序绑定到节点(表示硬件
或虚拟设备),驱动程序的绑定规则必须与
节点的节点属性匹配。在本指南中,我们将为
i2c_temperature 示例驱动程序编写绑定规则,使其与 i2c-child 节点的节点属性匹配。
i2c_controller 驱动程序会创建一个名为 i2c-child 的子节点,用于测试 i2c_temperature 示例驱动程序。我们可以使用此
i2c_controller 驱动程序来识别 i2c-child 节点的节点属性,并为 i2c_temperature 编写匹配的绑定规则。
具体步骤如下:
1. 识别节点属性
您可以通过以下任一方式识别目标节点的节点属性:
使用 ffx driver list-devices 命令
如需输出 Fuchsia 系统中每个节点的属性,请运行以下命令:
ffx driver list-devices -v此命令会以以下格式输出节点的属性:
Name : i2c-child
Moniker : root.sys.platform.pt.acpi.FWCF.i2c-child
Driver : None
2 Properties
[ 1/ 2] : Key "fuchsia.Service" Value String("fuchsia.hardware.i2c.Service")
[ 2/ 2] : Key fuchsia.BIND_I2C_ADDRESS Value 0x0000ff
上面的输出显示,i2c-child 节点具有以下节点属性:
- 属性键
fuchsia.Service,字符串值为"fuchsia.hardware.i2c.Service"。 - 属性键
fuchsia.BIND_I2C_ADDRESS,整数值为0xFF。
在驱动程序源代码中查找节点属性
添加子节点时,驱动程序可以向节点提供节点属性。 查看将目标节点创建为子节点的驱动程序的源代码有助于您识别要包含在绑定规则中的节点属性。
i2c_controller 驱动程序会创建一个名为 i2c-child 的子节点,i2c_temperature 示例驱动程序会绑定到该子节点。检查 i2c_controller 驱动程序的源代码,以识别传递给此子节点的节点属性:
// Set the properties of the node for drivers to target.
auto properties = fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>(arena, 2);
properties[0] = fdf::MakeProperty(arena, bind_fuchsia_hardware_i2c::SERVICE,
bind_fuchsia_hardware_i2c::SERVICE_ZIRCONTRANSPORT);
properties[1] = fdf::MakeProperty(arena, 0x0A02 /* BIND_I2C_ADDRESS */, 0xff);
此代码显示,i2c-child 节点是使用以下绑定属性创建的:
- 属性键
fuchsia.Service,字符串值为"fuchsia.hardware.i2c.Service"。 - 属性键
fuchsia.BIND_I2C_ADDRESS,整数值为0xFF。
2. 编写绑定规则
了解要匹配的节点属性后,您可以使用绑定语言为驱动程序编写绑定规则。
在上一部分中,我们已确定 i2c-child 节点具有以下节点属性:
- 属性键
fuchsia.Service,字符串值为"fuchsia.hardware.i2c.Service"。 - 属性键
fuchsia.BIND_I2C_ADDRESS,整数值为0xFF。
为了匹配这些属性,i2c_temperature 驱动程序声明了以下绑定规则:
using fuchsia.hardware.i2c;
fuchsia.hardware.i2c.Service == fuchsia.hardware.i2c.Service.ZirconTransport;
fuchsia.BIND_I2C_ADDRESS == 0xFF;
以 BIND_ 开头的基于整数的节点属性键(在
binding_priv.h 在 Fuchsia 源代码树中定义)是旧属性
键,目前在绑定编译器中硬编码。请参阅 binding_priv.h 中 BIND_I2C_ADDRESS 的以下定义:
#define BIND_I2C_ADDRESS 0x0A02
在绑定规则中使用这些键时,它们会以 fuchsia. 为前缀。
3. 为绑定规则添加 Bazel build 目标
为驱动程序编写绑定规则后,您需要更新 BUILD.bazel 文件,以使用 fuchsia_driver_bytecode_bind_rules() 模板为绑定规则字节码添加 build 目标:
fuchsia_driver_bind_bytecode(
name = "bind_bytecode",
output = "i2c_temperature.bindbc",
rules = "i2c_temperature.bind",
deps = [
"@fuchsia_sdk//fidl/fuchsia.hardware.i2c:fuchsia.hardware.i2c_bindlib",
],
)
对于绑定规则中使用的每个库,请将该库作为依赖项添加到 build 目标。例如,i2c_temperature 示例驱动程序的绑定规则使用 fuchsia.hardware.i2c 库,因此 build 目标会将绑定库作为 build 依赖项。
如需确定绑定规则中使用了哪些绑定库,您可以检查驱动程序源代码。在 i2c-child 节点的节点属性中,第一个属性键 fuchsia.hardware.i2c.Service 来自 FIDL 协议生成的绑定库:
// Set the properties of the node for drivers to target.
auto properties = fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>(arena, 2);
properties[0] = fdf::MakeProperty(arena, bind_fuchsia_hardware_i2c::SERVICE,
bind_fuchsia_hardware_i2c::SERVICE_ZIRCONTRANSPORT);
properties[1] = fdf::MakeProperty(arena, 0x0A02 /* BIND_I2C_ADDRESS */, 0xff);
前缀 fuchsia_hardware_i2c 表示此节点属性的键和值是在以下头文件中定义的:
#include <bind/fuchsia/hardware/i2c/cpp/bind.h>
这些绑定库在驱动程序的 build 规则中将具有相应的依赖项。请参阅 i2c_controller 二进制目标中的以下 fuchsia.hardware.i2c 依赖项:
fuchsia_cc_driver(
name = "i2c_controller",
srcs = [
"i2c_controller.cc",
"i2c_controller.h",
"i2c_server.cc",
"i2c_server.h",
],
deps = [
"//src/i2c_temperature/lib",
"@fuchsia_sdk//fidl/fuchsia.hardware.i2c:fuchsia.hardware.i2c_bindlib_cc",
"@fuchsia_sdk//fidl/fuchsia.hardware.i2c:fuchsia.hardware.i2c_llcpp_cc",
"@fuchsia_sdk//pkg/driver_component_cpp",
],
)
附录
NodeProperty 和 NodeAddArgs 结构体
节点属性由 fuchsia.driver.framework FIDL 库中的 NodeProperty 结构体表示:
/// Definition of a property for a node. A property is commonly used to match a
/// node to a driver for driver binding.
type NodeProperty = table {
/// Key for the property.
1: key NodePropertyKey;
/// Value for the property.
2: value NodePropertyValue;
};
然后,使用 NodeAddArgs 结构体将节点属性传递给子节点:
/// Arguments for adding a node.
type NodeAddArgs = table {
/// Name of the node.
1: name string:MAX_NODE_NAME_LENGTH;
/// Capabilities to offer to the driver that is bound to this node.
2: offers vector<fuchsia.component.decl.Offer>:MAX_OFFER_COUNT;
/// Functions to provide to the driver that is bound to this node.
3: symbols vector<NodeSymbol>:MAX_SYMBOL_COUNT;
/// Properties of the node.
4: properties vector<NodeProperty>:MAX_PROPERTY_COUNT;
};