【android bluetooth 协议分析 02】【bluetooth hal 层详解 6】【bt_vendor_opcode_t 介绍】

bt_vendor_opcode_t 介绍

在 AOSP 的 Bluetooth Vendor 接口中,bt_vendor_opcode_t 定义了一组供上层调用的操作指令。这些操作在蓝牙初始化、使用和关闭过程中由协议栈(如 Bluedroid)驱动调用,按照一定的顺序执行。

这些枚举项代表 Vendor Interface API 的操作码,协议栈通过调用 vendor_call() 接口并传入这些 opcodes 来控制蓝牙芯片的底层行为。其设计目的在于:

  • 平台差异适配(如不同 SoC 的上电、串口打开方式)
  • 硬件加速支持(如 A2DP offload)
  • 功耗优化(如 LPM 控制)
  • 音频子系统协同(如 SCO、音频状态)

1. 详解介绍

  • hidl_hci/1.0/default/bt_vendor_lib.h
c 复制代码
/** Vendor specific operations OPCODE */
typedef enum {
  /*  [operation]
   *      Power on or off the BT Controller.
   *  [input param]
   *      A pointer to int type with content of bt_vendor_power_state_t.
   *      Typecasting conversion: (int *) param.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_POWER_CTRL,

  /*  [operation]
   *      Perform any vendor specific initialization or configuration
   *      on the BT Controller. This is called before stack initialization.
   *  [input param]
   *      None.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      Must call fwcfg_cb to notify the stack of the completion of vendor
   *      specific initialization once it has been done.
   */
  BT_VND_OP_FW_CFG,

  /*  [operation]
   *      Perform any vendor specific SCO/PCM configuration on the BT
   * Controller.
   *      This is called after stack initialization.
   *  [input param]
   *      None.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      Must call scocfg_cb to notify the stack of the completion of vendor
   *      specific SCO configuration once it has been done.
   */
  BT_VND_OP_SCO_CFG,

  /*  [operation]
   *      Open UART port on where the BT Controller is attached.
   *      This is called before stack initialization.
   *  [input param]
   *      A pointer to int array type for open file descriptors.
   *      The mapping of HCI channel to fd slot in the int array is given in
   *      bt_vendor_hci_channels_t.
   *      And, it requires the vendor lib to fill up the content before
   * returning
   *      the call.
   *      Typecasting conversion: (int (*)[]) param.
   *  [return]
   *      Numbers of opened file descriptors.
   *      Valid number:
   *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
   *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
   *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
   *  [callback]
   *      None.
   */
  BT_VND_OP_USERIAL_OPEN,

  /*  [operation]
   *      Close the previously opened UART port.
   *  [input param]
   *      None.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_USERIAL_CLOSE,

  /*  [operation]
   *      Get the LPM idle timeout in milliseconds.
   *      The stack uses this information to launch a timer delay before it
   *      attempts to de-assert LPM WAKE signal once downstream HCI packet
   *      has been delivered.
   *  [input param]
   *      A pointer to uint32_t type which is passed in by the stack. And, it
   *      requires the vendor lib to fill up the content before returning
   *      the call.
   *      Typecasting conversion: (uint32_t *) param.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_GET_LPM_IDLE_TIMEOUT,

  /*  [operation]
   *      Enable or disable LPM mode on BT Controller.
   *  [input param]
   *      A pointer to uint8_t type with content of bt_vendor_lpm_mode_t.
   *      Typecasting conversion: (uint8_t *) param.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      Must call lpm_cb to notify the stack of the completion of LPM
   *      disable/enable process once it has been done.
   */
  BT_VND_OP_LPM_SET_MODE,

  /*  [operation]
   *      Assert or Deassert LPM WAKE on BT Controller.
   *  [input param]
   *      A pointer to uint8_t type with content of bt_vendor_lpm_wake_state_t.
   *      Typecasting conversion: (uint8_t *) param.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_LPM_WAKE_SET_STATE,

  /*  [operation]
   *      Perform any vendor specific commands related to audio state changes.
   *  [input param]
   *      a pointer to bt_vendor_op_audio_state_t indicating what audio state is
   *      set.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_SET_AUDIO_STATE,

  /*  [operation]
   *      The epilog call to the vendor module so that it can perform any
   *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
   *      before the caller calls for cleanup().
   *  [input param]
   *      None.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      Must call epilog_cb to notify the stack of the completion of vendor
   *      specific epilog process once it has been done.
   */
  BT_VND_OP_EPILOG,

  /*  [operation]
   *      Call to the vendor module so that it can perform all vendor-specific
   *      operations to start offloading a2dp media encode & tx.
   *  [input param]
   *      pointer to bt_vendor_op_a2dp_offload_start_t containing elements
   *      required for VND FW to setup a2dp offload.
   *  [return]
   *      0  - default, dont care.
   *  [callback]
   *      Must call a2dp_offload_start_cb to notify the stack of the
   *      completion of vendor specific setup process once it has been done.
   */
  BT_VND_OP_A2DP_OFFLOAD_START,

  /*  [operation]
   *      Call to the vendor module so that it can perform all vendor-specific
   *      operations to suspend offloading a2dp media encode & tx.
   *  [input param]
   *      pointer to bt_vendor_op_a2dp_offload_t containing elements
   *      required for VND FW to setup a2dp offload.
   *  [return]
   *      0  - default, dont care.
   *  [callback]
   *      Must call a2dp_offload_cb to notify the stack of the
   *      completion of vendor specific setup process once it has been done.
   */
  BT_VND_OP_A2DP_OFFLOAD_STOP,

} bt_vendor_opcode_t;
枚举项 作用说明 触发时机 典型应用场合
BT_VND_OP_POWER_CTRL 控制蓝牙芯片上电/断电 蓝牙开启或关闭前后 控制 BT SoC 电源,如初始化前上电,退出前下电
BT_VND_OP_FW_CFG 执行厂商特有的固件初始化配置 蓝牙协议栈初始化前 加载 firmware patch、设置特有寄存器等,完成后调用 fwcfg_cb 通知上层
BT_VND_OP_SCO_CFG 执行厂商特定的 SCO/PCM 音频配置 协议栈初始化之后(有 SCO 功能时) 设置 HCI SCO 路径,配置 PCM 接口参数,完成后需调用 scocfg_cb
BT_VND_OP_USERIAL_OPEN 打开串口或类似物理连接接口,用于 HCI 通信 初始化前 为主控和 BT 控制器之间建立 HCI 通道(如 UART),返回 fd 列表供上层使用
BT_VND_OP_USERIAL_CLOSE 关闭串口或物理连接接口 清理蓝牙前 关闭 UART、SPI、USB 接口文件描述符
BT_VND_OP_GET_LPM_IDLE_TIMEOUT 获取低功耗空闲超时(单位 ms) 启用 LPM 功能后,发送数据后启动 idle 计时器 控制下行数据发送后 LPM WAKE deassert 的延迟时间,避免频繁切换
BT_VND_OP_LPM_SET_MODE 设置是否启用低功耗模式(LPM) 蓝牙初始化后,根据策略动态设置 进入低功耗模式(例如未连接时)、退出低功耗(如开始通信时),需调用 lpm_cb
BT_VND_OP_LPM_WAKE_SET_STATE 设置 WAKE 状态:assert 或 deassert LPM 状态切换时,通常由协议栈驱动 控制 LPM 的 WAKE GPIO,保持通信或释放资源
BT_VND_OP_SET_AUDIO_STATE 通知音频状态变化以执行特定命令 音频连接或断开时 比如 HFP 通话开始/结束,通知底层做相关设置
BT_VND_OP_EPILOG 蓝牙关闭前的收尾工作 cleanup() 调用前 发出 HCI_RESET 等命令,释放资源,完成后调用 epilog_cb
BT_VND_OP_A2DP_OFFLOAD_START 启动 A2DP 硬件 offload(编码和传输) 开始播放 A2DP 音乐时 将音频流交给底层硬件加速处理,完成后调用 a2dp_offload_start_cb
BT_VND_OP_A2DP_OFFLOAD_STOP 停止 A2DP offload 暂停或停止音乐播放时 通知底层停止 offload 模块,完成后调用 a2dp_offload_cb

