【android bluetooth 协议分析 01】【HCI 层介绍 1】【hci_packets.pdl 介绍】

在 AOSP 的蓝牙协议栈 (Gabeldorsche) 中,hci_packets.pdl 是一个 协议描述语言文件,用于定义 HCI (Host Controller Interface) 层的数据包结构和通信协议。以下是详细解析:


1. 文件作用

  • system/gd/hci/hci_packets.pdl

  • 协议自动化生成 :通过 .pdl 文件定义蓝牙 HCI 命令/事件/数据包的二进制格式

  • 跨语言支持:生成 C++/Java 等语言的协议解析/构建代码

  • 保证一致性:避免手动编写协议代码导致的错误

关键定义示例:


OpCode 枚举定义

pdl 复制代码
enum OpCode : 16 {
	RESET = 0x0C03, // 规范定义的原始操作码
}
  • 作用:定义 HCI 命令的操作码(OpCode)

  • 语法

    • enum 声明枚举类型

    • : 16 表示用 16 位存储(蓝牙规范要求)

    • RESET = 0x0C03

      • 0x0C03 是蓝牙规范定义的 Reset 命令码

      • 高 6 位 0x03 是 OGF(Opcode Group Field)

      • 低 10 位 0x03 是 OCF(Opcode Command Field)

pdl 复制代码
enum OpCodeIndex : 16 {
  RESET = 57, // 将 RESET 命令映射到索引 57
}
  • : 16:索引值用 16 位整数存储(实际索引通常远小于此范围)
  • RESET = 57:表示 RESET 命令在内部数组中的位置为 57

核心作用

  • 二级映射 :将 OpCode(如 0x0C03)转换为更紧凑的 数组索引 (如 57),优化内存和访问效率

  • 快速查找:通过数字索引快速定位命令处理器(替代哈希表或线性搜索)

  • 代码生成:为自动生成的代码提供命令编号与索引的映射关系

和 OpCode 的关系:

pdl 复制代码
enum OpCode : 16 {
  RESET = 0x0C03,  // 规范定义的原始操作码
}

