3. HFP协议深入:AT指令集与服务级连接建立
好,咱们今天来聊聊HFP协议里最核心的部分——AT指令集和服务级连接建立。说实话,这部分是很多蓝牙音频工程师的“拦路虎”。我当年刚接触HFP时,也被这些AT指令搞得晕头转向。但搞懂了之后你会发现,其实逻辑很清晰。
3.1 服务级连接建立(SLC)
在建立音频连接(SCO/eSCO)之前,必须先建立服务级连接(Service Level Connection,简称SLC)。你可以把SLC理解为“控制通道”,而SCO/eSCO是“音频通道”。没有控制通道,音频通道就无从谈起。
SLC建立的典型流程是这样的:
- L2CAP通道建立(RFCOMM)
- AT+BRSF协商(双方能力交换)
- AT+CIND查询(指示器状态同步)
- AT+CMER设置(事件报告模式)
- AT+CLIP设置(来电显示通知)
- 其他可选指令(如AT+VGS、AT+CHLD等)
嗯,这里要注意:SLC建立的顺序是固定的。我曾经在项目中遇到过,有个同事把AT+BRSF和AT+CIND的顺序搞反了,结果手机端一直不响应,折腾了两天才找到原因。
3.2 AT指令集详解
3.2.1 AT+BRSF(能力协商)
这是SLC建立后的第一条指令。说白了,就是双方互相告诉对方:“我支持这些功能,你呢?”
指令格式:
AT+BRSF=<supported_features>
响应格式:
+BRSF: <peer_supported_features>
OK
功能位定义(我常用的几个):
| Bit | 功能 | 说明 |
|---|---|---|
| 0 | 三方通话 | Three-way calling |
| 1 | 呼叫等待/保持 | EC/NR(我经常搞混这个) |
| 3 | 语音识别 | Voice recognition |
| 5 | 回音消除/降噪 | EC/NR功能 |
| 7 | 宽带语音 | 支持mSBC编码 |
个人经验:我建议在实现时,先把所有支持的功能位都置1,然后根据对端的响应再动态调整。这样兼容性最好。我曾经遇到过一个奇葩的耳机芯片,它只支持Bit0和Bit5,其他位置1反而会导致协商失败。
3.2.2 AT+CIND(指示器查询)
这条指令用来查询当前设备的指示器状态。比如:信号强度、通话状态、电池电量等。
指令格式:
AT+CIND=?
AT+CIND?
典型响应:
+CIND: ("call",(0,1)),("callsetup",(0-3)),("service",(0,1)),("signal",(0-5)),("roam",(0,1)),("battchg",(0-5))
OK
你想想看,这个指令其实挺重要的。如果耳机端不处理AT+CIND,手机端可能就不会上报来电状态。我刚开始做的时候,就因为这个吃了亏——耳机能连上,但就是不显示来电信息。
3.2.3 AT+CLIP(来电显示)
这条指令控制是否启用来电显示功能。说白了,就是让手机在来电时把电话号码发过来。
指令格式:
AT+CLIP=1 // 启用来电显示
AT+CLIP=0 // 禁用来电显示
来电时的通知:
+CLIP: "13800138000",129,"",0,"",0
避坑指南:我曾经遇到过一个问题:AT+CLIP=1发送后,手机返回了OK,但来电时就是不发送+CLIP通知。后来发现,是因为SLC建立时没有正确设置AT+CMER(事件报告模式)。记住:AT+CMER必须在AT+CLIP之前设置,否则手机不会主动上报事件。
3.3 音频连接建立(SCO/eSCO)
SLC建立完成后,就可以建立音频连接了。这里有两种方式:SCO和eSCO。
SCO vs eSCO:
| 特性 | SCO | eSCO |
|---|---|---|
| 全称 | Synchronous Connection Oriented | Enhanced SCO |
| 重传机制 | 无 | 有(最多2次重传) |
| 音频质量 | 一般 | 更好(尤其宽带语音) |
| 延迟 | 固定 | 可配置 |
| 典型应用 | 传统通话 | 宽带语音(mSBC) |
建立流程:
- HF(耳机)发送AT+CHUP(如果当前有通话)
- AG(手机)发送RING或+CLIP通知
- HF发送ATA(接听)或AT+CHUP(拒接)
- AG发起SCO/eSCO连接请求
- HF接受连接,音频通道建立
关键点:eSCO连接建立时,需要协商三个参数:传输间隔(Tesco)、重传窗口(Wesco)、数据包类型。我建议使用以下参数组合:
- 传输间隔:12(约7.5ms)
- 重传窗口:2
- 数据包类型:EV3或2-EV3
这个组合在大多数手机上都能稳定工作。
3.4 实际项目中的坑
嗯,最后分享几个我踩过的坑:
- AT指令超时问题:有些手机处理AT指令很慢,尤其是AT+CIND=?这种查询指令。我建议超时时间设置至少5秒。
- SCO/eSCO切换:有些手机只支持SCO,有些只支持eSCO。我建议先尝试eSCO,如果失败再回退到SCO。
- 音频参数协商:mSBC编码(宽带语音)需要eSCO支持。如果手机不支持eSCO,就只能用CVSD编码(窄带)。
- 多路通话处理:AT+CHLD指令用于处理呼叫保持、三方通话等。这个逻辑比较复杂,我建议单独写一个状态机来处理。
好了,这一章的内容就到这里。下一章我们会深入讲解音频数据的传输和处理,包括SCO/eSCO数据包的格式、抖动缓冲区的设计等。到时候见!