3. HFP协议深入:AT指令集与服务级连接建立

好,咱们今天来聊聊HFP协议里最核心的部分——AT指令集和服务级连接建立。说实话,这部分是很多蓝牙音频工程师的“拦路虎”。我当年刚接触HFP时,也被这些AT指令搞得晕头转向。但搞懂了之后你会发现,其实逻辑很清晰。

3.1 服务级连接建立(SLC)

在建立音频连接(SCO/eSCO)之前,必须先建立服务级连接(Service Level Connection,简称SLC)。你可以把SLC理解为“控制通道”,而SCO/eSCO是“音频通道”。没有控制通道,音频通道就无从谈起。

SLC建立的典型流程是这样的:

  1. L2CAP通道建立(RFCOMM)
  2. AT+BRSF协商(双方能力交换)
  3. AT+CIND查询(指示器状态同步)
  4. AT+CMER设置(事件报告模式)
  5. AT+CLIP设置(来电显示通知)
  6. 其他可选指令(如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:

特性SCOeSCO
全称Synchronous Connection OrientedEnhanced SCO
重传机制有(最多2次重传)
音频质量一般更好(尤其宽带语音)
延迟固定可配置
典型应用传统通话宽带语音(mSBC)

建立流程:

  1. HF(耳机)发送AT+CHUP(如果当前有通话)
  2. AG(手机)发送RING或+CLIP通知
  3. HF发送ATA(接听)或AT+CHUP(拒接)
  4. AG发起SCO/eSCO连接请求
  5. HF接受连接,音频通道建立

关键点:eSCO连接建立时,需要协商三个参数:传输间隔(Tesco)、重传窗口(Wesco)、数据包类型。我建议使用以下参数组合:

  • 传输间隔:12(约7.5ms)
  • 重传窗口:2
  • 数据包类型:EV3或2-EV3

这个组合在大多数手机上都能稳定工作。

3.4 实际项目中的坑

嗯,最后分享几个我踩过的坑:

  1. AT指令超时问题:有些手机处理AT指令很慢,尤其是AT+CIND=?这种查询指令。我建议超时时间设置至少5秒。
  2. SCO/eSCO切换:有些手机只支持SCO,有些只支持eSCO。我建议先尝试eSCO,如果失败再回退到SCO。
  3. 音频参数协商:mSBC编码(宽带语音)需要eSCO支持。如果手机不支持eSCO,就只能用CVSD编码(窄带)。
  4. 多路通话处理:AT+CHLD指令用于处理呼叫保持、三方通话等。这个逻辑比较复杂,我建议单独写一个状态机来处理。

好了,这一章的内容就到这里。下一章我们会深入讲解音频数据的传输和处理,包括SCO/eSCO数据包的格式、抖动缓冲区的设计等。到时候见!