【android bluetooth 协议分析 01】【HCI 层介绍 9】【ReadLocalSupportedCommands命令介绍】

1. HCI_Read_Local_Supported_Commands 命令介绍

1. 命令介绍(Description)

HCI_Read_Local_Supported_Commands 是 HCI 层中非常重要的查询命令。它允许 Host(如 Android 系统中的 Bluetooth stack)获取 Controller(蓝牙芯片)支持的 所有 HCI 命令 列表。

这些命令的支持情况由 Supported_Commands 这个 64 字节位图 表示,每一位(bit)对应一个 HCI 命令是否支持。

🔹 本质:能力查询的位图(Command Capabilities Bitmap)


2.命令参数

c 复制代码
13	2025-04-24 15:55:53.354453	host	controller	HCI_CMD	4	Sent Read Local Supported Commands

Bluetooth HCI Command - Read Local Supported Commands
    Command Opcode: Read Local Supported Commands (0x1002)
        0001 00.. .... .... = Opcode Group Field: Informational Parameters (0x04)
        .... ..00 0000 0010 = Opcode Command Field: Read Local Supported Commands (0x002)
    Parameter Total Length: 0
    [Response in frame: 14]
    [Command-Response Delta: 0.775ms]

无参数


3. 返回参数

c 复制代码
14	2025-04-24 15:55:53.355228	controller	host	HCI_EVT	71	Rcvd Command Complete (Read Local Supported Commands)

Bluetooth HCI Event - Command Complete
    Event Code: Command Complete (0x0e)
    Parameter Total Length: 68
    Number of Allowed Command Packets: 1
    Command Opcode: Read Local Supported Commands (0x1002)
        0001 00.. .... .... = Opcode Group Field: Informational Parameters (0x04)
        .... ..00 0000 0010 = Opcode Command Field: Read Local Supported Commands (0x002)
    Status: Success (0x00)
    Local Supported Commands: ffffff03ceffefffffffff1ff20fe8fe3ff783ff1c00040061ffffff7f3820f5fff0ffff...
    [Command in frame: 13]
    [Command-Response Delta: 0.775ms]
参数名 大小 描述
Status 1 byte 0x00 表示成功
Supported_Commands 64 bytes 每个 bit 对应一个 HCI 命令是否支持(参考 Vol 4, Part E, Section 6.27)

4.事件

  • 成功后会通过 HCI_Command_Complete 事件返回上述字段

5. Supported_Commands 的位图说明

这个位图是 HCI 控制器支持能力的集中体现。例如:

  • Byte 0 bit 0 → HCI_Inquiry
  • Byte 0 bit 1 → HCI_Inquiry_Cancel
  • Byte 1 bit 5 → HCI_Read_Remote_Supported_Features
  • Byte 5 bit 6 → HCI_LE_Set_Advertise_Enable
  • Byte 27 bit 2 → HCI_LE_Set_Extended_Advertising_Parameters

等等,具体定义见 Bluetooth Core Spec Vol 4, Part E, Section 6.27(共 64 字节,512 bits,分别映射所有可能的 HCI 命令)


2. aosp 中的应用

1. host 发送该命令

c 复制代码
// system/gd/hci/controller.cc

struct Controller::impl {

  void Start(hci::HciLayer* hci) {
...
	hci_->EnqueueCommand(ReadLocalSupportedCommandsBuilder::Create(),
                         handler->BindOnceOn(this, &Controller::impl::read_local_supported_commands_complete_handler));
...
}

当收到 controller 的回复时将调用 read_local_supported_commands_complete_handler

1. read_local_supported_commands_complete_handler

c 复制代码
  void read_local_supported_commands_complete_handler(CommandCompleteView view) {
    auto complete_view = ReadLocalSupportedCommandsCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    ErrorCode status = complete_view.GetStatus();
    ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str());
    local_supported_commands_ = complete_view.GetSupportedCommands();
  }
  • 将 命令支持位图 保存在 local_supported_commands_ 中

我们来看一下如何使用 local_supported_commands_

c 复制代码
// system/gd/hci/controller.cc

#define OP_CODE_MAPPING(name)                                                  \
  case OpCode::name: {                                                         \
    uint16_t index = (uint16_t)OpCodeIndex::name;                              \
    uint16_t byte_index = index / 10;                                          \
    uint16_t bit_index = index % 10;                                           \
    bool supported = local_supported_commands_[byte_index] & (1 << bit_index); \
    if (!supported) {                                                          \
      LOG_DEBUG("unsupported command opcode: 0x%04x", (uint16_t)OpCode::name); \
    }                                                                          \
    return supported;                                                          \
  }

OpCodeIndex 命令索引如下:

  • system/gd/hci/hci_packets.pdl