2. 如何触发调用

例如:

c 复制代码
  ALOGI("Turn On BT power");
  powerstate = BT_VND_PWR_ON;
  ret = lib_interface_->op(BT_VND_OP_POWER_CTRL, &powerstate);
c 复制代码
/*
 * Bluetooth Host/Controller VENDOR Interface
 */
typedef struct {
  /** Set to sizeof(bt_vndor_interface_t) */
  size_t size;

  /*
   * Functions need to be implemented in Vendor libray (libbt-vendor.so).
   */

  /**
   * Caller will open the interface and pass in the callback routines
   * to the implemenation of this interface.
   */
  int (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char* local_bdaddr);

  /**  Vendor specific operations */
  int (*op)(bt_vendor_opcode_t opcode, void* param);

  /** Closes the interface */
  void (*cleanup)(void);
} bt_vendor_interface_t;

2. 案例赏析

1. 一般蓝牙操作流程

下面是一个典型的蓝牙开启、使用、关闭的完整流程,配合 Vendor 操作指令说明。


1. 蓝牙初始化阶段(Bluetooth Turn ON)

顺序 操作 opcode 描述
1 打开串口 BT_VND_OP_USERIAL_OPEN 打开与 BT 芯片通信的物理接口(如 UART)
2 芯片上电 BT_VND_OP_POWER_CTRL 通知 vendor 上电;若芯片已供电则可能为 no-op
3 固件配置 BT_VND_OP_FW_CFG 执行固件加载或寄存器配置,完成后需调用 fwcfg_cb()
4 低功耗模式设置 BT_VND_OP_LPM_SET_MODE 启用或禁用 LPM(低功耗)模式,完成后调用 lpm_cb()
5 获取 LPM 超时 BT_VND_OP_GET_LPM_IDLE_TIMEOUT 获取 LPM 模式下的空闲超时时间

⚠️ 有 SCO 功能设备还会执行:

  • BT_VND_OP_SCO_CFG:设置 PCM 参数,完成后调用 scocfg_cb()

2. 音频使用阶段(如通话、播放音乐)

情况 操作 opcode 描述
开始通话(HFP) BT_VND_OP_SET_AUDIO_STATE 通知底层开始 SCO 语音传输
播放音乐(A2DP) BT_VND_OP_A2DP_OFFLOAD_START 启动音频硬件 offload
暂停音乐 BT_VND_OP_A2DP_OFFLOAD_STOP 停止 A2DP 硬件 offload
通信中 BT_VND_OP_LPM_WAKE_SET_STATE 发送数据前 deassert WAKE;空闲后再 assert

3. 蓝牙关闭阶段(Bluetooth Turn OFF)

顺序 操作 opcode 描述
1 执行 epilog 清理流程 BT_VND_OP_EPILOG 可能发送 HCI_RESET 或其他定制命令,完成后需调用 epilog_cb()
2 关闭串口 BT_VND_OP_USERIAL_CLOSE 关闭 UART、SPI 或 USB 接口
3 芯片断电 BT_VND_OP_POWER_CTRL 通知 Vendor 关闭 BT 电源(如果支持)

c 复制代码
Bluetooth ON 流程:
 ┌───────────────────────────────┐
 │ USERIAL_OPEN                  │
 │ POWER_CTRL (ON)               │
 │ FW_CFG → fwcfg_cb             │
 │ SCO_CFG → scocfg_cb (可选)    │
 │ LPM_SET_MODE → lpm_cb         │
 │ GET_LPM_IDLE_TIMEOUT          │
 └───────────────────────────────┘

使用过程:
 ┌───────────────────────────────┐
 │ SET_AUDIO_STATE               │
 │ A2DP_OFFLOAD_START / STOP     │
 │ LPM_WAKE_SET_STATE            │
 └───────────────────────────────┘

Bluetooth OFF 流程:
 ┌───────────────────────────────┐
 │ EPILOG → epilog_cb            │
 │ USERIAL_CLOSE                 │
 │ POWER_CTRL (OFF)              │
 └───────────────────────────────┘

3. 补充说明

  • 所有 *_cb() 结尾的操作都需要在异步完成后由 vendor 层手动调用回调通知协议栈。
  • vendor lib 是一个中间层,负责将这些操作转换为实际硬件控制动作(如 ioctl、GPIO 控制、UART 操作等)。
  • 上层 bt_vendor_interface_t->op() 接口在 vendor.c 中实现,内部 switch-case 匹配这些 opcode。
c 复制代码
typedef struct {
  /** set to sizeof(bt_vendor_callbacks_t) */
  size_t size;

  /*
   * Callback and callout functions have implemented in HCI libray
   * (libbt-hci.so).
   */

  /* notifies caller result of firmware configuration request */
  cfg_result_cb fwcfg_cb;

  /* notifies caller result of sco configuration request */
  cfg_result_cb scocfg_cb;

  /* notifies caller result of lpm enable/disable */
  cfg_result_cb lpm_cb;

  /* notifies the result of codec setting */
  cfg_result_cb audio_state_cb;

  /* buffer allocation request */
  malloc_cb alloc;

  /* buffer deallocation request */
  mdealloc_cb dealloc;

  /* hci command packet transmit request */
  cmd_xmit_cb xmit_cb;

  /* notifies caller completion of epilog process */
  cfg_result_cb epilog_cb;

  /* notifies status of a2dp offload cmd's */
  cfg_a2dp_cb a2dp_offload_cb;
} bt_vendor_callbacks_t;
相关推荐
tangweiguo0305198744 分钟前
Android全局网络监控最佳实践(Kotlin实现)
android·kotlin
移动开发者1号1 小时前
Android后台服务保活方案对比分析
android·kotlin
移动开发者1号1 小时前
ContentProvider URI匹配机制详解
android·kotlin
Digitally5 小时前
在 Android 上备份短信:保护您的对话
android
诸神黄昏EX9 小时前
Android Native 之 adbd进程分析
android
Estar.Lee11 小时前
腾讯云开发者社区文章内容提取免费API接口教程
android·云计算·腾讯云·api·免费api·api大全
匆匆整棹还13 小时前
idea配置android--以idea2023为例
android·java·intellij-idea
zhifanxu14 小时前
android协程异步编程常用方法
android·开发语言·kotlin
蓉妹妹14 小时前
React项目在ios和安卓端要做一个渐变色背景,用css不支持,可使用react-native-linear-gradient
android·css·react.js
雨白16 小时前
Activity的三个实用技巧
android