经典蓝牙(BR/EDR)核心流程详解:设备发现、连接建立、配对绑定与服务发现

文章目录

  • 一、经典蓝牙协议栈概览
  • 二、设备发现流程
    • [2.1 发现过程涉及的角色](#2.1 发现过程涉及的角色)
    • [2.2 查询的两个阶段](#2.2 查询的两个阶段)
    • [2.3 关键 HCI 命令与事件](#2.3 关键 HCI 命令与事件)
    • [2.4 设备发现流程图](#2.4 设备发现流程图)
    • [2.5 发现结果的关键字段解析](#2.5 发现结果的关键字段解析)
    • [2.6 发现的底层细节(跳频机制)](#2.6 发现的底层细节(跳频机制))
  • 三、连接建立流程
    • [3.1 Paging 的核心原理](#3.1 Paging 的核心原理)
    • [3.2 连接建立步骤](#3.2 连接建立步骤)
    • [3.3 连接建立详细流程图](#3.3 连接建立详细流程图)
    • [3.4 连接过程中的 LMP 协商细节](#3.4 连接过程中的 LMP 协商细节)
    • [3.5 连接建立的时序图](#3.5 连接建立的时序图)
    • [3.6 与 BLE 对比(开发提示)](#3.6 与 BLE 对比(开发提示))
  • 四、配对与绑定
    • [4.1 核心概念](#4.1 核心概念)
    • [4.2 两种配对模式](#4.2 两种配对模式)
      • [4.2.1 Legacy Pairing(传统配对,蓝牙 2.0 及以前)](#4.2.1 Legacy Pairing(传统配对,蓝牙 2.0 及以前))
      • [4.2.2 Secure Simple Pairing(SSP,蓝牙 2.1+)](#4.2.2 Secure Simple Pairing(SSP,蓝牙 2.1+))
    • [4.3 配对与绑定完整流程图(SSP 为主)](#4.3 配对与绑定完整流程图(SSP 为主))
    • [4.4 认证(Authentication)的质询-响应细节](#4.4 认证(Authentication)的质询-响应细节)
    • [4.5 绑定的数据存储结构](#4.5 绑定的数据存储结构)
  • 五、服务发现流程
    • [5.1 SDP 的基本模型](#5.1 SDP 的基本模型)
    • [5.2 SDP 查询的两种方式](#5.2 SDP 查询的两种方式)
    • [5.3 服务发现详细流程图](#5.3 服务发现详细流程图)
    • [5.4 SDP 时序图](#5.4 SDP 时序图)
    • [5.5 常见 Profile 的 SDP 查询结果示例](#5.5 常见 Profile 的 SDP 查询结果示例)
  • 六、四大流程的完整时序串联
  • 七、开发常见问题与调试要点
    • [7.1 各流程常见失败点速查](#7.1 各流程常见失败点速查)
    • [7.2 流程间状态依赖关系](#7.2 流程间状态依赖关系)
    • [7.3 核心要点回顾](#7.3 核心要点回顾)

一、经典蓝牙协议栈概览

在深入各流程之前,先明确经典蓝牙协议栈的分层结构,这是理解后续所有流程的基础:
#mermaid-svg-ExQfsCxOiZY50d5U{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ExQfsCxOiZY50d5U .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ExQfsCxOiZY50d5U .error-icon{fill:#552222;}#mermaid-svg-ExQfsCxOiZY50d5U .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ExQfsCxOiZY50d5U .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ExQfsCxOiZY50d5U .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ExQfsCxOiZY50d5U .marker.cross{stroke:#333333;}#mermaid-svg-ExQfsCxOiZY50d5U svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ExQfsCxOiZY50d5U p{margin:0;}#mermaid-svg-ExQfsCxOiZY50d5U .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ExQfsCxOiZY50d5U .cluster-label text{fill:#333;}#mermaid-svg-ExQfsCxOiZY50d5U .cluster-label span{color:#333;}#mermaid-svg-ExQfsCxOiZY50d5U .cluster-label span p{background-color:transparent;}#mermaid-svg-ExQfsCxOiZY50d5U .label text,#mermaid-svg-ExQfsCxOiZY50d5U span{fill:#333;color:#333;}#mermaid-svg-ExQfsCxOiZY50d5U .node rect,#mermaid-svg-ExQfsCxOiZY50d5U .node circle,#mermaid-svg-ExQfsCxOiZY50d5U .node ellipse,#mermaid-svg-ExQfsCxOiZY50d5U .node polygon,#mermaid-svg-ExQfsCxOiZY50d5U .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ExQfsCxOiZY50d5U .rough-node .label text,#mermaid-svg-ExQfsCxOiZY50d5U .node .label text,#mermaid-svg-ExQfsCxOiZY50d5U .image-shape .label,#mermaid-svg-ExQfsCxOiZY50d5U .icon-shape .label{text-anchor:middle;}#mermaid-svg-ExQfsCxOiZY50d5U .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ExQfsCxOiZY50d5U .rough-node .label,#mermaid-svg-ExQfsCxOiZY50d5U .node .label,#mermaid-svg-ExQfsCxOiZY50d5U .image-shape .label,#mermaid-svg-ExQfsCxOiZY50d5U .icon-shape .label{text-align:center;}#mermaid-svg-ExQfsCxOiZY50d5U .node.clickable{cursor:pointer;}#mermaid-svg-ExQfsCxOiZY50d5U .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ExQfsCxOiZY50d5U .arrowheadPath{fill:#333333;}#mermaid-svg-ExQfsCxOiZY50d5U .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ExQfsCxOiZY50d5U .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ExQfsCxOiZY50d5U .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ExQfsCxOiZY50d5U .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ExQfsCxOiZY50d5U .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ExQfsCxOiZY50d5U .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ExQfsCxOiZY50d5U .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ExQfsCxOiZY50d5U .cluster text{fill:#333;}#mermaid-svg-ExQfsCxOiZY50d5U .cluster span{color:#333;}#mermaid-svg-ExQfsCxOiZY50d5U div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ExQfsCxOiZY50d5U .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ExQfsCxOiZY50d5U rect.text{fill:none;stroke-width:0;}#mermaid-svg-ExQfsCxOiZY50d5U .icon-shape,#mermaid-svg-ExQfsCxOiZY50d5U .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ExQfsCxOiZY50d5U .icon-shape p,#mermaid-svg-ExQfsCxOiZY50d5U .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ExQfsCxOiZY50d5U .icon-shape .label rect,#mermaid-svg-ExQfsCxOiZY50d5U .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ExQfsCxOiZY50d5U .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ExQfsCxOiZY50d5U .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ExQfsCxOiZY50d5U :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 控制器层 (Host Controller Interface 之下)
核心协议层
Profile 层
应用层
Profile 应用

A2DP / HFP / SPP / AVRCP
A2DP
HFP/HSP
SPP
AVRCP
SDP

服务发现协议
RFCOMM

串口仿真
L2CAP

逻辑链路控制与适配
AVDTP / AVCTP
HCI 主机控制接口
Baseband 基带
Link Manager 链路管理器 LM/LMP
Radio 射频 2.4GHz

关键概念:

概念 说明
Inquiry(查询) 设备发现机制,通过广播/响应方式找到周围设备
Paging(寻呼) 连接建立机制,主设备主动呼叫从设备
ACL 链路 异步无连接链路,承载数据传输(L2CAP 走 ACL)
SCO/eSCO 链路 同步链路,承载语音(HFP 走 SCO/eSCO)
Pairing(配对) 交换密钥、完成认证的过程
Bonding(绑定) 将配对结果(Link Key)持久化存储
SDP 服务发现协议,查询对端支持哪些服务及连接参数
LMP 链路管理协议,负责链路建立、认证、加密协商等

二、设备发现流程

设备发现的核心是 Inquiry(查询)过程。经典蓝牙设备默认不会被"直接看见",需要通过 Inquiry 扫描来交换设备地址、时钟、设备类别等基本信息。

2.1 发现过程涉及的角色

  • Inquirer(查询方 / 主设备候选):发起查询,寻找周围设备。
  • Inquiry Scanner(被查询方):周期性监听 Inquiry 广播并回复的设备。

2.2 查询的两个阶段

  1. Inquiry(查询):查询方发送 ID 包(含 GIAC 通用查询访问码),被查询方返回 FHS 包(包含 BD_ADDR、时钟、设备类型等信息)。
  2. Inquiry Response(查询响应) :被查询方在跳频序列上回应,查询方收集响应结果,随后通常还会执行 RSSI 读取(通过 HCI_Read_RSSI)获取信号强度。

2.3 关键 HCI 命令与事件

方向 HCI 指令/事件 作用
Host → Controller HCI_Inquiry 启动查询,可指定 LAP(GIAC/LIAC)、查询时长
Controller → Host HCI_Inquiry_Result / HCI_Inquiry_Result_With_RSSI / HCI_Extended_Inquiry_Result (EIR) 返回发现的设备信息(地址、CoD、RSSI、设备名称等)
Host → Controller HCI_Inquiry_Cancel 提前终止查询
Controller → Host HCI_Inquiry_Complete 查询完成事件

EIR(Extended Inquiry Response):允许被查询方在响应中附带更多数据(如设备名称、支持的 UUID 列表、厂商自定义数据),减少后续连接后再读取的次数。

2.4 设备发现流程图

#mermaid-svg-5uqQwjyJvTepDP7D{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5uqQwjyJvTepDP7D .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5uqQwjyJvTepDP7D .error-icon{fill:#552222;}#mermaid-svg-5uqQwjyJvTepDP7D .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5uqQwjyJvTepDP7D .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5uqQwjyJvTepDP7D .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5uqQwjyJvTepDP7D .marker.cross{stroke:#333333;}#mermaid-svg-5uqQwjyJvTepDP7D svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5uqQwjyJvTepDP7D p{margin:0;}#mermaid-svg-5uqQwjyJvTepDP7D .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5uqQwjyJvTepDP7D .cluster-label text{fill:#333;}#mermaid-svg-5uqQwjyJvTepDP7D .cluster-label span{color:#333;}#mermaid-svg-5uqQwjyJvTepDP7D .cluster-label span p{background-color:transparent;}#mermaid-svg-5uqQwjyJvTepDP7D .label text,#mermaid-svg-5uqQwjyJvTepDP7D span{fill:#333;color:#333;}#mermaid-svg-5uqQwjyJvTepDP7D .node rect,#mermaid-svg-5uqQwjyJvTepDP7D .node circle,#mermaid-svg-5uqQwjyJvTepDP7D .node ellipse,#mermaid-svg-5uqQwjyJvTepDP7D .node polygon,#mermaid-svg-5uqQwjyJvTepDP7D .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5uqQwjyJvTepDP7D .rough-node .label text,#mermaid-svg-5uqQwjyJvTepDP7D .node .label text,#mermaid-svg-5uqQwjyJvTepDP7D .image-shape .label,#mermaid-svg-5uqQwjyJvTepDP7D .icon-shape .label{text-anchor:middle;}#mermaid-svg-5uqQwjyJvTepDP7D .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5uqQwjyJvTepDP7D .rough-node .label,#mermaid-svg-5uqQwjyJvTepDP7D .node .label,#mermaid-svg-5uqQwjyJvTepDP7D .image-shape .label,#mermaid-svg-5uqQwjyJvTepDP7D .icon-shape .label{text-align:center;}#mermaid-svg-5uqQwjyJvTepDP7D .node.clickable{cursor:pointer;}#mermaid-svg-5uqQwjyJvTepDP7D .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5uqQwjyJvTepDP7D .arrowheadPath{fill:#333333;}#mermaid-svg-5uqQwjyJvTepDP7D .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5uqQwjyJvTepDP7D .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5uqQwjyJvTepDP7D .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5uqQwjyJvTepDP7D .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5uqQwjyJvTepDP7D .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5uqQwjyJvTepDP7D .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5uqQwjyJvTepDP7D .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5uqQwjyJvTepDP7D .cluster text{fill:#333;}#mermaid-svg-5uqQwjyJvTepDP7D .cluster span{color:#333;}#mermaid-svg-5uqQwjyJvTepDP7D div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5uqQwjyJvTepDP7D .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5uqQwjyJvTepDP7D rect.text{fill:none;stroke-width:0;}#mermaid-svg-5uqQwjyJvTepDP7D .icon-shape,#mermaid-svg-5uqQwjyJvTepDP7D .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5uqQwjyJvTepDP7D .icon-shape p,#mermaid-svg-5uqQwjyJvTepDP7D .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5uqQwjyJvTepDP7D .icon-shape .label rect,#mermaid-svg-5uqQwjyJvTepDP7D .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5uqQwjyJvTepDP7D .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5uqQwjyJvTepDP7D .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5uqQwjyJvTepDP7D :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
是
否
否
是
被查询设备侧 (Inquiry Scanner)
是
周期性进入 Inquiry Scan 状态

监听 GIAC 广播
收到 ID 包?
延迟 0~1023 个 slot 后回应 FHS 包

避免多设备同时响应冲突
可选: 携带 EIR 扩展查询响应

包含设备名/UUID列表
Host 应用层: 启动设备发现
Host 发送 HCI_Inquiry 命令

参数: LAP=GIAC 通用查询访问码

Inquiry_Length=10.24s 查询时长

Num_Responses=0 不限数量
Controller 返回

HCI_Command_Complete?
Controller 进入 Inquiry 状态

按 Inquiry 跳频序列发送 ID 广播包
收到某设备 FHS 包
Controller 上报

HCI_Inquiry_Result_With_RSSI 事件

BD_ADDR + Class of Device + RSSI
还有新设备响应?
查询时长结束?

或达到 Num_Responses?
Controller 上报 HCI_Inquiry_Complete
Host 读取设备名称

可选: HCI_Remote_Name_Request

2.5 发现结果的关键字段解析

以 HCI_Inquiry_Result_With_RSSI 事件为例,每个发现条目包含:

  • BD_ADDR(48 位蓝牙地址) :设备唯一标识。地址类型分为 00:xx(Public)、40:xx(Random Static)等,经典蓝牙主要使用 Public 地址。
  • Page_Scan_Repetition_Mode(PSRM):对端寻呼扫描的重复模式,影响后续 Paging 的调度策略。
  • Class of Device(CoD,设备类别):24 位字段,指示设备类型(手机、耳机、电脑、音频设备等)及服务类别(Audio、Rendering、Networking 等),应用层可据此过滤目标设备。
  • Clock_Offset :对端本地时钟与查询方时钟的偏移,用于加速后续 Paging 过程。
  • RSSI:信号强度,用于距离估计与排序。

2.6 发现的底层细节(跳频机制)

被查询方 (Scanner) 查询方 (Inquirer) 被查询方 (Scanner) 查询方 (Inquirer) #mermaid-svg-IxAsbJeD7eRjqyCr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IxAsbJeD7eRjqyCr .error-icon{fill:#552222;}#mermaid-svg-IxAsbJeD7eRjqyCr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IxAsbJeD7eRjqyCr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IxAsbJeD7eRjqyCr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IxAsbJeD7eRjqyCr .marker.cross{stroke:#333333;}#mermaid-svg-IxAsbJeD7eRjqyCr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IxAsbJeD7eRjqyCr p{margin:0;}#mermaid-svg-IxAsbJeD7eRjqyCr .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-IxAsbJeD7eRjqyCr text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-IxAsbJeD7eRjqyCr .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-IxAsbJeD7eRjqyCr .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-IxAsbJeD7eRjqyCr #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-IxAsbJeD7eRjqyCr .sequenceNumber{fill:white;}#mermaid-svg-IxAsbJeD7eRjqyCr #sequencenumber{fill:#333;}#mermaid-svg-IxAsbJeD7eRjqyCr #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-IxAsbJeD7eRjqyCr .messageText{fill:#333;stroke:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-IxAsbJeD7eRjqyCr .labelText,#mermaid-svg-IxAsbJeD7eRjqyCr .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .loopText,#mermaid-svg-IxAsbJeD7eRjqyCr .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-IxAsbJeD7eRjqyCr .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-IxAsbJeD7eRjqyCr .noteText,#mermaid-svg-IxAsbJeD7eRjqyCr .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-IxAsbJeD7eRjqyCr .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-IxAsbJeD7eRjqyCr .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-IxAsbJeD7eRjqyCr .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-IxAsbJeD7eRjqyCr .actorPopupMenu{position:absolute;}#mermaid-svg-IxAsbJeD7eRjqyCr .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-IxAsbJeD7eRjqyCr .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-IxAsbJeD7eRjqyCr .actor-man circle,#mermaid-svg-IxAsbJeD7eRjqyCr line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-IxAsbJeD7eRjqyCr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 查询状态: 每 1.28s 切换 16 个跳频信道之一 loop 每个响应槽 (625μs slot) Inquiry Scan: 以较慢速率轮询监听信道 记录设备信息 + Clock_Offset 若支持 EIR, 随后还有扩展响应数据包 ID 包 (携带 GIAC 访问码) FHS 包 (BD_ADDR + CLK + CoD)

要点总结:

  • Inquiry 使用 32 个专用查询跳频信道,采用 A/B 双频段交替策略。
  • 被查询方的响应延迟是随机的(0~1023 slots),这是蓝牙规范的冲突避免机制。
  • 查询过程不建立连接,两个设备仍处于"未连接"状态。
  • 查询时长(Inquiry Length)典型值 10.24s,时长越长发现设备越完整,但功耗和时延越高。

三、连接建立流程

发现设备之后,主设备通过 Paging(寻呼) 过程与目标设备建立 ACL 链路。连接建立后才会进行认证、加密和服务访问。

3.1 Paging 的核心原理

Paging 利用在 Inquiry 阶段获取的 BD_ADDR 和 Clock_Offset:

  • 由 BD_ADDR 计算出目标设备的 Page 跳频序列(约 32 个信道)。
  • 由 Clock_Offset 推算对端当前使用的信道,从而加速锁定(约 2 个半时隙内可命中),否则退化为全信道轮询(最坏 10ms 以上)。

3.2 连接建立步骤

  1. 主设备发送 HCI_Create_Connection,携带 BD_ADDR、Packet_Type、Page_Scan_Repetition_Mode、Clock_Offset、Allow_Role_Switch 等参数。
  2. 控制器执行 Page:主设备在 Page 信道上发送 ID 包(含被叫设备的 Device Access Code, DAC)。
  3. 从设备在 Page Scan 状态收到 ID 包后回应 ID 包(携带相同 DAC)。
  4. 主设备发送 FHS 包,其中携带主设备的实时时钟和 BD_ADDR,用于从设备同步跳频序列。
  5. 从设备回应一个 ACK(NULL/POLL 包),至此 物理链路同步完成。
  6. 控制器上报 HCI_Connection_Complete 事件,Host 获得 Connection_Handle。
  7. 随后 LMP 层进行链路参数协商(见 3.4)。

3.3 连接建立详细流程图

#mermaid-svg-tuiaMzbEe39nkvLw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tuiaMzbEe39nkvLw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tuiaMzbEe39nkvLw .error-icon{fill:#552222;}#mermaid-svg-tuiaMzbEe39nkvLw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tuiaMzbEe39nkvLw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tuiaMzbEe39nkvLw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tuiaMzbEe39nkvLw .marker.cross{stroke:#333333;}#mermaid-svg-tuiaMzbEe39nkvLw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tuiaMzbEe39nkvLw p{margin:0;}#mermaid-svg-tuiaMzbEe39nkvLw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tuiaMzbEe39nkvLw .cluster-label text{fill:#333;}#mermaid-svg-tuiaMzbEe39nkvLw .cluster-label span{color:#333;}#mermaid-svg-tuiaMzbEe39nkvLw .cluster-label span p{background-color:transparent;}#mermaid-svg-tuiaMzbEe39nkvLw .label text,#mermaid-svg-tuiaMzbEe39nkvLw span{fill:#333;color:#333;}#mermaid-svg-tuiaMzbEe39nkvLw .node rect,#mermaid-svg-tuiaMzbEe39nkvLw .node circle,#mermaid-svg-tuiaMzbEe39nkvLw .node ellipse,#mermaid-svg-tuiaMzbEe39nkvLw .node polygon,#mermaid-svg-tuiaMzbEe39nkvLw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tuiaMzbEe39nkvLw .rough-node .label text,#mermaid-svg-tuiaMzbEe39nkvLw .node .label text,#mermaid-svg-tuiaMzbEe39nkvLw .image-shape .label,#mermaid-svg-tuiaMzbEe39nkvLw .icon-shape .label{text-anchor:middle;}#mermaid-svg-tuiaMzbEe39nkvLw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tuiaMzbEe39nkvLw .rough-node .label,#mermaid-svg-tuiaMzbEe39nkvLw .node .label,#mermaid-svg-tuiaMzbEe39nkvLw .image-shape .label,#mermaid-svg-tuiaMzbEe39nkvLw .icon-shape .label{text-align:center;}#mermaid-svg-tuiaMzbEe39nkvLw .node.clickable{cursor:pointer;}#mermaid-svg-tuiaMzbEe39nkvLw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tuiaMzbEe39nkvLw .arrowheadPath{fill:#333333;}#mermaid-svg-tuiaMzbEe39nkvLw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tuiaMzbEe39nkvLw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tuiaMzbEe39nkvLw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tuiaMzbEe39nkvLw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tuiaMzbEe39nkvLw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tuiaMzbEe39nkvLw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tuiaMzbEe39nkvLw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tuiaMzbEe39nkvLw .cluster text{fill:#333;}#mermaid-svg-tuiaMzbEe39nkvLw .cluster span{color:#333;}#mermaid-svg-tuiaMzbEe39nkvLw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tuiaMzbEe39nkvLw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tuiaMzbEe39nkvLw rect.text{fill:none;stroke-width:0;}#mermaid-svg-tuiaMzbEe39nkvLw .icon-shape,#mermaid-svg-tuiaMzbEe39nkvLw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tuiaMzbEe39nkvLw .icon-shape p,#mermaid-svg-tuiaMzbEe39nkvLw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tuiaMzbEe39nkvLw .icon-shape .label rect,#mermaid-svg-tuiaMzbEe39nkvLw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tuiaMzbEe39nkvLw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tuiaMzbEe39nkvLw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tuiaMzbEe39nkvLw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} LMP 链路协商阶段
Paging 物理层同步
已有
无
超时未响应
收到响应
是
否
Host: 请求连接某设备
HCI_Create_Connection

BD_ADDR + Clock_Offset

  • Page_Scan_Repetition_Mode

  • Allow_Role_Switch
    Controller: 是否已有到该设备的链路?
    直接返回已有 Connection_Handle

流程结束
进入 Page 状态

根据 BD_ADDR 计算 Page 跳频序列
发送 ID 包 含目标 DAC 访问码
从设备在 Page Scan

收到并回 ID 包?
重试 / 退避

重新 Page
主设备发送 FHS 包

携带主设备实时 CLK + BD_ADDR
从设备 ACK 确认

双方跳频序列同步完成
上报 HCI_Connection_Complete

获得 Connection_Handle

ACL 链路建立
LMP 交换: 版本/特性协商

LMP_version_req/res
LMP 协商: 加密模式

LMP_encryption_mode_req
LMP 协商: 时钟偏移/槽偏移

LMP_slot_offset + LMP_timing_accuracy
LMP 请求: 改变链路角色?

LMP_switch_req

主从切换
LMP 设置: 链路监督超时

LMP_supervision_timeout
Host 是否要求认证+加密?
进入认证流程

见第四章
链路就绪

可进行 L2CAP 数据交互

3.4 连接过程中的 LMP 协商细节

ACL 链路建立后,Link Manager 之间自动进行以下 LMP 过程(Host 无需介入):

LMP 过程 内容 说明
LMP_version_req/res 蓝牙版本、公司标识 确定双方支持的特性
LMP_features_req/res 特性掩码(加密、EIR、BR/EDR、5-slot 包等) 决定后续能力
LMP_name_req/res 设备名称 可在 ACL 建立后补读名称
LMP_encryption_mode_req 加密模式(不加密/仅点对点/点对点+广播) 通常要求先认证
LMP_encryption_key_size_req 密钥长度(7~16 字节) 经典蓝牙 legacy 配对密钥可协商
LMP_switch_req 主从角色切换 连接发起方不一定是最终 Master
LMP_supervision_timeout 链路监督超时(0.625ms~32s) 超时未收到包则断开,用于死链检测

3.5 连接建立的时序图

Slave Host Master Host Slave (被叫方) Master (发起方) Slave Host Master Host Slave (被叫方) Master (发起方) #mermaid-svg-kGOciiyFLSrgEGl8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kGOciiyFLSrgEGl8 .error-icon{fill:#552222;}#mermaid-svg-kGOciiyFLSrgEGl8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kGOciiyFLSrgEGl8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kGOciiyFLSrgEGl8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kGOciiyFLSrgEGl8 .marker.cross{stroke:#333333;}#mermaid-svg-kGOciiyFLSrgEGl8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kGOciiyFLSrgEGl8 p{margin:0;}#mermaid-svg-kGOciiyFLSrgEGl8 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kGOciiyFLSrgEGl8 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-kGOciiyFLSrgEGl8 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-kGOciiyFLSrgEGl8 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-kGOciiyFLSrgEGl8 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-kGOciiyFLSrgEGl8 .sequenceNumber{fill:white;}#mermaid-svg-kGOciiyFLSrgEGl8 #sequencenumber{fill:#333;}#mermaid-svg-kGOciiyFLSrgEGl8 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-kGOciiyFLSrgEGl8 .messageText{fill:#333;stroke:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kGOciiyFLSrgEGl8 .labelText,#mermaid-svg-kGOciiyFLSrgEGl8 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .loopText,#mermaid-svg-kGOciiyFLSrgEGl8 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-kGOciiyFLSrgEGl8 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-kGOciiyFLSrgEGl8 .noteText,#mermaid-svg-kGOciiyFLSrgEGl8 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-kGOciiyFLSrgEGl8 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kGOciiyFLSrgEGl8 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kGOciiyFLSrgEGl8 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-kGOciiyFLSrgEGl8 .actorPopupMenu{position:absolute;}#mermaid-svg-kGOciiyFLSrgEGl8 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-kGOciiyFLSrgEGl8 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-kGOciiyFLSrgEGl8 .actor-man circle,#mermaid-svg-kGOciiyFLSrgEGl8 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-kGOciiyFLSrgEGl8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Page 状态: 32 信道跳频寻呼 物理同步完成, 进入 Connection 状态 LMP 自动协商 ACL 链路就绪, Connection_Handle 分配 HCI_Create_Connection(BD_ADDR, CLK_offset) ID 包 (DAC) ID 包 (DAC) 响应 FHS 包 (含 Master CLK, BD_ADDR) POLL/NULL (ACK) HCI_Connection_Complete HCI_Connection_Complete LMP_version_req LMP_version_res LMP_features_req LMP_features_res LMP_encryption_mode_req LMP_accepted

3.6 与 BLE 对比(开发提示)

  • 经典蓝牙 Paging 是定向快速连接(利用时钟偏移加速),而 BLE 是周期性广播+扫描窗口机制。
  • 经典蓝牙连接建立时间典型为 < 100ms(已知时钟偏移时更快),BLE 取决于广播间隔,通常为几十到几百 ms。

四、配对与绑定

配对(Pairing)解决认证与密钥生成 问题;绑定(Bonding)解决密钥持久化 问题。经典蓝牙的配对由 LMP 认证 + LMP 配对过程完成。

4.1 核心概念

概念 说明
Link Key 链路密钥,双方共享的 128 位密钥,是配对的核心产物
PIN Code 传统配对(Legacy Pairing)中用户输入的密码(4~16 位数字/字符)
Simple Pairing (SSP) 蓝牙 2.1+ 引入的安全简单配对,支持 Numeric Comparison、Passkey Entry、Just Works、Out-of-Band (OOB) 四种模式
Authentication 基于 Link Key 的质询-响应(Challenge-Response),每次连接都会执行
Bonding 将 Link Key 写入双方 Flash(NVRAM)的持久化动作
Encryption 基于认证后的 Cipher Key(由 Link Key 派生:E3 算法)对 ACL 载荷加密

4.2 两种配对模式

4.2.1 Legacy Pairing(传统配对,蓝牙 2.0 及以前)

双方由 PIN 码生成 Init/Comb Key:
#mermaid-svg-DJJ8ktxGraUZ3Xf8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .error-icon{fill:#552222;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .marker.cross{stroke:#333333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 p{margin:0;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster-label text{fill:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster-label span{color:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster-label span p{background-color:transparent;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .label text,#mermaid-svg-DJJ8ktxGraUZ3Xf8 span{fill:#333;color:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node rect,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node circle,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node ellipse,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node polygon,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .rough-node .label text,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node .label text,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .image-shape .label,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .rough-node .label,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node .label,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .image-shape .label,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .icon-shape .label{text-align:center;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node.clickable{cursor:pointer;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .arrowheadPath{fill:#333333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster text{fill:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .cluster span{color:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .icon-shape,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .icon-shape p,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .icon-shape .label rect,#mermaid-svg-DJJ8ktxGraUZ3Xf8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DJJ8ktxGraUZ3Xf8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
双方输入相同 PIN Code
各自计算:

E21 算法基于 PIN + 对方地址

生成 Initialization Key K_init
交换随机数 RAND 与质询
计算 Comb Key

K_link = E21 K_init, RAND, BD_ADDR
得到最终 Link Key
执行 LMP 认证质询-响应

验证双方密钥一致
认证通过?
配对成功, 进入绑定/加密
配对失败: PIN 错误或超时

缺点:PIN 短则安全性弱(易受暴力破解);无用户界面设备(耳机)只能用固定 PIN(如 0000/1234),安全性差。因此蓝牙 2.1 引入 SSP。

4.2.2 Secure Simple Pairing(SSP,蓝牙 2.1+)

SSP 基于 Diffie-Hellman(使用 P-192 椭圆曲线或 P-256,取决于 Secure Connections),核心流程为四个阶段:

  1. Public Key Exchange:交换公钥。
  2. Authentication Stage 1:根据 IO Capability 选择四种模式之一完成用户确认。
  3. Authentication Stage 2:双方确认 DH Key 一致(通过 Nonce 校验)。
  4. Link Key Calculation:由 DH Key 派生 Link Key。

四种关联模型:

模式 IO 要求 中间人防护 适用场景
Numeric Comparison 双方均有显示 有 手机-电脑
Passkey Entry 一方显示一方输入 有 手机-键盘
Just Works 无显示无输入 无 耳机、音箱(仅抗被动窃听)
Out-of-Band (OOB) 通过 NFC/其他通道交换 有 NFC 辅助配对

4.3 配对与绑定完整流程图(SSP 为主)

#mermaid-svg-pOsRkRNTG9JjFsQv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pOsRkRNTG9JjFsQv .error-icon{fill:#552222;}#mermaid-svg-pOsRkRNTG9JjFsQv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pOsRkRNTG9JjFsQv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pOsRkRNTG9JjFsQv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pOsRkRNTG9JjFsQv .marker.cross{stroke:#333333;}#mermaid-svg-pOsRkRNTG9JjFsQv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pOsRkRNTG9JjFsQv p{margin:0;}#mermaid-svg-pOsRkRNTG9JjFsQv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster-label text{fill:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster-label span{color:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster-label span p{background-color:transparent;}#mermaid-svg-pOsRkRNTG9JjFsQv .label text,#mermaid-svg-pOsRkRNTG9JjFsQv span{fill:#333;color:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv .node rect,#mermaid-svg-pOsRkRNTG9JjFsQv .node circle,#mermaid-svg-pOsRkRNTG9JjFsQv .node ellipse,#mermaid-svg-pOsRkRNTG9JjFsQv .node polygon,#mermaid-svg-pOsRkRNTG9JjFsQv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pOsRkRNTG9JjFsQv .rough-node .label text,#mermaid-svg-pOsRkRNTG9JjFsQv .node .label text,#mermaid-svg-pOsRkRNTG9JjFsQv .image-shape .label,#mermaid-svg-pOsRkRNTG9JjFsQv .icon-shape .label{text-anchor:middle;}#mermaid-svg-pOsRkRNTG9JjFsQv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pOsRkRNTG9JjFsQv .rough-node .label,#mermaid-svg-pOsRkRNTG9JjFsQv .node .label,#mermaid-svg-pOsRkRNTG9JjFsQv .image-shape .label,#mermaid-svg-pOsRkRNTG9JjFsQv .icon-shape .label{text-align:center;}#mermaid-svg-pOsRkRNTG9JjFsQv .node.clickable{cursor:pointer;}#mermaid-svg-pOsRkRNTG9JjFsQv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pOsRkRNTG9JjFsQv .arrowheadPath{fill:#333333;}#mermaid-svg-pOsRkRNTG9JjFsQv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pOsRkRNTG9JjFsQv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pOsRkRNTG9JjFsQv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pOsRkRNTG9JjFsQv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pOsRkRNTG9JjFsQv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pOsRkRNTG9JjFsQv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster text{fill:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv .cluster span{color:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pOsRkRNTG9JjFsQv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pOsRkRNTG9JjFsQv rect.text{fill:none;stroke-width:0;}#mermaid-svg-pOsRkRNTG9JjFsQv .icon-shape,#mermaid-svg-pOsRkRNTG9JjFsQv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pOsRkRNTG9JjFsQv .icon-shape p,#mermaid-svg-pOsRkRNTG9JjFsQv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pOsRkRNTG9JjFsQv .icon-shape .label rect,#mermaid-svg-pOsRkRNTG9JjFsQv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pOsRkRNTG9JjFsQv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pOsRkRNTG9JjFsQv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pOsRkRNTG9JjFsQv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 绑定 Bonding 阶段 (Host 可选)
SSP 配对阶段 (P0)
有
无
Numeric Comparison
Passkey Entry
Just Works
OOB
失败
通过
否
是
是
否
触发条件: ACL 建立后

Host 请求认证/加密

或访问受保护服务
发起方发送 LMP_in_rand

携带 128-bit 随机数 RAND
对端是否有双方

已绑定的 Link Key?
进入 Authentication

质询-响应阶段 D
进入配对 Pairing 流程
阶段1: 交换 IO Capability

LMP_IO_capability_req/res

决定关联模型
阶段2: 交换公钥

DH Key 协商开始
IO 决定关联模型
双方显示 6 位数字

用户确认一致
一方显示 6 位数字

另一方输入
无用户交互

自动继续
通过 NFC 等带外信道

交换确认数据
阶段3: 认证确认

校验 DH Key 一致

HMAC-SHA-256 Nonce
阶段4: 计算 Link Key

f5 函数派生
双方各自执行 LMP 认证:

验证方发 LMP_in_rand RAND

声称方用 Link Key 计算 SRES = E1 Key, RAND, BD_ADDR

回送 LMP_sres
SRES 校验通过?
上报 HCI_Authentication_Complete

Status = 错误 认证失败

可选重试/重新配对
Host 是否请求加密?

HCI_Set_Connection_Encryption
认证完成

可继续明文通信
LMP_encryption_mode_req

协商加密模式与密钥长度
基于 Link Key 派生 Cipher Key

E3: Kcipher = E3 LinkKey, RAND, COF
双方启用硬件加密引擎

ACL 载荷 AES 加密传输
Host 决定绑定?

HCI_Write_Stored_Link_Key
双方 Link Key + BD_ADDR

写入 NVRAM 持久化

后续连接免配对
Link Key 仅存内存

断链后失效
配对+认证+加密 完成

4.4 认证(Authentication)的质询-响应细节

每次连接建立后,只要访问受保护资源或双方要求加密,都会执行 LMP 认证。这一过程每次都执行,与是否已绑定无关:
Claimant 声称方 Verifier 验证方 (主动发起) Claimant 声称方 Verifier 验证方 (主动发起) #mermaid-svg-BsYybRkymG3KUgJI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BsYybRkymG3KUgJI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BsYybRkymG3KUgJI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BsYybRkymG3KUgJI .error-icon{fill:#552222;}#mermaid-svg-BsYybRkymG3KUgJI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BsYybRkymG3KUgJI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BsYybRkymG3KUgJI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BsYybRkymG3KUgJI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BsYybRkymG3KUgJI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BsYybRkymG3KUgJI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BsYybRkymG3KUgJI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BsYybRkymG3KUgJI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BsYybRkymG3KUgJI .marker.cross{stroke:#333333;}#mermaid-svg-BsYybRkymG3KUgJI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BsYybRkymG3KUgJI p{margin:0;}#mermaid-svg-BsYybRkymG3KUgJI .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-BsYybRkymG3KUgJI text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-BsYybRkymG3KUgJI .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-BsYybRkymG3KUgJI .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-BsYybRkymG3KUgJI .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-BsYybRkymG3KUgJI .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-BsYybRkymG3KUgJI #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-BsYybRkymG3KUgJI .sequenceNumber{fill:white;}#mermaid-svg-BsYybRkymG3KUgJI #sequencenumber{fill:#333;}#mermaid-svg-BsYybRkymG3KUgJI #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-BsYybRkymG3KUgJI .messageText{fill:#333;stroke:none;}#mermaid-svg-BsYybRkymG3KUgJI .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-BsYybRkymG3KUgJI .labelText,#mermaid-svg-BsYybRkymG3KUgJI .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-BsYybRkymG3KUgJI .loopText,#mermaid-svg-BsYybRkymG3KUgJI .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-BsYybRkymG3KUgJI .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-BsYybRkymG3KUgJI .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-BsYybRkymG3KUgJI .noteText,#mermaid-svg-BsYybRkymG3KUgJI .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-BsYybRkymG3KUgJI .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-BsYybRkymG3KUgJI .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-BsYybRkymG3KUgJI .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-BsYybRkymG3KUgJI .actorPopupMenu{position:absolute;}#mermaid-svg-BsYybRkymG3KUgJI .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-BsYybRkymG3KUgJI .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-BsYybRkymG3KUgJI .actor-man circle,#mermaid-svg-BsYybRkymG3KUgJI line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-BsYybRkymG3KUgJI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SRES = E1(Link Key, RAND, Claimant BD_ADDR) 本地同样计算 E1 结果并比较 认证通过 失败, 可触发重新配对 alt SRES 匹配 SRES 不匹配 LMP_in_rand (128-bit RAND) LMP_sres (32-bit SRES) LMP_accepted LMP_rejected (Authentication Failure)

4.5 绑定的数据存储结构

绑定信息在 Host 侧通常按如下结构存储:

复制代码
NVRAM 绑定记录(每设备一条):
┌─────────────────────────────────┐
│ BD_ADDR (6 bytes)               │
│ Link Key (16 bytes)             │
│ Key Type (4 bits):              │
│   - Combination Key             │
│   - Local Unit Key              │
│   - Remote Unit Key             │
│   - Debug Combination Key       │
│   - Unauthenticated Combination │
│     Key (Just Works 产生)       │
│   - Authenticated Combination   │
│     Key                         │
│ PIN Length (legacy, 1 byte)     │
│ 配对时使用的 IO Capabilities    │
│ 上次连接时间(应用层可选)       │
└─────────────────────────────────┘

开发提示:

  • 使用 HCI_Read_Stored_Link_Key / HCI_Write_Stored_Link_Key 管理绑定信息。
  • Just Works 模式 产生的 Key Type 是 Unauthenticated,意味着它不能用于要求 MITM 防护的场景(如某些 HID 键盘服务)。
  • 清除配对记录时要通知对端删除 (HCI_Delete_Stored_Link_Key + LMP),否则对端仍持有旧 Key,会导致下次连接认证失败。

五、服务发现流程

ACL 链路建立并(可选)完成认证加密后,应用层通常需要查询对端支持哪些 Profile 服务、使用哪个 L2CAP PSM、RFCOMM 通道号是多少 ------这就是 SDP(Service Discovery Protocol)。

5.1 SDP 的基本模型

  • SDP Server:运行于每个蓝牙设备上,维护一张服务记录表(Service Record)。
  • SDP Client:查询方,通过 L2CAP(PSM = 0x0001)与 Server 通信。
  • Service Record :由一系列 Attribute(属性) 组成,每个属性是 (Attribute ID, Attribute Value) 对,用 UUID 标识。

关键属性:

Attribute ID 名称 说明
0x0000 ServiceRecordHandle 记录句柄
0x0001 ServiceClassIDList 服务类 UUID 列表(核心)
0x0002 ServiceRecordState 记录状态(变更检测)
0x0004 ProtocolDescriptorList 协议栈描述(L2CAP PSM、RFCOMM 通道号等,核心)
0x0005 BrowseGroupList 浏览分组(PublicBrowseGroup = 0x1002)
0x0006 LanguageBaseAttributeIDList 语言基准
0x0009 BluetoothProfileDescriptorList Profile 描述(如 A2DP Sink UUID + 版本)
0x0100 ServiceName 服务名称

5.2 SDP 查询的两种方式

  1. Service Search(服务搜索):按 Service UUID 搜索,返回匹配记录的 Record Handle 列表。
  2. Service Attribute Retrieval(属性获取):按 Record Handle + Attribute ID 列表,提取具体属性(主要是 ProtocolDescriptorList 获取 PSM/通道号)。

实际中常组合为 Service Search Attribute Request(SSAR):一次性按 UUID 搜索并返回指定属性。

5.3 服务发现详细流程图

#mermaid-svg-8CEqiNFiyL0W1lIO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8CEqiNFiyL0W1lIO .error-icon{fill:#552222;}#mermaid-svg-8CEqiNFiyL0W1lIO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8CEqiNFiyL0W1lIO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8CEqiNFiyL0W1lIO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8CEqiNFiyL0W1lIO .marker.cross{stroke:#333333;}#mermaid-svg-8CEqiNFiyL0W1lIO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8CEqiNFiyL0W1lIO p{margin:0;}#mermaid-svg-8CEqiNFiyL0W1lIO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster-label text{fill:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster-label span{color:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster-label span p{background-color:transparent;}#mermaid-svg-8CEqiNFiyL0W1lIO .label text,#mermaid-svg-8CEqiNFiyL0W1lIO span{fill:#333;color:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO .node rect,#mermaid-svg-8CEqiNFiyL0W1lIO .node circle,#mermaid-svg-8CEqiNFiyL0W1lIO .node ellipse,#mermaid-svg-8CEqiNFiyL0W1lIO .node polygon,#mermaid-svg-8CEqiNFiyL0W1lIO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8CEqiNFiyL0W1lIO .rough-node .label text,#mermaid-svg-8CEqiNFiyL0W1lIO .node .label text,#mermaid-svg-8CEqiNFiyL0W1lIO .image-shape .label,#mermaid-svg-8CEqiNFiyL0W1lIO .icon-shape .label{text-anchor:middle;}#mermaid-svg-8CEqiNFiyL0W1lIO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8CEqiNFiyL0W1lIO .rough-node .label,#mermaid-svg-8CEqiNFiyL0W1lIO .node .label,#mermaid-svg-8CEqiNFiyL0W1lIO .image-shape .label,#mermaid-svg-8CEqiNFiyL0W1lIO .icon-shape .label{text-align:center;}#mermaid-svg-8CEqiNFiyL0W1lIO .node.clickable{cursor:pointer;}#mermaid-svg-8CEqiNFiyL0W1lIO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8CEqiNFiyL0W1lIO .arrowheadPath{fill:#333333;}#mermaid-svg-8CEqiNFiyL0W1lIO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8CEqiNFiyL0W1lIO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8CEqiNFiyL0W1lIO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8CEqiNFiyL0W1lIO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8CEqiNFiyL0W1lIO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8CEqiNFiyL0W1lIO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster text{fill:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO .cluster span{color:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8CEqiNFiyL0W1lIO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8CEqiNFiyL0W1lIO rect.text{fill:none;stroke-width:0;}#mermaid-svg-8CEqiNFiyL0W1lIO .icon-shape,#mermaid-svg-8CEqiNFiyL0W1lIO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8CEqiNFiyL0W1lIO .icon-shape p,#mermaid-svg-8CEqiNFiyL0W1lIO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8CEqiNFiyL0W1lIO .icon-shape .label rect,#mermaid-svg-8CEqiNFiyL0W1lIO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8CEqiNFiyL0W1lIO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8CEqiNFiyL0W1lIO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8CEqiNFiyL0W1lIO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 拒绝
接受
是
否
是
否
应用层: 需要查询对端服务

如查找 A2DP Sink
Host 建立到对端的 ACL 链路

已完成认证/加密
Host 发送 SDP 连接请求

L2CAP 连接 PSM = 0x0001 SDP
对端 SDP Server

接受 L2CAP 连接?
失败处理

对端 SDP 不可达

可能是设备类型不支持
L2CAP 通道建立

Config 协商 MTU
构造 SDP_ServiceSearchAttributeRequest

参数1: ServiceSearchPattern

= A2DP Sink UUID 0x110B

参数2: AttributeIDList

= ProtocolDescriptorList 0x0004

  • BluetoothProfileDescriptorList 0x0009
    响应数据大小

超过 L2CAP MTU?
Server 分段响应

ContinuationState 非空
Client 发送 Continuation 请求

携带 ContinuationState

循环拉取剩余数据
收到完整 SDP 响应

ContinuationState 为空
解析 ProtocolDescriptorList:

L2CAP PSM = AVDTP 0x0019

AVDTP 版本
解析 ProfileDescriptor:

A2DP Profile UUID + v1.3
应用还需要其他服务?

如 AVRCP TG 0x110C
断开 SDP L2CAP 连接

或复用通道继续通信
服务发现完成

应用获得连接所需全部参数

5.4 SDP 时序图

SDP Server (对端) SDP Client (查询方 Host) SDP Server (对端) SDP Client (查询方 Host) #mermaid-svg-jMiHWpnKMiGxwkuG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jMiHWpnKMiGxwkuG .error-icon{fill:#552222;}#mermaid-svg-jMiHWpnKMiGxwkuG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jMiHWpnKMiGxwkuG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jMiHWpnKMiGxwkuG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jMiHWpnKMiGxwkuG .marker.cross{stroke:#333333;}#mermaid-svg-jMiHWpnKMiGxwkuG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jMiHWpnKMiGxwkuG p{margin:0;}#mermaid-svg-jMiHWpnKMiGxwkuG .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jMiHWpnKMiGxwkuG text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jMiHWpnKMiGxwkuG .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-jMiHWpnKMiGxwkuG .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-jMiHWpnKMiGxwkuG #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-jMiHWpnKMiGxwkuG .sequenceNumber{fill:white;}#mermaid-svg-jMiHWpnKMiGxwkuG #sequencenumber{fill:#333;}#mermaid-svg-jMiHWpnKMiGxwkuG #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-jMiHWpnKMiGxwkuG .messageText{fill:#333;stroke:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jMiHWpnKMiGxwkuG .labelText,#mermaid-svg-jMiHWpnKMiGxwkuG .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .loopText,#mermaid-svg-jMiHWpnKMiGxwkuG .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jMiHWpnKMiGxwkuG .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-jMiHWpnKMiGxwkuG .noteText,#mermaid-svg-jMiHWpnKMiGxwkuG .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-jMiHWpnKMiGxwkuG .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jMiHWpnKMiGxwkuG .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jMiHWpnKMiGxwkuG .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jMiHWpnKMiGxwkuG .actorPopupMenu{position:absolute;}#mermaid-svg-jMiHWpnKMiGxwkuG .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-jMiHWpnKMiGxwkuG .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jMiHWpnKMiGxwkuG .actor-man circle,#mermaid-svg-jMiHWpnKMiGxwkuG line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-jMiHWpnKMiGxwkuG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ACL 已建立并完成认证 alt 数据可一次返回 需要分段 解析得到: AVDTP PSM = 0x0019, Profile 版本 L2CAP Connection Request (PSM = 0x0001) L2CAP Connection Response (CID 分配) L2CAP Config Request (MTU 协商) L2CAP Config Response SDP_ServiceSearchAttributeRequest SearchPattern: A2DP Sink UUID AttrList: 0x0004, 0x0009 SDP_Response (Complete) ContinuationState = NULL SDP_Response (Partial) ContinuationState = 0x01... SDP Request + ContinuationState SDP_Response (Complete) ContinuationState = NULL L2CAP Disconnection Request L2CAP Disconnection Response

5.5 常见 Profile 的 SDP 查询结果示例

以搜索 A2DP Audio Sink(音箱/耳机) 为例,返回的属性值:

复制代码
ServiceClassIDList:
  ├─ Audio Sink (0x110B)

ProtocolDescriptorList:
  ├─ L2CAP (0x0100), PSM = AVDTP (0x0019)
  └─ AVDTP (0x0019), Version = 0x0103 (v1.3)

BluetoothProfileDescriptorList:
  └─ Advanced Audio Distribution (0x110D), v1.3

再以 SPP(串口) 为例,应用真正需要的是 RFCOMM 通道号:

复制代码
ProtocolDescriptorList:
  ├─ L2CAP (0x0100), PSM = RFCOMM (0x0003)
  └─ RFCOMM (0x0003), Channel = 0x05  ← 应用连接此通道号

六、四大流程的完整时序串联

实际场景中(如手机连接蓝牙音箱听音乐),四大流程依次衔接:
音箱 Controller 音箱 Host 手机 Controller 手机 Host 音箱 Controller 音箱 Host 手机 Controller 手机 Host #mermaid-svg-KJrEcUs3sQo4aR83{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KJrEcUs3sQo4aR83 .error-icon{fill:#552222;}#mermaid-svg-KJrEcUs3sQo4aR83 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KJrEcUs3sQo4aR83 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KJrEcUs3sQo4aR83 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KJrEcUs3sQo4aR83 .marker.cross{stroke:#333333;}#mermaid-svg-KJrEcUs3sQo4aR83 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KJrEcUs3sQo4aR83 p{margin:0;}#mermaid-svg-KJrEcUs3sQo4aR83 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KJrEcUs3sQo4aR83 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KJrEcUs3sQo4aR83 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-KJrEcUs3sQo4aR83 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-KJrEcUs3sQo4aR83 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-KJrEcUs3sQo4aR83 .sequenceNumber{fill:white;}#mermaid-svg-KJrEcUs3sQo4aR83 #sequencenumber{fill:#333;}#mermaid-svg-KJrEcUs3sQo4aR83 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-KJrEcUs3sQo4aR83 .messageText{fill:#333;stroke:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KJrEcUs3sQo4aR83 .labelText,#mermaid-svg-KJrEcUs3sQo4aR83 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .loopText,#mermaid-svg-KJrEcUs3sQo4aR83 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KJrEcUs3sQo4aR83 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-KJrEcUs3sQo4aR83 .noteText,#mermaid-svg-KJrEcUs3sQo4aR83 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-KJrEcUs3sQo4aR83 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KJrEcUs3sQo4aR83 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KJrEcUs3sQo4aR83 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KJrEcUs3sQo4aR83 .actorPopupMenu{position:absolute;}#mermaid-svg-KJrEcUs3sQo4aR83 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-KJrEcUs3sQo4aR83 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KJrEcUs3sQo4aR83 .actor-man circle,#mermaid-svg-KJrEcUs3sQo4aR83 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-KJrEcUs3sQo4aR83 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 设备发现 Inquiry ② 连接建立 Paging ③ 配对与绑定 用户确认 (Just Works/数字比较) Link Key 写入双方 NVRAM (绑定) ④ 服务发现 SDP ⑤ 应用数据传输 (A2DP 音频流) HCI_Inquiry 1 ID 广播 (GIAC) 2 FHS + EIR (名称, CoD=Audio) 3 HCI_Inquiry_Result_With_RSSI 4 HCI_Inquiry_Complete 5 HCI_Create_Connection (BD_ADDR, CLK_Offset) 6 Page (ID, FHS...) 7 同步确认 8 HCI_Connection_Complete (Handle) 9 LMP 版本/特性/加密协商 10 LMP IO Capabilities 交换 11 公钥交换 (DH) 12 LMP 认证 (质询-响应) 13 HCI_Authentication_Complete 14 启用加密 15 L2CAP 连接 PSM=0x0001 16 SDP 查询: A2DP Sink UUID 17 返回: AVDTP PSM=0x0019 18 L2CAP 连接 PSM=0x0019 (AVDTP) 19 AVDTP 流建立 → 音频 RTP 包经加密 ACL 传输 20


七、开发常见问题与调试要点

7.1 各流程常见失败点速查

流程 常见失败原因 排查手段
设备发现 对端未处于可发现模式;Inquiry 时长过短;射频干扰 用 Ellisys/Frontline 抓包看是否有 FHS 响应
连接建立 Clock_Offset 过期(对端时钟漂移);对端 Page Scan 间隔过长;PSRM 不匹配 延长 Page Timeout(默认 5.12s,可调至 61.44s)
配对 Just Works 与 Passkey 模式不匹配;一方删除绑定另一方未删;PIN 错误(Legacy) 查看 HCI_Authentication_Complete 的 Status 码
服务发现 对端无 SDP Server 响应;Continuation 处理错误导致数据截断 解析 SDP 响应的 ContinuationState

7.2 流程间状态依赖关系

#mermaid-svg-v5rsiuYHxcwppMaa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-v5rsiuYHxcwppMaa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-v5rsiuYHxcwppMaa .error-icon{fill:#552222;}#mermaid-svg-v5rsiuYHxcwppMaa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-v5rsiuYHxcwppMaa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-v5rsiuYHxcwppMaa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-v5rsiuYHxcwppMaa .marker.cross{stroke:#333333;}#mermaid-svg-v5rsiuYHxcwppMaa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-v5rsiuYHxcwppMaa p{margin:0;}#mermaid-svg-v5rsiuYHxcwppMaa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-v5rsiuYHxcwppMaa .cluster-label text{fill:#333;}#mermaid-svg-v5rsiuYHxcwppMaa .cluster-label span{color:#333;}#mermaid-svg-v5rsiuYHxcwppMaa .cluster-label span p{background-color:transparent;}#mermaid-svg-v5rsiuYHxcwppMaa .label text,#mermaid-svg-v5rsiuYHxcwppMaa span{fill:#333;color:#333;}#mermaid-svg-v5rsiuYHxcwppMaa .node rect,#mermaid-svg-v5rsiuYHxcwppMaa .node circle,#mermaid-svg-v5rsiuYHxcwppMaa .node ellipse,#mermaid-svg-v5rsiuYHxcwppMaa .node polygon,#mermaid-svg-v5rsiuYHxcwppMaa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-v5rsiuYHxcwppMaa .rough-node .label text,#mermaid-svg-v5rsiuYHxcwppMaa .node .label text,#mermaid-svg-v5rsiuYHxcwppMaa .image-shape .label,#mermaid-svg-v5rsiuYHxcwppMaa .icon-shape .label{text-anchor:middle;}#mermaid-svg-v5rsiuYHxcwppMaa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-v5rsiuYHxcwppMaa .rough-node .label,#mermaid-svg-v5rsiuYHxcwppMaa .node .label,#mermaid-svg-v5rsiuYHxcwppMaa .image-shape .label,#mermaid-svg-v5rsiuYHxcwppMaa .icon-shape .label{text-align:center;}#mermaid-svg-v5rsiuYHxcwppMaa .node.clickable{cursor:pointer;}#mermaid-svg-v5rsiuYHxcwppMaa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-v5rsiuYHxcwppMaa .arrowheadPath{fill:#333333;}#mermaid-svg-v5rsiuYHxcwppMaa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-v5rsiuYHxcwppMaa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-v5rsiuYHxcwppMaa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v5rsiuYHxcwppMaa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-v5rsiuYHxcwppMaa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v5rsiuYHxcwppMaa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-v5rsiuYHxcwppMaa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-v5rsiuYHxcwppMaa .cluster text{fill:#333;}#mermaid-svg-v5rsiuYHxcwppMaa .cluster span{color:#333;}#mermaid-svg-v5rsiuYHxcwppMaa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-v5rsiuYHxcwppMaa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-v5rsiuYHxcwppMaa rect.text{fill:none;stroke-width:0;}#mermaid-svg-v5rsiuYHxcwppMaa .icon-shape,#mermaid-svg-v5rsiuYHxcwppMaa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v5rsiuYHxcwppMaa .icon-shape p,#mermaid-svg-v5rsiuYHxcwppMaa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-v5rsiuYHxcwppMaa .icon-shape .label rect,#mermaid-svg-v5rsiuYHxcwppMaa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v5rsiuYHxcwppMaa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-v5rsiuYHxcwppMaa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-v5rsiuYHxcwppMaa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 无
有
是
否
Inquiry

设备发现
Page

ACL 连接建立
有绑定 Link Key?
Pairing

配对生成 Link Key
Authentication

直接认证
需要加密?
Encryption

启用加密
SDP

服务发现
Profile 连接

L2CAP/RFCOMM/AVDTP
应用数据交互

7.3 核心要点回顾

  1. 设备发现(Inquiry) 是广播式查询,产出 BD_ADDR、CoD、Clock_Offset------其中 Clock_Offset 直接服务于下一步加速连接。
  2. 连接建立(Paging) 是定向快速同步过程,FHS 包完成跳频同步,之后 LMP 自动完成链路协商。
  3. 配对 的核心产物是 Link Key ;SSP 通过 DH 密钥交换 + IO 能力匹配四种关联模型解决安全性与易用性矛盾;绑定 即 Link Key 持久化。
  4. 认证 是基于 Link Key 的质询-响应,每次连接都可执行;加密 密钥由 Link Key 经 E3 派生。
  5. SDP 运行在 L2CAP PSM 0x0001 上,通过 "UUID 搜索 + 属性提取" 两步(或 SSAR 一步)获取 Profile 连接参数(PSM、RFCOMM Channel 等),是 Profile 连接的前置必经步骤。

相关推荐
rls_v22 天前
jieli:I2S外设是如何工作的?
bluetooth
rls_v1 个月前
什么是蓝牙的信令测试
bluetooth
rls_v1 个月前
AC696X-双模蓝牙功耗与时隙分析
bluetooth
rls_v1 个月前
经典蓝牙音量同步机制
bluetooth
你怎么知道我是队长2 个月前
经典蓝牙(Classic Bluetooth / BR/EDR)--- 核心协议层5 --- 经典蓝牙(BR/EDR)服务发现层核心机制详解
bluetooth
你怎么知道我是队长2 个月前
经典蓝牙(Classic Bluetooth / BR/EDR)--- 核心协议层5 --- 经典蓝牙(BR/EDR)电缆替代协议层核心机制详解
bluetooth
你怎么知道我是队长2 个月前
经典蓝牙(Classic Bluetooth / BR/EDR)--- 核心协议层1 --- 经典蓝牙(BR/EDR)物理层核心机制详解
bluetooth
奔跑吧 android3 个月前
【Bluetooth-SIG】【CoreV6.2】【Vol3 Part G】【GATT】【零】【GATT 逐句逐段学习计划 2】
ble·bluetooth·att·gatt·core_v6.2·sig
奔跑吧 android3 个月前
【Bluetooth-SIG】【CoreV6.2】【Vol3 Part F】【十三】【Error Handling——ATT_ERROR_RSP】
ble·bluetooth·att·gatt·蓝牙协议·bt·core_v6.2