c 复制代码
// For mapping Local Supported Commands command
// Value = Octet * 10 + bit
enum OpCodeIndex : 16 {
  INQUIRY = 0,
  INQUIRY_CANCEL = 1,
  PERIODIC_INQUIRY_MODE = 2,
  EXIT_PERIODIC_INQUIRY_MODE = 3,
  CREATE_CONNECTION = 4,
  DISCONNECT = 5,
  ADD_SCO_CONNECTION = 6,
  CREATE_CONNECTION_CANCEL = 7,
  ACCEPT_CONNECTION_REQUEST = 10,
  REJECT_CONNECTION_REQUEST = 11,
  LINK_KEY_REQUEST_REPLY = 12,
  LINK_KEY_REQUEST_NEGATIVE_REPLY = 13,
  PIN_CODE_REQUEST_REPLY = 14,
  PIN_CODE_REQUEST_NEGATIVE_REPLY = 15,
  CHANGE_CONNECTION_PACKET_TYPE = 16,
  AUTHENTICATION_REQUESTED = 17,
  SET_CONNECTION_ENCRYPTION = 20,
  CHANGE_CONNECTION_LINK_KEY = 21,
  CENTRAL_LINK_KEY = 22,
  REMOTE_NAME_REQUEST = 23,
  REMOTE_NAME_REQUEST_CANCEL = 24,
  READ_REMOTE_SUPPORTED_FEATURES = 25,
  READ_REMOTE_EXTENDED_FEATURES = 26,
  READ_REMOTE_VERSION_INFORMATION = 27,
  READ_CLOCK_OFFSET = 30,
  READ_LMP_HANDLE = 31,
  HOLD_MODE = 41,
  SNIFF_MODE = 42,
  EXIT_SNIFF_MODE = 43,
  QOS_SETUP = 46,
  ROLE_DISCOVERY = 47,
  SWITCH_ROLE = 50,
  READ_LINK_POLICY_SETTINGS = 51,
  WRITE_LINK_POLICY_SETTINGS = 52,
  READ_DEFAULT_LINK_POLICY_SETTINGS = 53,
  WRITE_DEFAULT_LINK_POLICY_SETTINGS = 54,
  FLOW_SPECIFICATION = 55,
  SET_EVENT_MASK = 56,
  RESET = 57,
  SET_EVENT_FILTER = 60,
  FLUSH = 61,
  READ_PIN_TYPE = 62,
  WRITE_PIN_TYPE = 63,
  READ_STORED_LINK_KEY = 65,
  WRITE_STORED_LINK_KEY = 66,
  DELETE_STORED_LINK_KEY = 67,
  WRITE_LOCAL_NAME = 70,
  READ_LOCAL_NAME = 71,
  READ_CONNECTION_ACCEPT_TIMEOUT = 72,
  WRITE_CONNECTION_ACCEPT_TIMEOUT = 73,
  READ_PAGE_TIMEOUT = 74,
  WRITE_PAGE_TIMEOUT = 75,
  READ_SCAN_ENABLE = 76,
  WRITE_SCAN_ENABLE = 77,
  READ_PAGE_SCAN_ACTIVITY = 80,
  WRITE_PAGE_SCAN_ACTIVITY = 81,
  READ_INQUIRY_SCAN_ACTIVITY = 82,
  WRITE_INQUIRY_SCAN_ACTIVITY = 83,
  READ_AUTHENTICATION_ENABLE = 84,
  WRITE_AUTHENTICATION_ENABLE = 85,
  READ_CLASS_OF_DEVICE = 90,
  WRITE_CLASS_OF_DEVICE = 91,
  READ_VOICE_SETTING = 92,
  WRITE_VOICE_SETTING = 93,
  READ_AUTOMATIC_FLUSH_TIMEOUT = 94,
  WRITE_AUTOMATIC_FLUSH_TIMEOUT = 95,
  READ_NUM_BROADCAST_RETRANSMITS = 96,
  WRITE_NUM_BROADCAST_RETRANSMITS = 97,
  READ_HOLD_MODE_ACTIVITY = 100,
  WRITE_HOLD_MODE_ACTIVITY = 101,
  READ_TRANSMIT_POWER_LEVEL = 102,
  READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 103,
  WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 104,
  SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 105,
  HOST_BUFFER_SIZE = 106,
  HOST_NUM_COMPLETED_PACKETS = 107,
  READ_LINK_SUPERVISION_TIMEOUT = 110,
  WRITE_LINK_SUPERVISION_TIMEOUT = 111,
  READ_NUMBER_OF_SUPPORTED_IAC = 112,
  READ_CURRENT_IAC_LAP = 113,
  WRITE_CURRENT_IAC_LAP = 114,
  SET_AFH_HOST_CHANNEL_CLASSIFICATION = 121,
  READ_INQUIRY_SCAN_TYPE = 124,
  WRITE_INQUIRY_SCAN_TYPE = 125,
  READ_INQUIRY_MODE = 126,
  WRITE_INQUIRY_MODE = 127,
  READ_PAGE_SCAN_TYPE = 130,
  WRITE_PAGE_SCAN_TYPE = 131,
  READ_AFH_CHANNEL_ASSESSMENT_MODE = 132,
  WRITE_AFH_CHANNEL_ASSESSMENT_MODE = 133,
  READ_LOCAL_VERSION_INFORMATION = 143,
  READ_LOCAL_SUPPORTED_FEATURES = 145,
  READ_LOCAL_EXTENDED_FEATURES = 146,
  READ_BUFFER_SIZE = 147,
  READ_BD_ADDR = 151,
  READ_FAILED_CONTACT_COUNTER = 152,
  RESET_FAILED_CONTACT_COUNTER = 153,
  READ_LINK_QUALITY = 154,
  READ_RSSI = 155,
  READ_AFH_CHANNEL_MAP = 156,
  READ_CLOCK = 157,
  READ_LOOPBACK_MODE = 160,
  WRITE_LOOPBACK_MODE = 161,
  ENABLE_DEVICE_UNDER_TEST_MODE = 162,
  SETUP_SYNCHRONOUS_CONNECTION = 163,
  ACCEPT_SYNCHRONOUS_CONNECTION = 164,
  REJECT_SYNCHRONOUS_CONNECTION = 165,
  READ_EXTENDED_INQUIRY_RESPONSE = 170,
  WRITE_EXTENDED_INQUIRY_RESPONSE = 171,
  REFRESH_ENCRYPTION_KEY = 172,
  SNIFF_SUBRATING = 174,
  READ_SIMPLE_PAIRING_MODE = 175,
  WRITE_SIMPLE_PAIRING_MODE = 176,
  READ_LOCAL_OOB_DATA = 177,
  READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = 180,
  WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = 181,
  IO_CAPABILITY_REQUEST_REPLY = 187,
  USER_CONFIRMATION_REQUEST_REPLY = 190,
  USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = 191,
  USER_PASSKEY_REQUEST_REPLY = 192,
  USER_PASSKEY_REQUEST_NEGATIVE_REPLY = 193,
  REMOTE_OOB_DATA_REQUEST_REPLY = 194,
  WRITE_SIMPLE_PAIRING_DEBUG_MODE = 195,
  ENHANCED_FLUSH = 196,
  REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = 197,
  SEND_KEYPRESS_NOTIFICATION = 202,
  IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = 203,
  READ_ENCRYPTION_KEY_SIZE = 204,
  SET_EVENT_MASK_PAGE_2 = 222,
  READ_DATA_BLOCK_SIZE = 232,
  READ_LE_HOST_SUPPORT = 245,
  WRITE_LE_HOST_SUPPORT = 246,
  LE_SET_EVENT_MASK = 250,
  LE_READ_BUFFER_SIZE_V1 = 251,
  LE_READ_LOCAL_SUPPORTED_FEATURES = 252,
  LE_SET_RANDOM_ADDRESS = 254,
  LE_SET_ADVERTISING_PARAMETERS = 255,
  LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER = 256,
  LE_SET_ADVERTISING_DATA = 257,
  LE_SET_SCAN_RESPONSE_DATA = 260,
  LE_SET_ADVERTISING_ENABLE = 261,
  LE_SET_SCAN_PARAMETERS = 262,
  LE_SET_SCAN_ENABLE = 263,
  LE_CREATE_CONNECTION = 264,
  LE_CREATE_CONNECTION_CANCEL = 265,
  LE_READ_FILTER_ACCEPT_LIST_SIZE = 266,
  LE_CLEAR_FILTER_ACCEPT_LIST = 267,
  LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST = 270,
  LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST = 271,
  LE_CONNECTION_UPDATE = 272,
  LE_SET_HOST_CHANNEL_CLASSIFICATION = 273,
  LE_READ_CHANNEL_MAP = 274,
  LE_READ_REMOTE_FEATURES = 275,
  LE_ENCRYPT = 276,
  LE_RAND = 277,
  LE_START_ENCRYPTION = 280,
  LE_LONG_TERM_KEY_REQUEST_REPLY = 281,
  LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY = 282,
  LE_READ_SUPPORTED_STATES = 283,
  LE_RECEIVER_TEST = 284,
  LE_TRANSMITTER_TEST = 285,
  LE_TEST_END = 286,
  ENHANCED_SETUP_SYNCHRONOUS_CONNECTION = 293,
  ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION = 294,
  READ_LOCAL_SUPPORTED_CODECS_V1 = 295,
  REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY = 321,
  READ_SECURE_CONNECTIONS_HOST_SUPPORT = 322,
  WRITE_SECURE_CONNECTIONS_HOST_SUPPORT = 323,
  READ_LOCAL_OOB_EXTENDED_DATA = 326,
  WRITE_SECURE_CONNECTIONS_TEST_MODE = 327,
  LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY = 334,
  LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY = 335,
  LE_SET_DATA_LENGTH = 336,
  LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = 337,
  LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = 340,
  LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND = 341,
  LE_GENERATE_DHKEY_COMMAND_V1 = 342,
  LE_ADD_DEVICE_TO_RESOLVING_LIST = 343,
  LE_REMOVE_DEVICE_FROM_RESOLVING_LIST = 344,
  LE_CLEAR_RESOLVING_LIST = 345,
  LE_READ_RESOLVING_LIST_SIZE = 346,
  LE_READ_PEER_RESOLVABLE_ADDRESS = 347,
  LE_READ_LOCAL_RESOLVABLE_ADDRESS = 350,
  LE_SET_ADDRESS_RESOLUTION_ENABLE = 351,
  LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT = 352,
  LE_READ_MAXIMUM_DATA_LENGTH = 353,
  LE_READ_PHY = 354,
  LE_SET_DEFAULT_PHY = 355,
  LE_SET_PHY = 356,
  LE_ENHANCED_RECEIVER_TEST = 357,
  LE_ENHANCED_TRANSMITTER_TEST = 360,
  LE_SET_ADVERTISING_SET_RANDOM_ADDRESS = 361,
  LE_SET_EXTENDED_ADVERTISING_PARAMETERS = 362,
  LE_SET_EXTENDED_ADVERTISING_DATA = 363,
  LE_SET_EXTENDED_SCAN_RESPONSE_DATA = 364,
  LE_SET_EXTENDED_ADVERTISING_ENABLE = 365,
  LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = 366,
  LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS = 367,
  LE_REMOVE_ADVERTISING_SET = 370,
  LE_CLEAR_ADVERTISING_SETS = 371,
  LE_SET_PERIODIC_ADVERTISING_PARAM = 372,
  LE_SET_PERIODIC_ADVERTISING_DATA = 373,
  LE_SET_PERIODIC_ADVERTISING_ENABLE = 374,
  LE_SET_EXTENDED_SCAN_PARAMETERS = 375,
  LE_SET_EXTENDED_SCAN_ENABLE = 376,
  LE_EXTENDED_CREATE_CONNECTION = 377,
  LE_PERIODIC_ADVERTISING_CREATE_SYNC = 380,
  LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = 381,
  LE_PERIODIC_ADVERTISING_TERMINATE_SYNC = 382,
  LE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST = 383,
  LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISING_LIST = 384,
  LE_CLEAR_PERIODIC_ADVERTISING_LIST = 385,
  LE_READ_PERIODIC_ADVERTISING_LIST_SIZE = 386,
  LE_READ_TRANSMIT_POWER = 387,
  LE_READ_RF_PATH_COMPENSATION_POWER = 390,
  LE_WRITE_RF_PATH_COMPENSATION_POWER = 391,
  LE_SET_PRIVACY_MODE = 392,

  LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE = 405,
  LE_PERIODIC_ADVERTISING_SYNC_TRANSFER = 406,
  LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER = 407,
  LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS = 410,
  LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS = 411,
  LE_GENERATE_DHKEY_COMMAND = 412,
  LE_MODIFY_SLEEP_CLOCK_ACCURACY = 414,
  LE_READ_BUFFER_SIZE_V2 = 415,
  LE_READ_ISO_TX_SYNC = 416,
  LE_SET_CIG_PARAMETERS = 417,
  LE_SET_CIG_PARAMETERS_TEST = 418,
  LE_CREATE_CIS = 421,
  LE_REMOVE_CIG = 422,
  LE_ACCEPT_CIS_REQUEST = 423,
  LE_REJECT_CIS_REQUEST = 424,
  LE_CREATE_BIG = 425,
  LE_TERMINATE_BIG = 427,
  LE_BIG_CREATE_SYNC = 430,
  LE_BIG_TERMINATE_SYNC = 431,
  LE_REQUEST_PEER_SCA = 432,
  LE_SETUP_ISO_DATA_PATH = 433,
  LE_REMOVE_ISO_DATA_PATH = 434,
  LE_SET_HOST_FEATURE = 441,
  LE_READ_ISO_LINK_QUALITY = 442,
  LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL = 443,
  LE_READ_REMOTE_TRANSMIT_POWER_LEVEL = 444,
  LE_SET_PATH_LOSS_REPORTING_PARAMETERS = 445,
  LE_SET_PATH_LOSS_REPORTING_ENABLE = 446,
  LE_SET_TRANSMIT_POWER_REPORTING_ENABLE = 447,
  SET_ECOSYSTEM_BASE_INTERVAL = 451,
  READ_LOCAL_SUPPORTED_CODECS_V2 = 452,
  READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES = 453,
  READ_LOCAL_SUPPORTED_CONTROLLER_DELAY = 454,
  CONFIGURE_DATA_PATH = 455,
  LE_SET_DATA_RELATED_ADDRESS_CHANGES = 456,
  SET_MIN_ENCRYPTION_KEY_SIZE = 457,
  LE_SET_DEFAULT_SUBRATE = 460,
  LE_SUBRATE_REQUEST = 461,
}