packet Reset : Command (op_code = RESET, op_code_index = RESET) {}
  • 双绑定机制

    1. op_code :协议规范定义的原始值(如 0x0C03

    2. op_code_index :内部优化的数组索引(如 57

  • 编译时关联:代码生成工具会确保两者正确匹配


pdl 复制代码
packet Reset : Command (op_code = RESET) {
}
  • 作用:声明 Reset 命令的数据结构

  • 语法

    • packet 声明一个协议数据包

    • : Command 表示这是 HCI 命令类型

    • (op_code = RESET) 绑定到前面定义的枚举值

    • {} 表示此命令无附加参数

pdl 复制代码
test Reset {
  "\x03\x0c\x00",
}
  • 二进制解释

    • 03 0c:小端格式的 0x0C03(Reset 命令码)

    • 00:无参数填充

pdl 复制代码
packet ResetComplete : CommandComplete (command_op_code = RESET) {
  status : ErrorCode,
}
  • 作用:定义命令完成事件的数据结构

  • 语法

    • : CommandComplete 表示这是命令完成事件

    • (command_op_code = RESET) 关联对应的命令

    • status : ErrorCode

      • 字段名 status

      • 类型 ErrorCode(通常是 8 位错误码枚举)

pdl 复制代码
test ResetComplete {
  "\x0e\x04\x01\x03\x0c\x00",
  "\x0e\x04\x01\x03\x0c\x01", // unknown command
}
  • 二进制解释

    • 0e:事件码(Command Complete)

    • 04:参数总长度

    • 01:允许发送的 HCI 命令数

    • 03 0c:对应的命令码(小端)

    • 00/01:状态码(成功/未知命令)

关键语法规则

语法元素 说明
enum Name : bits 定义枚举类型,指定存储位数
packet Name : Type 定义数据包,继承特定基类(Command/Event等)
field : Type 定义字段,类型可以是基础类型或自定义枚举
test 定义二进制测试用例
(key=value) 属性绑定(如关联命令与操作码)

2. 编译流程

.pdl 文件通过 Packet Framework 工具链处理,具体步骤:

编译阶段

system/gd/Android.bp

makefile 复制代码
genrule {
    name: "BluetoothGeneratedPackets_h",
    tools: [
        "bluetooth_packetgen",
    ],
    cmd: "$(location bluetooth_packetgen) --include=packages/modules/Bluetooth/system/gd --out=$(genDir) $(in)",
    srcs: [
        "hci/hci_packets.pdl",
        "l2cap/l2cap_packets.pdl",
        "security/smp_packets.pdl",
    ],
    out: [
        "hci/hci_packets.h",
        "l2cap/l2cap_packets.h",
        "security/smp_packets.h",
    ],
}
字段 说明
name 规则名称:BluetoothGeneratedPackets_h
tools 使用的工具:bluetooth_packetgen (协议代码生成器)
cmd 实际执行的命令,包含: • 工具路径 $(location) • 输入参数 --include • 输出目录 --out • 输入文件 $(in)
srcs 输入的协议描述文件: • HCI 层 (hci_packets.pdl) • L2CAP 层 (l2cap_packets.pdl) • 安全层 (smp_packets.pdl)
out 生成的头文件输出路径

Build System bluetooth_packetgen hci_packets.pdl l2cap_packets.pdl smp_packets.pdl genDir 调用工具 解析协议描述 解析协议描述 解析协议描述 生成 h/l2cap/smp_packets.h Build System bluetooth_packetgen hci_packets.pdl l2cap_packets.pdl smp_packets.pdl genDir

  1. 输入.pdl 文件定义协议格式(字段、长度、类型等)

  2. 处理bluetooth_packetgen 工具解析描述文件

  3. 输出:生成类型安全的 C++ 头文件

其他模块通过 generated_headers 依赖这些生成的头文件:

makefile 复制代码
cc_library {
    name: "libbluetooth_gd",
    defaults: [
        "libbluetooth_gd_defaults", # 依赖它
    ],
    apex_available: [
        "com.android.bluetooth",
    ],
    min_sdk_version: "31",
}


cc_defaults {
    name: "libbluetooth_gd_defaults",

	generated_headers: [
        "BluetoothGeneratedPackets_h", # 这里
    ],
}

3. 生成代码结构

  • out/soong/.intermediates/packages/modules/Bluetooth/system/gd/BluetoothGeneratedPackets_h/gen/hci/hci_packets.h

生成的代码会包含:

c 复制代码
class ResetBuilder : public CommandBuilder
{
public:
    virtual ~ResetBuilder() = default;
    static std::unique_ptr<ResetBuilder> Create()
    {
        auto builder = std::unique_ptr<ResetBuilder>(new ResetBuilder());
        return builder;
    }

#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)
    static std::unique_ptr<ResetBuilder> FromView(ResetView view) { return ResetBuilder::Create(); }
#endif

protected:
    void SerializeHeader(BitInserter &i) const { CommandBuilder::SerializeHeader(i); }

    void SerializeFooter(BitInserter &i) const { CommandBuilder::SerializeFooter(i); }

public:
    virtual void Serialize(BitInserter &i) const override
    {
        SerializeHeader(i);
        SerializeFooter(i);
    }

protected:
    size_t BitsOfHeader() const { return 0 + CommandBuilder::BitsOfHeader(); }

    size_t BitsOfFooter() const { return 0 + CommandBuilder::BitsOfFooter(); }

public:
    virtual size_t size() const override { return (BitsOfHeader() / 8) + (BitsOfFooter() / 8); }

protected:
    explicit ResetBuilder() : CommandBuilder(OpCode::RESET /* op_code_ */) {}
};
相关推荐
千里马学框架21 小时前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台21 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui