【android bluetooth 协议分析 01】【HCI 层介绍 8】【ReadLocalVersionInformation命令介绍】

1. HCI_Read_Local_Version_Information 命令介绍

在这里插入图片描述在这里插入图片描述

1. 功能(Description)

HCI_Read_Local_Version_Information 命令用于读取本地 Bluetooth Controller 的版本信息,包括 HCI 和 LMP 层的版本,以及厂商 ID 和子版本号。
这类信息用于 Host 识别当前控制器的 功能支持范围、厂商来源 及其具体的实现版本,通常用于以下场景:

  • 协议栈 兼容性判断
  • 对应厂商定制功能 条件启用
  • 调试定位 版本差异导致的问题

2.命令参数(Command Parameters)


11	2025-04-24 15:55:53.353695	host	controller	HCI_CMD	4	Sent Read Local Version InformationBluetooth HCI Command - Read Local Version InformationCommand Opcode: Read Local Version Information (0x1001)0001 00.. .... .... = Opcode Group Field: Informational Parameters (0x04).... ..00 0000 0001 = Opcode Command Field: Read Local Version Information (0x001)Parameter Total Length: 0[Response in frame: 12][Command-Response Delta: 0.572ms]

无参数
只需发送命令,不带任何附加内容。


3.返回参数(Return Parameters)

12	2025-04-24 15:55:53.354267	controller	host	HCI_EVT	15	Rcvd Command Complete (Read Local Version Information)Bluetooth HCI Event - Command CompleteEvent Code: Command Complete (0x0e)Parameter Total Length: 12Number of Allowed Command Packets: 1Command Opcode: Read Local Version Information (0x1001)0001 00.. .... .... = Opcode Group Field: Informational Parameters (0x04).... ..00 0000 0001 = Opcode Command Field: Read Local Version Information (0x001)Status: Success (0x00)HCI Version: 5.3 (0x0c)HCI Revision: 0LMP Version: 5.3 (0x0c)Manufacturer Name: Qualcomm (0x001d)LMP Subversion: 29337[Command in frame: 11][Command-Response Delta: 0.572ms]
参数名大小描述
Status1 字节表示命令执行结果,0x00 表示成功
HCI_Version1 字节控制器 HCI 层的版本号
HCI_Subversion2 字节控制器厂商定义的 HCI 子版本号
LMP_Version1 字节LMP(Link Manager Protocol)版本号
Company_Identifier2 字节控制器厂商 ID,定义于 Bluetooth SIG
LMP_Subversion2 字节厂商自定义的 LMP 子版本号

4. 事件

成功后,Controller 会通过 HCI_Command_Complete 事件返回这些参数。


2. aosp 中如何使用

1. 字段作用与 AOSP 中的意义

下面我们逐个解释这些字段在 AOSP 蓝牙协议栈(如 stack/bt) 中的用途和意义:


1. HCI_Version(1 byte)

  • 定义:控制器实现的 HCI 层版本
  • 可能值
含义
0x06Bluetooth 4.0
0x07Bluetooth 4.1
0x08Bluetooth 4.2
0x09Bluetooth 5.0
0x0ABluetooth 5.1
持续增长
  • 在 AOSP 中的作用
    • 用于判断是否支持某些 HCI 命令或功能,比如 Extended Advertising(需要 BT5.0+)
    • 控制某些 feature 的使能与 fallback(降级)策略

2. HCI_Subversion(2 bytes)

  • 定义:控制器厂商定义的子版本号(可能代表固件版本)
  • 在 AOSP 中的作用
    • 主要用于 调试厂商定制功能的兼容适配
    • 某些厂商驱动层(如 Qualcomm 或 Broadcom)可能会用这个字段判断是否加载特定补丁

3. LMP_Version(1 byte)

  • 定义:Link Manager Protocol 的版本号,用于表示底层链路控制协议的版本

  • 常见值

LMP 版本标准版本
0x06LMP 6BT 2.0
0x07LMP 7BT 2.1
0x08LMP 8BT 3.0
0x09LMP 9BT 4.0
  • 在 AOSP 中的作用
    • 判断是否支持特性如 eSCO、Secure Simple Pairing、LE、BR/EDR coexistence
    • 某些协议或逻辑的 fallback 依据

4. Company_Identifier(2 bytes)

  • 定义:厂商 ID,由 Bluetooth SIG 分配
  • 例子
ID厂商
0x000FBroadcom
0x000CCSR
0x001DApple
0x003DIntel
0x0001Cambridge Silicon Radio (CSR)
  • 在 AOSP 中的作用
    • 用于厂商特定补丁加载
    • 在 log 中标记设备来源
    • 控制 chipset-specific workarounds

5. LMP_Subversion(2 bytes)

  • 定义:LMP 层的子版本号,由厂商定义
  • 在 AOSP 中的作用
    • 仅对特定厂商驱动有用
    • 通常用于识别固件版本差异
    • HCI_Subversion 一起,辅助调试判断“是否为某个具体平台”

2.这些版本信息“能干啥”?意义在哪里?

用途说明
功能判断判断 Controller 是否支持特定协议功能,如 LE Extended Advertising、Secure Connections 等
厂商识别确定芯片是 Broadcom、Qualcomm、Intel 还是其他,从而决定加载哪些定制行为
平台兼容在 AOSP 中决定是否使用某些 vendor hooks 或者是否 fallback 某些功能
调试分析蓝牙功能异常时用于判断是否为固件版本问题
日志可读性蓝牙连接日志中可以清晰显示 Controller 的版本与厂商,方便排查

3. aosp 中的例子

  
// system/gd/hci/controller.ccstruct Controller::impl {void Start(hci::HciLayer* hci) {
...hci_->EnqueueCommand(ReadLocalVersionInformationBuilder::Create(),handler->BindOnceOn(this, &Controller::impl::read_local_version_information_complete_handler));...
}

在 Controller::impl::Start 函数中,我们会获取 本地蓝牙控制器的版本信息。
当我们获取到内容后,回调 read_local_version_information_complete_handler

1. read_local_version_information_complete_handler


// system/gd/hci/controller.ccvoid read_local_version_information_complete_handler(CommandCompleteView view) {auto complete_view = ReadLocalVersionInformationCompleteView::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_version_information_ = complete_view.GetLocalVersionInformation();bluetooth::os::LogMetricBluetoothLocalVersions(local_version_information_.manufacturer_name_,static_cast<uint8_t>(local_version_information_.lmp_version_),local_version_information_.lmp_subversion_,static_cast<uint8_t>(local_version_information_.hci_version_),local_version_information_.hci_revision_);}
  • 最终将 controller 获取到的版本信息,保存在 local_version_information_ 中。
LocalVersionInformation Controller::GetLocalVersionInformation() const {return impl_->local_version_information_;
}
  • 通过 Controller::GetLocalVersionInformation 来获取版本信息

看看如何使用

