3. HFP服务发现与连接建立:SDP中HFP服务记录结构、RFCOMM通道协商、AT命令Bearer建立流程、连接状态机转换
HFP(Hands-Free Profile)的连接建立过程是车载蓝牙电话功能的核心链路。本章深入剖析从服务发现到Bearer建立的完整技术细节,包括SDP服务记录结构、RFCOMM通道协商机制、AT命令交互流程以及连接状态机的精确转换。
3.1 SDP中HFP服务记录结构
在蓝牙服务发现协议(SDP)中,HFP规范定义了一套标准的服务记录结构。车载HF(Hands-Free)端通过查询AG(Audio Gateway)端的SDP记录,获取建立HFP连接所需的全部参数。
3.1.1 核心服务记录属性
| 属性ID | 属性名称 | 必选/可选 | 说明 |
|---|---|---|---|
| 0x0001 | ServiceClassIDList | 必选 | 包含Hands-Free或Headset服务类UUID |
| 0x0004 | ProtocolDescriptorList | 必选 | 描述协议栈:L2CAP → RFCOMM → 服务特定通道 |
| 0x0005 | BrowseGroupList | 可选 | 用于服务浏览分组 |
| 0x0009 | BluetoothProfileDescriptorList | 必选 | 包含HFP版本号(如1.7/1.8) |
| 0x0100 | ServiceName | 可选 | 人类可读的服务名称 |
| 0x0301 | SupportedFeatures | 必选 | 16位位掩码,标识支持的HFP特性 |
| 0x0302 | NetworkAvailability | 可选 | 指示网络可用性状态 |
3.1.2 HFP服务类UUID
HFP规范定义了两个关键UUID,用于区分HF和AG角色:
- Hands-Free UUID:0x111E(HF角色,通常由车载设备使用)
- Headset UUID:0x1108(HS角色,用于向后兼容Headset Profile)
- Hands-Free AG UUID:0x111F(AG角色,通常由手机使用)
实践要点:车载HF端在SDP查询时,应同时搜索0x111E和0x1108两个UUID。部分手机AG端可能只注册了Headset服务类,但实际支持HFP功能。建议优先匹配0x111E,若失败则回退到0x1108。
3.1.3 SupportedFeatures位掩码详解
SupportedFeatures属性(0x0301)是一个16位位掩码,用于在连接建立前交换双方的能力信息。以下是HFP 1.8版本的关键位定义:
| 位位置 | 特性名称 | 说明 |
|---|---|---|
| Bit 0 | Three-Way Calling | 三方通话功能 |
| Bit 1 | EC/NR | 回声消除与噪声抑制 |
| Bit 2 | Voice Recognition | 语音识别激活 |
| Bit 3 | In-Band Ring Tone | 带内振铃能力 |
| Bit 4 | Attach a Phone Number | 附加电话号码 |
| Bit 5 | Wide Band Speech | 宽带语音(mSBC编码) |
| Bit 6 | Enhanced Voice Recognition | 增强语音识别 |
| Bit 7 | Voice Recognition Text | 语音识别文本 |
| Bit 8 | Codec Negotiation | 编解码协商能力 |
| Bit 9 | HF Indicators | HF指示器支持 |
| Bit 10 | eSCO S4 | 增强SCO S4设置 |
| Bit 11-15 | Reserved | 保留位,置0 |
开发建议:在实现SDP解析时,务必对SupportedFeatures进行位掩码校验。例如,若AG端未设置Bit 5(Wide Band Speech),则后续音频连接应回退到CVSD编码,避免mSBC协商失败导致无声音。
3.2 RFCOMM通道协商
RFCOMM是HFP的传输层基础,它模拟RS-232串口通信,在L2CAP之上提供多路串口仿真。RFCOMM通道协商是HFP连接建立的第二步。
3.2.1 协议栈层次结构
3.2.2 RFCOMM通道协商流程
- SDP查询获取通道号:HF端向AG端发起SDP服务搜索,从ProtocolDescriptorList中提取RFCOMM通道号(通常为1~30之间的整数)。
- L2CAP连接建立:HF端发起L2CAP连接请求,PSM=3(RFCOMM协议服务复用器)。
- RFCOMM会话建立:在L2CAP通道上,HF端发送SABM(Set Asynchronous Balanced Mode)帧,包含目标通道号。
- UA响应:AG端回复UA(Unnumbered Acknowledgment)帧,确认RFCOMM通道建立成功。
- 参数协商:可选步骤,双方交换最大帧大小、信用量等参数。
常见问题:RFCOMM通道号冲突。部分手机AG端可能动态分配通道号,HF端不应硬编码通道号。每次连接前必须通过SDP重新查询,否则可能导致连接失败或连接到错误的串口服务。
3.3 AT命令Bearer建立流程
RFCOMM通道建立后,HF端与AG端通过AT命令进行Bearer(承载)建立。Bearer建立的核心目标是协商服务连接(Service Connection),为后续的呼叫控制、电话簿同步等功能奠定基础。
3.3.1 Bearer建立AT命令序列
| 步骤 | 方向 | AT命令 | 响应 | 说明 |
|---|---|---|---|---|
| 1 | HF → AG | AT+BRSF=<features> |
+BRSF: <features> |
交换双方支持的HFP特性位掩码 |
| 2 | AG → HF | +BRSF: <ag_features> |
— | AG端回复其支持的特性 |
| 3 | HF → AG | AT+CIND=? |
+CIND: ... |
查询AG端支持的指示器列表 |
| 4 | AG → HF | +CIND: ... |
— | AG回复指示器名称和取值范围 |
| 5 | HF → AG | AT+CIND? |
+CIND: ... |
查询当前指示器状态值 |
| 6 | AG → HF | +CIND: ... |
— | AG回复当前状态(如信号强度、电池电量) |
| 7 | HF → AG | AT+CMER=3,0,0,1 |
OK |
启用指示器事件主动上报 |
| 8 | HF → AG | AT+CHLD=? |
+CHLD: ... |
查询呼叫保持与多方通话能力 |
| 9 | AG → HF | +CHLD: ... |
— | AG回复支持的呼叫保持操作 |
| 10 | HF → AG | AT+COPS=3,0 |
OK |
设置运营商格式为长字母名称 |
| 11 | HF → AG | AT+COPS? |
+COPS: ... |
查询当前运营商信息 |
| 12 | AG → HF | +COPS: ... |
— | AG回复运营商名称 |
关键时序约束:HF端必须在收到AG端的
+BRSF响应后,才能发送后续的AT+CIND=?命令。部分AG端对命令顺序敏感,乱序发送可能导致连接失败。建议在实现中使用状态机严格管理AT命令的发送时序。
3.3.2 Bearer建立完整交互示例
HF: AT+BRSF=1023
AG: +BRSF: 895
HF: AT+CIND=?
AG: +CIND: ("service",(0,1)),("call",(0,1)),("callsetup",(0,3)),
("callheld",(0,2)),("signal",(0,5)),("roam",(0,1)),
("battchg",(0,5))
HF: AT+CIND?
AG: +CIND: 1,0,0,0,4,0,4
HF: AT+CMER=3,0,0,1
AG: OK
HF: AT+CHLD=?
AG: +CHLD: (0,1,1x,2,2x,3)
HF: AT+COPS=3,0
AG: OK
HF: AT+COPS?
AG: +COPS: 0,0,"China Mobile"
HF: AT+CMEE=1
AG: OK
3.4 连接状态机转换
HFP连接状态机是协议栈实现的核心,它定义了HF端从空闲到完全连接的状态转换路径。准确实现状态机是保证连接稳定性的关键。
3.4.1 状态定义
| 状态名称 | 状态值 | 说明 |
|---|---|---|
| HFP_STATE_IDLE | 0 | 空闲状态,无任何连接 |
| HFP_STATE_SDP_QUERY | 1 | 正在执行SDP服务发现 |
| HFP_STATE_RFCOMM_CONNECTING | 2 | 正在建立RFCOMM连接 |
| HFP_STATE_RFCOMM_CONNECTED | 3 | RFCOMM连接已建立,等待AT命令交互 |
| HFP_STATE_BRSF_EXCHANGE | 4 | 正在交换BRSF特性 |
| HFP_STATE_CIND_QUERY | 5 | 正在查询指示器列表和状态 |
| HFP_STATE_CMER_SET | 6 | 正在设置事件上报模式 |
| HFP_STATE_CHLD_QUERY | 7 | 正在查询呼叫保持能力 |
| HFP_STATE_COPS_QUERY | 8 | 正在查询运营商信息 |
| HFP_STATE_CONNECTED | 9 | 完全连接状态,可进行呼叫和电话簿操作 |
| HFP_STATE_DISCONNECTING | 10 | 正在断开连接 |
3.4.2 状态机转换图
3.4.3 状态机实现要点
- 超时管理:每个状态都应配置独立的超时定时器。建议SDP查询超时设为10秒,RFCOMM连接超时设为5秒,AT命令响应超时设为3秒。
- 错误恢复:当某个AT命令失败时,不应立即断开连接。建议实现重试机制(最多3次),重试仍失败后再进入DISCONNECTING状态。
- 状态持久化:在车载嵌入式环境中,连接状态应存储在非易失性存储器中,以便在系统重启后快速恢复连接。
- 并发处理:状态机应支持挂起和恢复操作。例如,在电话簿同步过程中,若收到来电事件,状态机应能暂停同步并优先处理呼叫。
最佳实践:建议使用有限状态机(FSM)框架实现HFP连接管理。将每个状态封装为独立的状态处理函数,通过事件驱动的方式触发状态转换。这种设计便于调试、测试和维护,也方便后续添加新的状态(如Codec Negotiation状态)。
3.5 连接建立完整时序
将上述所有步骤整合,HFP连接建立的完整时序如下:
- ACL链路建立:HF端与AG端完成基带连接和LMP认证。
- SDP服务发现:HF端查询AG端的HFP服务记录,获取RFCOMM通道号和SupportedFeatures。
- L2CAP连接:建立PSM=3的L2CAP通道。
- RFCOMM会话:在L2CAP通道上建立RFCOMM串口仿真连接。
- AT命令Bearer建立:依次执行BRSF、CIND、CMER、CHLD、COPS等AT命令。
- 音频连接建立:可选步骤,根据应用需求建立SCO/eSCO音频链路。
- 服务连接就绪:进入CONNECTED状态,可进行呼叫控制、电话簿同步等操作。
性能考量:在车载环境中,从ACL链路建立到HFP完全连接的总耗时应控制在3秒以内。超过5秒的用户体验将显著下降。建议对每个步骤进行耗时统计,并在调试日志中输出,便于定位性能瓶颈。