这里我拿 LE_SUBRATE_REQUEST 为例 说明 OP_CODE_MAPPING 如何使用:

c 复制代码
#define OP_CODE_MAPPING(LE_SUBRATE_REQUEST)      

// 等价于下面的:

  case OpCode::LE_SUBRATE_REQUEST: {                                                         
    uint16_t index = (uint16_t)OpCodeIndex::LE_SUBRATE_REQUEST;// 461                              
    uint16_t byte_index = index / 10; // 46                                          
    uint16_t bit_index = index % 10;  // 1                                         
    bool supported = local_supported_commands_[byte_index] & (1 << bit_index);  // local_supported_commands_ 位图中第 46 字节第1bit
    if (!supported) {                                                          
      LOG_DEBUG("unsupported command opcode: 0x%04x", (uint16_t)OpCode::LE_SUBRATE_REQUEST); 
    }                                                                          
    return supported;                                                          
  }
  • 通过 OP_CODE_MAPPING 我们可以成功索引到 该 hcicmd 在 位图中对应的位。
c 复制代码
// system/gd/hci/controller.cc
  bool is_supported(OpCode op_code) {
    switch (op_code) {
      OP_CODE_MAPPING(INQUIRY)
      OP_CODE_MAPPING(INQUIRY_CANCEL)
      OP_CODE_MAPPING(PERIODIC_INQUIRY_MODE)
      OP_CODE_MAPPING(EXIT_PERIODIC_INQUIRY_MODE)
      OP_CODE_MAPPING(CREATE_CONNECTION)
      OP_CODE_MAPPING(DISCONNECT)
      OP_CODE_MAPPING(CREATE_CONNECTION_CANCEL)
      OP_CODE_MAPPING(ACCEPT_CONNECTION_REQUEST)
      OP_CODE_MAPPING(REJECT_CONNECTION_REQUEST)
      OP_CODE_MAPPING(LINK_KEY_REQUEST_REPLY)
      OP_CODE_MAPPING(LINK_KEY_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(PIN_CODE_REQUEST_REPLY)
      OP_CODE_MAPPING(PIN_CODE_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(CHANGE_CONNECTION_PACKET_TYPE)
      OP_CODE_MAPPING(AUTHENTICATION_REQUESTED)
      OP_CODE_MAPPING(SET_CONNECTION_ENCRYPTION)
      OP_CODE_MAPPING(CHANGE_CONNECTION_LINK_KEY)
      OP_CODE_MAPPING(CENTRAL_LINK_KEY)
      OP_CODE_MAPPING(REMOTE_NAME_REQUEST)
      OP_CODE_MAPPING(REMOTE_NAME_REQUEST_CANCEL)
      OP_CODE_MAPPING(READ_REMOTE_SUPPORTED_FEATURES)
      OP_CODE_MAPPING(READ_REMOTE_EXTENDED_FEATURES)
      OP_CODE_MAPPING(READ_REMOTE_VERSION_INFORMATION)
      OP_CODE_MAPPING(READ_CLOCK_OFFSET)
      OP_CODE_MAPPING(READ_LMP_HANDLE)
      OP_CODE_MAPPING(HOLD_MODE)
      OP_CODE_MAPPING(SNIFF_MODE)
      OP_CODE_MAPPING(EXIT_SNIFF_MODE)
      OP_CODE_MAPPING(QOS_SETUP)
      OP_CODE_MAPPING(ROLE_DISCOVERY)
      OP_CODE_MAPPING(SWITCH_ROLE)
      OP_CODE_MAPPING(READ_LINK_POLICY_SETTINGS)
      OP_CODE_MAPPING(WRITE_LINK_POLICY_SETTINGS)
      OP_CODE_MAPPING(READ_DEFAULT_LINK_POLICY_SETTINGS)
      OP_CODE_MAPPING(WRITE_DEFAULT_LINK_POLICY_SETTINGS)
      OP_CODE_MAPPING(FLOW_SPECIFICATION)
      OP_CODE_MAPPING(SET_EVENT_MASK)
      OP_CODE_MAPPING(RESET)
      OP_CODE_MAPPING(SET_EVENT_FILTER)
      OP_CODE_MAPPING(FLUSH)
      OP_CODE_MAPPING(READ_PIN_TYPE)
      OP_CODE_MAPPING(WRITE_PIN_TYPE)
      OP_CODE_MAPPING(READ_STORED_LINK_KEY)
      OP_CODE_MAPPING(WRITE_STORED_LINK_KEY)
      OP_CODE_MAPPING(DELETE_STORED_LINK_KEY)
      OP_CODE_MAPPING(WRITE_LOCAL_NAME)
      OP_CODE_MAPPING(READ_LOCAL_NAME)
      OP_CODE_MAPPING(READ_CONNECTION_ACCEPT_TIMEOUT)
      OP_CODE_MAPPING(WRITE_CONNECTION_ACCEPT_TIMEOUT)
      OP_CODE_MAPPING(READ_PAGE_TIMEOUT)
      OP_CODE_MAPPING(WRITE_PAGE_TIMEOUT)
      OP_CODE_MAPPING(READ_SCAN_ENABLE)
      OP_CODE_MAPPING(WRITE_SCAN_ENABLE)
      OP_CODE_MAPPING(READ_PAGE_SCAN_ACTIVITY)
      OP_CODE_MAPPING(WRITE_PAGE_SCAN_ACTIVITY)
      OP_CODE_MAPPING(READ_INQUIRY_SCAN_ACTIVITY)
      OP_CODE_MAPPING(WRITE_INQUIRY_SCAN_ACTIVITY)
      OP_CODE_MAPPING(READ_AUTHENTICATION_ENABLE)
      OP_CODE_MAPPING(WRITE_AUTHENTICATION_ENABLE)
      OP_CODE_MAPPING(READ_CLASS_OF_DEVICE)
      OP_CODE_MAPPING(WRITE_CLASS_OF_DEVICE)
      OP_CODE_MAPPING(READ_VOICE_SETTING)
      OP_CODE_MAPPING(WRITE_VOICE_SETTING)
      OP_CODE_MAPPING(READ_AUTOMATIC_FLUSH_TIMEOUT)
      OP_CODE_MAPPING(WRITE_AUTOMATIC_FLUSH_TIMEOUT)
      OP_CODE_MAPPING(READ_NUM_BROADCAST_RETRANSMITS)
      OP_CODE_MAPPING(WRITE_NUM_BROADCAST_RETRANSMITS)
      OP_CODE_MAPPING(READ_HOLD_MODE_ACTIVITY)
      OP_CODE_MAPPING(WRITE_HOLD_MODE_ACTIVITY)
      OP_CODE_MAPPING(READ_TRANSMIT_POWER_LEVEL)
      OP_CODE_MAPPING(READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE)
      OP_CODE_MAPPING(WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE)
      OP_CODE_MAPPING(SET_CONTROLLER_TO_HOST_FLOW_CONTROL)
      OP_CODE_MAPPING(HOST_BUFFER_SIZE)
      OP_CODE_MAPPING(HOST_NUM_COMPLETED_PACKETS)
      OP_CODE_MAPPING(READ_LINK_SUPERVISION_TIMEOUT)
      OP_CODE_MAPPING(WRITE_LINK_SUPERVISION_TIMEOUT)
      OP_CODE_MAPPING(READ_NUMBER_OF_SUPPORTED_IAC)
      OP_CODE_MAPPING(READ_CURRENT_IAC_LAP)
      OP_CODE_MAPPING(WRITE_CURRENT_IAC_LAP)
      OP_CODE_MAPPING(SET_AFH_HOST_CHANNEL_CLASSIFICATION)
      OP_CODE_MAPPING(READ_INQUIRY_SCAN_TYPE)
      OP_CODE_MAPPING(WRITE_INQUIRY_SCAN_TYPE)
      OP_CODE_MAPPING(READ_INQUIRY_MODE)
      OP_CODE_MAPPING(WRITE_INQUIRY_MODE)
      OP_CODE_MAPPING(READ_PAGE_SCAN_TYPE)
      OP_CODE_MAPPING(WRITE_PAGE_SCAN_TYPE)
      OP_CODE_MAPPING(READ_AFH_CHANNEL_ASSESSMENT_MODE)
      OP_CODE_MAPPING(WRITE_AFH_CHANNEL_ASSESSMENT_MODE)
      OP_CODE_MAPPING(READ_LOCAL_VERSION_INFORMATION)
      OP_CODE_MAPPING(READ_LOCAL_SUPPORTED_FEATURES)
      OP_CODE_MAPPING(READ_LOCAL_EXTENDED_FEATURES)
      OP_CODE_MAPPING(READ_BUFFER_SIZE)
      OP_CODE_MAPPING(READ_BD_ADDR)
      OP_CODE_MAPPING(READ_FAILED_CONTACT_COUNTER)
      OP_CODE_MAPPING(RESET_FAILED_CONTACT_COUNTER)
      OP_CODE_MAPPING(READ_LINK_QUALITY)
      OP_CODE_MAPPING(READ_RSSI)
      OP_CODE_MAPPING(READ_AFH_CHANNEL_MAP)
      OP_CODE_MAPPING(READ_CLOCK)
      OP_CODE_MAPPING(READ_LOOPBACK_MODE)
      OP_CODE_MAPPING(WRITE_LOOPBACK_MODE)
      OP_CODE_MAPPING(ENABLE_DEVICE_UNDER_TEST_MODE)
      OP_CODE_MAPPING(SETUP_SYNCHRONOUS_CONNECTION)
      OP_CODE_MAPPING(ACCEPT_SYNCHRONOUS_CONNECTION)
      OP_CODE_MAPPING(REJECT_SYNCHRONOUS_CONNECTION)
      OP_CODE_MAPPING(READ_EXTENDED_INQUIRY_RESPONSE)
      OP_CODE_MAPPING(WRITE_EXTENDED_INQUIRY_RESPONSE)
      OP_CODE_MAPPING(REFRESH_ENCRYPTION_KEY)
      OP_CODE_MAPPING(SNIFF_SUBRATING)
      OP_CODE_MAPPING(READ_SIMPLE_PAIRING_MODE)
      OP_CODE_MAPPING(WRITE_SIMPLE_PAIRING_MODE)
      OP_CODE_MAPPING(READ_LOCAL_OOB_DATA)
      OP_CODE_MAPPING(READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL)
      OP_CODE_MAPPING(WRITE_INQUIRY_TRANSMIT_POWER_LEVEL)
      OP_CODE_MAPPING(IO_CAPABILITY_REQUEST_REPLY)
      OP_CODE_MAPPING(USER_CONFIRMATION_REQUEST_REPLY)
      OP_CODE_MAPPING(USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(USER_PASSKEY_REQUEST_REPLY)
      OP_CODE_MAPPING(USER_PASSKEY_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(REMOTE_OOB_DATA_REQUEST_REPLY)
      OP_CODE_MAPPING(WRITE_SIMPLE_PAIRING_DEBUG_MODE)
      OP_CODE_MAPPING(REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(SEND_KEYPRESS_NOTIFICATION)
      OP_CODE_MAPPING(SET_EVENT_MASK_PAGE_2)
      OP_CODE_MAPPING(IO_CAPABILITY_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY)
      OP_CODE_MAPPING(READ_ENCRYPTION_KEY_SIZE)
      OP_CODE_MAPPING(READ_DATA_BLOCK_SIZE)
      OP_CODE_MAPPING(READ_LE_HOST_SUPPORT)
      OP_CODE_MAPPING(WRITE_LE_HOST_SUPPORT)
      OP_CODE_MAPPING(LE_SET_EVENT_MASK)
      OP_CODE_MAPPING(LE_READ_BUFFER_SIZE_V1)
      OP_CODE_MAPPING(LE_READ_LOCAL_SUPPORTED_FEATURES)
      OP_CODE_MAPPING(LE_SET_RANDOM_ADDRESS)
      OP_CODE_MAPPING(LE_SET_ADVERTISING_PARAMETERS)
      OP_CODE_MAPPING(LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER)
      OP_CODE_MAPPING(LE_SET_ADVERTISING_DATA)
      OP_CODE_MAPPING(LE_SET_SCAN_RESPONSE_DATA)
      OP_CODE_MAPPING(LE_SET_ADVERTISING_ENABLE)
      OP_CODE_MAPPING(LE_SET_SCAN_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_SCAN_ENABLE)
      OP_CODE_MAPPING(LE_CREATE_CONNECTION)
      OP_CODE_MAPPING(LE_CREATE_CONNECTION_CANCEL)
      OP_CODE_MAPPING(LE_READ_FILTER_ACCEPT_LIST_SIZE)
      OP_CODE_MAPPING(LE_CLEAR_FILTER_ACCEPT_LIST)
      OP_CODE_MAPPING(LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST)
      OP_CODE_MAPPING(LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST)
      OP_CODE_MAPPING(LE_CONNECTION_UPDATE)
      OP_CODE_MAPPING(LE_SET_HOST_CHANNEL_CLASSIFICATION)
      OP_CODE_MAPPING(LE_READ_CHANNEL_MAP)
      OP_CODE_MAPPING(LE_READ_REMOTE_FEATURES)
      OP_CODE_MAPPING(LE_ENCRYPT)
      OP_CODE_MAPPING(LE_RAND)
      OP_CODE_MAPPING(LE_START_ENCRYPTION)
      OP_CODE_MAPPING(LE_LONG_TERM_KEY_REQUEST_REPLY)
      OP_CODE_MAPPING(LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(LE_READ_SUPPORTED_STATES)
      OP_CODE_MAPPING(LE_RECEIVER_TEST)
      OP_CODE_MAPPING(LE_TRANSMITTER_TEST)
      OP_CODE_MAPPING(LE_TEST_END)
      OP_CODE_MAPPING(ENHANCED_SETUP_SYNCHRONOUS_CONNECTION)
      OP_CODE_MAPPING(ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION)
      OP_CODE_MAPPING(READ_LOCAL_SUPPORTED_CODECS_V1)
      OP_CODE_MAPPING(READ_SECURE_CONNECTIONS_HOST_SUPPORT)
      OP_CODE_MAPPING(WRITE_SECURE_CONNECTIONS_HOST_SUPPORT)
      OP_CODE_MAPPING(READ_LOCAL_OOB_EXTENDED_DATA)
      OP_CODE_MAPPING(WRITE_SECURE_CONNECTIONS_TEST_MODE)
      OP_CODE_MAPPING(LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY)
      OP_CODE_MAPPING(LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY)
      OP_CODE_MAPPING(LE_SET_DATA_LENGTH)
      OP_CODE_MAPPING(LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH)
      OP_CODE_MAPPING(LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH)
      OP_CODE_MAPPING(LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND)
      OP_CODE_MAPPING(LE_GENERATE_DHKEY_COMMAND_V1)
      OP_CODE_MAPPING(LE_ADD_DEVICE_TO_RESOLVING_LIST)
      OP_CODE_MAPPING(LE_REMOVE_DEVICE_FROM_RESOLVING_LIST)
      OP_CODE_MAPPING(LE_CLEAR_RESOLVING_LIST)
      OP_CODE_MAPPING(LE_READ_RESOLVING_LIST_SIZE)
      OP_CODE_MAPPING(LE_READ_PEER_RESOLVABLE_ADDRESS)
      OP_CODE_MAPPING(LE_READ_LOCAL_RESOLVABLE_ADDRESS)
      OP_CODE_MAPPING(LE_SET_ADDRESS_RESOLUTION_ENABLE)
      OP_CODE_MAPPING(LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT)
      OP_CODE_MAPPING(LE_READ_MAXIMUM_DATA_LENGTH)
      OP_CODE_MAPPING(LE_READ_PHY)
      OP_CODE_MAPPING(LE_SET_DEFAULT_PHY)
      OP_CODE_MAPPING(LE_SET_PHY)
      OP_CODE_MAPPING(LE_ENHANCED_RECEIVER_TEST)
      OP_CODE_MAPPING(LE_ENHANCED_TRANSMITTER_TEST)
      OP_CODE_MAPPING(LE_SET_ADVERTISING_SET_RANDOM_ADDRESS)
      OP_CODE_MAPPING(LE_SET_EXTENDED_ADVERTISING_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_EXTENDED_ADVERTISING_DATA)
      OP_CODE_MAPPING(LE_SET_EXTENDED_SCAN_RESPONSE_DATA)
      OP_CODE_MAPPING(LE_SET_EXTENDED_ADVERTISING_ENABLE)
      OP_CODE_MAPPING(LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH)
      OP_CODE_MAPPING(LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS)
      OP_CODE_MAPPING(LE_REMOVE_ADVERTISING_SET)
      OP_CODE_MAPPING(LE_CLEAR_ADVERTISING_SETS)
      OP_CODE_MAPPING(LE_SET_PERIODIC_ADVERTISING_PARAM)
      OP_CODE_MAPPING(LE_SET_PERIODIC_ADVERTISING_DATA)
      OP_CODE_MAPPING(LE_SET_PERIODIC_ADVERTISING_ENABLE)
      OP_CODE_MAPPING(LE_SET_EXTENDED_SCAN_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_EXTENDED_SCAN_ENABLE)
      OP_CODE_MAPPING(LE_EXTENDED_CREATE_CONNECTION)
      OP_CODE_MAPPING(LE_PERIODIC_ADVERTISING_CREATE_SYNC)
      OP_CODE_MAPPING(LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL)
      OP_CODE_MAPPING(LE_PERIODIC_ADVERTISING_TERMINATE_SYNC)
      OP_CODE_MAPPING(LE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST)
      OP_CODE_MAPPING(LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISING_LIST)
      OP_CODE_MAPPING(LE_CLEAR_PERIODIC_ADVERTISING_LIST)
      OP_CODE_MAPPING(LE_READ_PERIODIC_ADVERTISING_LIST_SIZE)
      OP_CODE_MAPPING(LE_READ_TRANSMIT_POWER)
      OP_CODE_MAPPING(LE_READ_RF_PATH_COMPENSATION_POWER)
      OP_CODE_MAPPING(LE_WRITE_RF_PATH_COMPENSATION_POWER)
      OP_CODE_MAPPING(LE_SET_PRIVACY_MODE)
      OP_CODE_MAPPING(LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE)
      OP_CODE_MAPPING(LE_PERIODIC_ADVERTISING_SYNC_TRANSFER)
      OP_CODE_MAPPING(LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER)
      OP_CODE_MAPPING(LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS)
      OP_CODE_MAPPING(LE_GENERATE_DHKEY_COMMAND)
      OP_CODE_MAPPING(LE_MODIFY_SLEEP_CLOCK_ACCURACY)
      OP_CODE_MAPPING(LE_READ_BUFFER_SIZE_V2)
      OP_CODE_MAPPING(LE_READ_ISO_TX_SYNC)
      OP_CODE_MAPPING(LE_SET_CIG_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_CIG_PARAMETERS_TEST)
      OP_CODE_MAPPING(LE_CREATE_CIS)
      OP_CODE_MAPPING(LE_REMOVE_CIG)
      OP_CODE_MAPPING(LE_ACCEPT_CIS_REQUEST)
      OP_CODE_MAPPING(LE_REJECT_CIS_REQUEST)
      OP_CODE_MAPPING(LE_CREATE_BIG)
      OP_CODE_MAPPING(LE_TERMINATE_BIG)
      OP_CODE_MAPPING(LE_BIG_CREATE_SYNC)
      OP_CODE_MAPPING(LE_BIG_TERMINATE_SYNC)
      OP_CODE_MAPPING(LE_REQUEST_PEER_SCA)
      OP_CODE_MAPPING(LE_SETUP_ISO_DATA_PATH)
      OP_CODE_MAPPING(LE_REMOVE_ISO_DATA_PATH)
      OP_CODE_MAPPING(LE_SET_HOST_FEATURE)
      OP_CODE_MAPPING(LE_READ_ISO_LINK_QUALITY)
      OP_CODE_MAPPING(LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL)
      OP_CODE_MAPPING(LE_READ_REMOTE_TRANSMIT_POWER_LEVEL)
      OP_CODE_MAPPING(LE_SET_PATH_LOSS_REPORTING_PARAMETERS)
      OP_CODE_MAPPING(LE_SET_PATH_LOSS_REPORTING_ENABLE)
      OP_CODE_MAPPING(LE_SET_TRANSMIT_POWER_REPORTING_ENABLE)
      OP_CODE_MAPPING(SET_ECOSYSTEM_BASE_INTERVAL)
      OP_CODE_MAPPING(READ_LOCAL_SUPPORTED_CODECS_V2)
      OP_CODE_MAPPING(READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES)
      OP_CODE_MAPPING(READ_LOCAL_SUPPORTED_CONTROLLER_DELAY)
      OP_CODE_MAPPING(CONFIGURE_DATA_PATH)
      OP_CODE_MAPPING(ENHANCED_FLUSH)
      OP_CODE_MAPPING(LE_SET_DATA_RELATED_ADDRESS_CHANGES)
      OP_CODE_MAPPING(LE_SET_DEFAULT_SUBRATE)
      OP_CODE_MAPPING(LE_SUBRATE_REQUEST)
      OP_CODE_MAPPING(SET_MIN_ENCRYPTION_KEY_SIZE)

      // deprecated
      case OpCode::ADD_SCO_CONNECTION:
        return false;

      // vendor specific
      case OpCode::LE_GET_VENDOR_CAPABILITIES:
        return vendor_capabilities_.is_supported_ == 0x01;
      case OpCode::LE_MULTI_ADVT:
        return vendor_capabilities_.max_advt_instances_ != 0x00;
      case OpCode::LE_BATCH_SCAN:
        return vendor_capabilities_.total_scan_results_storage_ != 0x00;
      case OpCode::LE_ADV_FILTER:
        return vendor_capabilities_.filtering_support_ == 0x01;
      case OpCode::LE_ENERGY_INFO:
        return vendor_capabilities_.activity_energy_info_support_ == 0x01;
      case OpCode::LE_EXTENDED_SCAN_PARAMS:
        return vendor_capabilities_.extended_scan_support_ == 0x01;
      case OpCode::CONTROLLER_DEBUG_INFO:
        return vendor_capabilities_.debug_logging_supported_ == 0x01;
      case OpCode::CONTROLLER_A2DP_OPCODE:
        return vendor_capabilities_.a2dp_source_offload_capability_mask_ != 0x00;
      case OpCode::CONTROLLER_BQR:
        return vendor_capabilities_.bluetooth_quality_report_support_ == 0x01;
      // undefined in local_supported_commands_
      case OpCode::READ_LOCAL_SUPPORTED_COMMANDS:
        return true;
      case OpCode::NONE:
        return false;
    }
    return false;
  }
  • 所以如果要判断 当前 controller 是否支持 该命令,只需要调用 is_supported 函数即可。
c 复制代码
bool Controller::IsSupported(bluetooth::hci::OpCode op_code) const {
  return impl_->is_supported(op_code);
}
  • 外部模块只需要调用 Controller::IsSupported 即可判断是否支持该命令。

2. aosp 中的作用:为什么它很重要?

在 Android 蓝牙协议栈(如 system/bt)中,HCI_Read_Local_Supported_Commands 返回的这 64 字节位图广泛用于以下几个方面:


1. 功能检测与控制器能力决策

  • Android 蓝牙栈会根据该命令结果动态判断 Controller 支持哪些命令。

  • 典型例子:LE Extended Advertising、Coded PHY、LE Periodic Advertising 等功能是否可用,直接影响上层是否启用某些 GAP/GATT 功能。


2. 初始化过程动态调整命令发送策略

  • 在 stack 初始化时,controller 不支持某些命令则跳过它们的初始化调用,避免失败。
  • 举例:是否发送 LeReadBufferSizeV2 命令前会先检查对应 bit 是否为 1。
c 复制代码
    if (is_supported(OpCode::LE_READ_BUFFER_SIZE_V2)) {
      hci_->EnqueueCommand(
          LeReadBufferSizeV2Builder::Create(),
          handler->BindOnceOn(this, &Controller::impl::le_read_buffer_size_v2_handler));
    }

3. 厂商定制逻辑与能力适配

  • 有些厂商芯片即便宣称是 BT5.1,但可能缺失部分命令实现。

  • Android 通过查询这个位图 动态适配,避免调用未支持的命令导致错误。


4. 蓝牙兼容性 Debug

  • 蓝牙连接或功能异常时,可通过 dumpsys 或 log 分析哪些命令是被支持的。
  • Supported_Commands 是诊断「为什么不能执行某个 HCI 操作」的关键。

相关推荐
嗷o嗷o24 分钟前
Android BLE 里,MTU、分包和长数据发送到底该怎么处理
android
Gary Studio2 小时前
Android AIDL HAL工程结构示例
android
y = xⁿ2 小时前
MySQL八股知识合集
android·mysql·adb
andr_gale3 小时前
04_rc文件语法规则
android·framework·aosp
祖国的好青年4 小时前
VS Code 搭建 React Native 开发环境(Windows 实战指南)
android·windows·react native·react.js
黄林晴4 小时前
警惕!AGP 9.2 别只改版本号,R8 规则与构建链路全线收紧
android·gradle
小米渣的逆袭5 小时前
Android ADB 完全使用指南
android·adb
儿歌八万首5 小时前
Jetpack Compose Canvas 进阶:结合 animateFloatAsState 让自定义图形动起来
android·动画·compose
zhangphil6 小时前
Android Page 3 Flow读sql数据库媒体文件,Kotlin
android·kotlin