// system/main/shim/controller.cc
static const char GD_CONTROLLER_MODULE[] = "gd_controller_module";EXPORT_SYMBOL extern const module_t gd_controller_module = {.name = GD_CONTROLLER_MODULE,.start_up = start_up, // 这里};static future_t* start_up(void) {LOG_INFO("%s Starting up", __func__);data_.ready = true;if (gd_rust_is_enabled()) {} else {// 获取 mac 地址std::string string_address = GetController()->GetMacAddress().ToString();RawAddress::FromString(string_address, data_.raw_address);data_.le_supported_states =bluetooth::shim::GetController()->GetLeSupportedStates();// 获取 localVersionInfoauto local_version_info =bluetooth::shim::GetController()->GetLocalVersionInformation();data_.bt_version.hci_version =static_cast<uint8_t>(local_version_info.hci_version_);data_.bt_version.hci_revision = local_version_info.hci_revision_;data_.bt_version.lmp_version =static_cast<uint8_t>(local_version_info.lmp_version_);data_.bt_version.lmp_subversion = local_version_info.lmp_subversion_;data_.bt_version.manufacturer = local_version_info.manufacturer_name_;LOG_INFO("Mac address:%s", string_address.c_str());}

在 gd_controller_module 模块的 start_up 函数中,我们会将 local version info 信息放置在 data_.bt_version 中

// system/main/shim/controller.cc
static const RawAddress* get_address(void) { return &data_.raw_address; }static const bt_version_t* get_bt_version(void) { return &data_.bt_version; }

2. 使用案例

1. BTM_SetBleDataLength
// system/stack/btm/btm_ble.cc
tBTM_STATUS BTM_SetBleDataLength(const RawAddress& bd_addr,uint16_t tx_pdu_length) {
...if (controller_get_interface()->get_bt_version()->hci_version >=HCI_PROTO_VERSION_5_0)tx_time = BTM_BLE_DATA_TX_TIME_MAX;...}

根据 hci_version 来调整 ble 数据发送最大时间。

2.BTM_CreateSco
// system/stack/btm/btm_sco.cctBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig,uint16_t pkt_types, uint16_t* p_sco_inx,tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) {...if (controller_get_interface()->get_bt_version()->hci_version >=HCI_PROTO_VERSION_2_0) {p_setup->packet_types |=(pkt_types & BTM_SCO_EXCEPTION_PKTS_MASK) |(btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK);}
...
}
3.l2cu_set_acl_priority 和 l2cu_set_acl_latency
// system/stack/l2cap/l2c_utils.cc
bool l2cu_set_acl_priority(const RawAddress& bd_addr, tL2CAP_PRIORITY priority,bool reset_after_rs) {...if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||(reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {/* Use vendor specific commands to set the link priority */switch (controller_get_interface()->get_bt_version()->manufacturer) {case LMP_COMPID_BROADCOM:l2cu_set_acl_priority_latency_brcm(p_lcb, priority);break;case LMP_COMPID_SYNAPTICS:l2cu_set_acl_priority_syna(p_lcb->Handle(), priority);break;default:/* Not supported/required for other vendors */break;}}...
}bool l2cu_set_acl_latency(const RawAddress& bd_addr, tL2CAP_LATENCY latency) {
.../* only change controller's latency when stream using latency mode */if (p_lcb->use_latency_mode && p_lcb->is_high_priority() &&latency != p_lcb->acl_latency) {switch (controller_get_interface()->get_bt_version()->manufacturer) {case LMP_COMPID_BROADCOM:l2cu_set_acl_latency_brcm(p_lcb, latency);break;default:/* Not supported/required for other vendors */break;}p_lcb->set_latency(latency);}
...
}

根据不同的厂商做不同的处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/83805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React底层架构深度解析:从虚拟DOM到Fiber的演进之路

一、虚拟DOM&#xff1a;性能优化的基石 1.1 核心工作原理 React通过JSX语法将组件转换为轻量级JavaScript对象&#xff08;即虚拟DOM&#xff09;&#xff0c;而非直接操作真实DOM。这一过程由React.createElement()实现&#xff0c;其结构包含元素类型、属性和子节点等信息&a…

从AlphaGo到ChatGPT:AI技术如何一步步改变世界?

从AlphaGo到ChatGPT&#xff1a;AI技术如何一步步改变世界&#xff1f; 这里给大家分享一个人工智能学习网站。点击跳转到网站。 https://www.captainbed.cn/ccc 前言 在科技发展的历史长河中&#xff0c;人工智能&#xff08;AI&#xff09;技术无疑是最为璀璨的明珠之一。从…

关于在Unity项目中使用Post Processing插件打包到web端出现的问题

关于在Unity项目中使用Post Processing插件打包到web端出现的问题 解决方法&#xff1a;是不激活摄像机上的Post Processing有关组件&#xff0c;拉低场景中的Directional Light平行光的强度进行web端打包。 &#xff08;烘焙灯光时是可以激活。&#xff09; web端支持这个Pos…

MySQL - 如何突破单库性能瓶颈

数据库服务器硬件优化 我们来看看对数据库所在的服务器是如何进行优化的&#xff0c;服务器是数据库的宿主&#xff0c;其性能直接影响了数据库的性能&#xff0c;所以服务器的优化也是数据库优化的第一步。 数据库服务器通常是从 CPU、内存、磁盘三个角度进行硬件优化的&…

用 CodeBuddy 搭建「MiniGoal 小目标打卡器」:一次流畅的 UniApp 开发体验

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 在日常生活中&#xff0c;我们总是希望能够坚持一些小习惯&#xff0c;比如每天锻炼十分钟、读一页书、早睡十分…

OpenCV 环境搭建与概述

// //OpenCV-4.11.0 C VS2019 // 一、OpenCV学习路线 1、入门: OpenCV图像读写、视频读写、基本像素处理、基本卷积处理、基本C开发知识。 2、初级: OpenCV自定义卷积操作、图像梯度、边缘提取、二值分析、视频分析、形态学处理、几何变换与透视变换。 3、中级: 角点查找、BL…

如何快速更换电脑浏览器ip:教程与注意事项

无论是为了访问地域限制内容、保护隐私&#xff0c;还是解决网络问题&#xff0c;快速更换浏览器IP地址的需求日益增多。以下是快速更换电脑浏览器IP地址的几种常用方法及注意事项&#xff0c;结合了多种场景下的解决方案&#xff1a; 一、快速更换浏览器IP的方法 1. 代理服务…

【kafka】kafka概念,使用技巧go示例

1. Kafka基础概念 1.1 什么是Kafka&#xff1f; Kafka是一个分布式流处理平台&#xff0c;用于构建实时数据管道和流式应用。核心特点&#xff1a; 高吞吐量&#xff1a;每秒可处理百万级消息持久化存储&#xff1a;消息按Topic分区存储在磁盘分布式架构&#xff1a;支持水平…

掌握Git:版本控制与高效协作指南

一、初始Git 提出问题&#xff1a;无论是在工作还是学习&#xff0c;我们在编写各种文档的时候&#xff0c;更改失误&#xff0c;失误后恢复到原来版本&#xff0c;不得不复制出一个副本。 每个版本由各自的内容&#xff0c;但最终只有一个报告需要被我们使用。 但在此之前的…

【生活相关-日语-日本-东京-搬家后-引越(ひっこし)(3)-踩坑点:国民健康保险】

【生活相关-日语-日本-东京-搬家后-引越&#xff08;ひっこし&#xff09;&#xff08;3&#xff09;-注意点&#xff1a;国民健康保险】 1、前言2、情况说明&#xff08;1&#xff09;问题说明&#xff08;2&#xff09;情况说明&#xff08;1&#xff09;收到情况&#xff08…

linux——mysql故障排查与生产环境优化

目录 一&#xff0c;mysql数据库常见的故障 1&#xff0c;故障现象1 2&#xff0c;故障现象2 3&#xff0c;故障现象3 &#xff14;&#xff0c;故障现象&#xff14; &#xff15;&#xff0c;故障现象&#xff15; &#xff16;&#xff0c;故障现象&#xff16; 二&…

【C#】用 DevExpress 创建带“下拉子表”的参数表格视图

展示如何用 DevExpress 创建带“下拉子表”的参数表格视图。主表为 参数行 ParamRow&#xff0c;子表为 子项 ChildParam。 一、创建模型类 public class ParamRow {public string Pn { get; set; }public string DisplayName { get; set; }public string Value { get; set; }…

【JavaScript】用 Proxy 拦截对象属性

目录 一、Proxy 的基本结构&#xff08;打地基&#xff09; 二、最常用的两个拦截方法&#xff1a;get 和 set 1. get(target, key) 2. set(target, key, value) 三、说到这&#xff0c;那就可以回到题目来 四、什么是 Reflect&#xff1f; 总结不易&#xff0c;本章节对…

[IMX] 02.GPIO 寄存器

目录 手册对应章节 1.GPIO 复用&#xff08;引脚功能选择&#xff09;- IOMUXC_SW_MUX_CTL_PAD_xxx 2.GPIO 电气特性 - IOMUXC_SW_PAD_CTL_PAD_xxx 3.GPIO 数据与控制寄存器 3.1.数据 - DR 3.2.输入/输出选择 - GDIR 3.3.状态 - PSR 3.4.中断触发控制 - ICR 3.5.中断使…

Tomcat 配置 HTTPS 访问全攻略(CentOS 环境)

Tomcat 配置 HTTPS 访问全攻略&#xff08;CentOS 环境&#xff09; 一、环境说明 操作系统&#xff1a;CentOS Tomcat 版本&#xff1a;Apache Tomcat/9.0.105 服务器 IP&#xff1a;192.168.1.35 目标&#xff1a;将 Tomcat 默认的 HTTP 访问升级为 HTTPS&#xff0c;提…

Flink 运维监控与指标采集实战(Prometheus + Grafana 全流程)

一、引言:为什么 Flink 运维监控如此重要? 在实时计算场景中,Flink 作业 724 小时运行,对性能、资源、故障感知、状态变化的实时监控非常关键。没有有效的运维可观测体系: 不知道任务是否在稳定运行 发生问题难以快速定位 无法感知背压、延迟、反压等状态 因此,构建完善…

【prometheus+Grafana篇】基于Prometheus+Grafana实现Oracle数据库的监控与可视化

&#x1f4ab;《博主主页》&#xff1a; &#x1f50e; CSDN主页 &#x1f50e; IF Club社区主页 &#x1f525;《擅长领域》&#xff1a;擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(MongoDB)有了…

【数据仓库面试题合集③】实时数仓建模思路与实践详解

实时数据仓库已经成为各大企业构建核心指标监控与业务实时洞察的基础能力。面试中,关于实时建模的题目频繁出现,尤其聚焦于建模思路、宽表设计、状态管理、乱序处理等方面。本文整理典型题目及答题思路,帮助你应对相关考察。 一、建模原则与数仓分层认知 1. 实时数仓与离线…

鸿蒙PC操作系统:从Linux到自研微内核的蜕变

鸿蒙PC操作系统是否基于Linux内核,需要结合其技术架构、发展阶段和官方声明综合分析。以下从多个角度展开论述: 一、鸿蒙操作系统的多内核架构设计 多内核混合架构 根据资料,鸿蒙操作系统(HarmonyOS)采用分层多内核架构,内核层包含Linux内核、LiteOS-m内核、LiteOS-a内核…

LabVIEW数据库使用说明

介绍LabVIEW如何在数据库中插入记录以及执行 SQL 查询&#xff0c;适用于对数据库进行数据管理和操作的场景。借助 Database Connectivity Toolkit&#xff0c;可便捷地与指定数据库交互。 各 VI 功能详述 左侧 VI 功能概述&#xff1a;实现向数据库表中插入数据的操作。当输入…