蓝牙免提协议(HFP)

本笔记为作者在学习蓝牙Host协议栈的一些心得体会,如有不对的地方,请包涵与谅解!

​ ————by wsoz

蓝牙免提协议(HFP)

HFP(Hands-Free Profile)通俗理解就是蓝牙免提(电话)协议,主要用于手机与耳机/车机之间的通话控制与语音业务。

在协议角色上,手机通常是 AG(Audio Gateway),耳机或车机通常是 HF(Hands-Free)。双方通过 RFCOMM 通道交互标准 AT Command/Response,实现接听、挂断、拒接、语音拨号、音量同步等控制功能;而真正的通话音频数据走 SCO/eSCO 语音链路,不是通过 AT 命令传输。


协议定位

在蓝牙协议栈中,HFP的位置位于

┌─────────────────────────────────┐
│      应用程序 (Application)      │
├─────────────────────────────────┤
│      HFP (蓝牙免提协议)  │  ← 应用层Profile
├─────────────────────────────────┤
│      RFCOMM (串口仿真层)         │
├─────────────────────────────────┤
│      L2CAP (逻辑链路层)          │
├─────────────────────────────────┤
│      HCI (主机控制接口)          │
├─────────────────────────────────┤
│      Baseband (基带)             │
└─────────────────────────────────┘

在这里插入图片描述

HFP的底层协议就是RFCOMM协议,然后该协议有两个角色:AG和HF。

  • AG(Audio Gateway):音频网关,通常是手机。负责接入蜂窝网络、维护通话状态,并向免提设备提供通话控制与音频网关能力。

  • HF(Hands-Free):免提终端,通常是蓝牙耳机或车机。通过AT命令控制通话(接听/挂断/拒接/重拨等),并通过SCO/eSCO承载语音数据。


SDP服务注册(HFP)

HFP在进入RFCOMM AT交互前,需要先通过SDP完成服务发现。
对外表现为:服务端先注册SDP记录,客户端先查SDP再连RFCOMM通道

HFP常用UUID

UUID-16 名称 说明
0x111E Handsfree HFP 免提服务(HF)
0x111F HandsfreeAudioGateway HFP 音频网关服务(AG)

HFP最小SDP属性(建议)

Attribute ID 名称 作用
0x0001 ServiceClassIDList 声明本记录是HFP HF还是HFP AG
0x0004 ProtocolDescriptorList 描述连接栈(L2CAP + RFCOMM + Server Channel)
0x0009 BluetoothProfileDescriptorList 声明Profile及版本
0x0100 ServiceName 便于调试识别
0x0311 SupportedFeatures 声明支持特性位图(影响后续AT能力协商)

ProtocolDescriptorList关键点

HFP基于RFCOMM,所以ProtocolDescriptorList里至少应包含:

[
  [L2CAP, PSM=0x0003],
  [RFCOMM, Server Channel=N]
]

其中Server Channel=N是客户端后续发起RFCOMM连接时必须使用的通道号。

示例

HF侧(耳机/车机)

ServiceClassIDList            = [0x111E]
ProtocolDescriptorList        = [[L2CAP,0x0003],[RFCOMM,Channel=2]]
BluetoothProfileDescriptorList= [[0x111E,Version=0x0107]]
ServiceName                   = "Handsfree"
SupportedFeatures (0x0311)    = 0xXXXX

AG侧(手机/网关)

ServiceClassIDList            = [0x111F]
ProtocolDescriptorList        = [[L2CAP,0x0003],[RFCOMM,Channel=3]]
BluetoothProfileDescriptorList= [[0x111E,Version=0x0107]]
ServiceName                   = "Handsfree Audio Gateway"
SupportedFeatures (0x0311)    = 0xXXXX

SLC建立连接

SLC(Service Level Connection)可以理解为:HFP中HF与AG在RFCOMM控制通道上的AT命令协商阶段
只有双方把规定的AT命令序列交互完成(能力协商 + 指示器查询/订阅),才算SLC建立成功。

常见最小交互顺序:

  1. AT+BRSF / +BRSF:双方能力协商
  2. AT+CIND=? / +CIND:查询AG支持的指示器
  3. AT+CIND? / +CIND:读取当前指示器状态
  4. AT+CMER=...:开启状态变化上报(如来电、通话状态)

可选交互(按版本/特性):

  • AT+CHLD=?:三方通话能力查询
  • AT+BIND / AT+BIND? / AT+BIEV:HF指示器相关能力与状态

SLC成功后,才进入稳定业务阶段:拨号、接听、挂断、音量同步,以及后续的SCO/eSCO语音链路建立。

下面具体讲解一下连接建立过程:

① 支持功能交换(Supported features exchange)

首先由HF向AG发送AT+BRSF=<HF supported features>,告诉网关本地支持的特性;
当AG接收到HF特性后,会返回+BRSF: <AG supported features>(并跟随OK),完成支持特性的交换。

交互示意:

HF -> AG : AT+BRSF=<hf_features>
AG -> HF : +BRSF: <ag_features>
AG -> HF : OK

HF Supported Features(AT+BRSF参数,HF上报)

Bit 含义
0 EC/NR 功能(回声消除/噪声抑制)
1 Call Waiting / Three-way Calling(三方通话能力)
2 CLI Presentation Capability(来电号码显示能力)
3 Voice Recognition Activation(语音识别激活)
4 Remote Volume Control(远端音量控制)
5 Enhanced Call Status(增强通话状态)
6 Enhanced Call Control(增强通话控制)
7 Codec Negotiation(编解码协商,如mSBC)
8 HF Indicators(HF指示器)
9 eSCO S4 Setting Supported(支持eSCO S4设置)
10 Enhanced Voice Recognition Status(增强语音识别状态)
11 Voice Recognition Text(语音识别文本)

AG Supported Features(+BRSF返回值,AG上报)

Bit 含义
0 Three-way Calling(三方通话)
1 EC/NR Function(回声消除/噪声抑制)
2 Voice Recognition Function(语音识别)
3 In-band Ring Tone Capability(带内铃声)
4 Attach Number to Voice Tag(语音标签关联号码)
5 Ability to Reject a Call(拒接来电)
6 Enhanced Call Status(增强通话状态)
7 Enhanced Call Control(增强通话控制)
8 Extended Error Result Codes(扩展错误码)
9 Codec Negotiation(编解码协商)
10 HF Indicators(HF指示器支持)
11 eSCO S4 Setting Supported(支持eSCO S4设置)
12 Enhanced Voice Recognition Status(增强语音识别状态)
13 Voice Recognition Text(语音识别文本)

features格式:

这个特性的说法就直接按照哪个bit移动即可,例如 HF 支持 bit0、bit2、bit4:

features = 1 + 4 + 16 = 21所以直接发送AT+BRSF=21即可,AG也是如此。

快速解析方法

如果features是十进制值,判断某bit是否支持可用:

bool support = (features & (1 << bit)) != 0;
编解码协商(Codec negotiation)

Codec negotiation 的作用是:在建立语音链路前,协商使用哪种语音编码
常见编码:

Codec ID 编码 说明
1 CVSD 窄带语音(兼容性最好)
2 mSBC 宽带语音(音质更好)

前提条件:HF 和 AG 的 BRSF 位图里都声明支持 Codec Negotiation(对应bit置1)。

常见交互流程(简化):

HF -> AG : AT+BAC=1,2          // HF上报本端支持的编码列表
AG -> HF : OK

AG -> HF : +BCS:2              // AG选择mSBC(示例)
HF -> AG : AT+BCS=2            // HF确认使用该编码
AG -> HF : OK

随后建立/更新 SCO/eSCO 语音链路

说明:

  • 如果协商失败或对端不支持宽带语音,通常会回退到 CVSD (Codec ID=1)
  • 没有Codec negotiation能力时,一般默认按CVSD进行语音通话。

格式说明:

AT+BAC=<codec_id1>[,<codec_id2>,...]即是直接发即可

AT+BAC=1,2 支持CVSD以及mSBC编解码功能 AT+BAC=1仅支持CVSD编解码功能

AG状态指示器(AG Indicators)

AG Indicators可以理解为:AG(手机)暴露给HF的状态字段,HF通过这些字段感知当前电话状态。

常见指标:

Indicator 含义
service 是否有移动网络服务
call 是否处于通话中
callsetup 呼叫建立过程状态(来电/外呼)
callheld 是否存在保持通话
signal 信号强度
roam 是否漫游
battchg 手机电量等级

常见交互顺序:

HF -> AG : AT+CIND=?              // 查询AG支持哪些indicator及取值范围
AG -> HF : +CIND: (...)
AG -> HF : OK

HF -> AG : AT+CIND?               // 查询当前indicator值
AG -> HF : +CIND: <v1>,<v2>...
AG -> HF : OK

HF -> AG : AT+CMER=3,0,0,1        // 开启indicator变化上报
AG -> HF : OK

开启CMER后,AG状态变化会通过+CIEV异步上报给HF:

AG -> HF : +CIEV: <index>,<value>

注意:index对应AT+CIND=?返回的indicator顺序,所以实现时通常要先保存映射关系。

格式说明:

AT+CIND=?:查询AG支持的indicator定义(名称+取值范围)

AT+CIND?:查询当前indicator实时值

AT+CMER=<mode>,<keyp>,<disp>,<ind>:控制指示器上报
常用:AT+CMER=3,0,0,1(开启上报) / AT+CMER=3,0,0,0(关闭上报)

其中参数可简易理解为:

参数 含义 常用值
mode 上报模式(HFP里通常用实时上报模式) 3
keyp 按键事件上报开关(HFP中一般不用) 0
disp 显示事件上报开关(HFP中一般不用) 0
ind AG indicator上报总开关 1开 / 0

+CIEV:<index>,<value>:AG异步上报某个indicator的新值(indexCIND=?顺序映射)

+CIEV里的value含义取决于具体indicator,例如:
call常见 0/1callsetup常见 0~3signal常见 0~5

例子(按常见顺序):

AT+CIND=?
+CIND: ("service",(0,1)),("call",(0,1)),("callsetup",(0-3)),("callheld",(0-2)),("signal",(0-5)),("roam",(0,1)),("battchg",(0-5))

其中返回的可以看出索引以及取值范围

来电流程中的+CIEV可读成:

+CIEV: 3,1   // callsetup=1,表示来电中
+CIEV: 2,1   // call=1,表示已进入通话
+CIEV: 3,0   // callsetup=0,呼叫建立流程结束
+CIEV: 2,0   // call=0,表示通话结束

AT+BIA=<i1>,<i2>,...,<in>(可选):按indicator顺序逐项开关上报(1允许,0屏蔽)

示例:AT+BIA=1,1,1,1,0,1,0 表示按顺序关闭第5和第7项上报。

④ 通话保持与多方通话能力查询(CHLD)

这一步通常用于确认AG支持哪些呼叫保持/三方通话控制命令。
前提一般是HF与AG在BRSF里都声明了相关能力(常见为bit1)。

典型交互:

HF -> AG : AT+CHLD=?            // 查询AG支持哪些CHLD操作
AG -> HF : +CHLD: (0,1,1x,2,2x,3)
AG -> HF : OK

常见CHLD含义(不同设备实现可能有差异):

命令 常见含义
AT+CHLD=0 释放保持中的通话或拒接等待来电
AT+CHLD=1 释放当前活动通话,接听等待/保持通话
AT+CHLD=1x 释放索引为x的指定通话
AT+CHLD=2 保持当前活动通话,并接听等待/保持通话
AT+CHLD=2x 保持除索引x外的所有通话,并恢复x
AT+CHLD=3 加入多方通话(会议)

说明:

  • AT+CHLD=?属于能力查询,通常放在SLC建立阶段。
  • 实际通话中再按需发送AT+CHLD=<op>执行控制。
  • 若AG不支持某些操作,可能不会出现在+CHLD:返回列表中。

格式说明:

AT+CHLD=?:查询AG支持的CHLD操作集合(能力查询)

+CHLD: (0,1,1x,2,2x,3):AG返回支持的操作列表;列表里没有的操作通常不可用

AT+CHLD=<op>:执行具体通话控制操作(op可为0/1/1x/2/2x/3

其中x是通话索引,一般配合AT+CLCC返回的idx使用(如AT+CHLD=12表示执行1xx=2)。

示例:

AT+CLCC                 // 先查看当前通话列表和idx
AT+CHLD=2               // 保持当前活动通话并接听等待通话
AT+CHLD=11              // 释放idx=1的通话(1x)
⑤ HF Indicators(BIND / BIEV)

这部分是HFP 1.7引入的可选能力,用于让HF把本地状态(如耳机电量)上报给AG
前提通常是HF和AG在BRSF里都声明支持 HF Indicators(常见bit8/bit10相关能力位)。

常见HF Indicator类型:

Indicator ID 含义
1 Enhanced Safety(增强安全) 0-1
2 Battery Level(HF电量等级) 0-100

常见交互(简化,具体顺序依实现可能有差异):

HF -> AG : AT+BIND=1,2           // HF声明本端支持的HF indicators
AG -> HF : OK

HF -> AG : AT+BIND=?             // 查询AG支持哪些HF indicators
AG -> HF : +BIND: (1,2)
AG -> HF : OK

HF -> AG : AT+BIND?              // 查询当前已启用的HF indicators
AG -> HF : +BIND: 1,1
AG -> HF : +BIND: 2,1
AG -> HF : OK

当HF状态变化时(例如耳机电量变化),可发送:

HF -> AG : AT+BIEV=2,<level>     // 上报HF电量
AG -> HF : OK

说明:

  • BIND主要做能力与启用状态协商,BIEV用于运行期状态上报。
  • AT+BIEV一般在SLC完成后使用。
  • 若对端不支持HF Indicators,通常不会进入这组流程。

格式说明:

AT+BIND=<ind1>[,<ind2>...]:HF声明本端支持的HF Indicator ID列表
示例:AT+BIND=1,2

AT+BIND=?:查询AG支持哪些HF Indicator ID
返回示例:+BIND: (1,2)

AT+BIND?:查询当前已启用的HF Indicator状态
返回格式:+BIND: <id>,<enabled>
其中:enabled=1表示启用,enabled=0表示未启用。

AT+BIEV=<id>,<value>:HF运行期上报某个HF Indicator的新值
示例:AT+BIEV=2,85(上报HF电量85)

常见value取值:

  • id=1(Enhanced Safety):0/1
  • id=2(Battery Level):0~100

注意:AT+BIEV一般在SLC建立后、且对应indicator已启用时发送。

下图为HF的SLC建立流程:

在这里插入图片描述


SLC断开连接

SLC断开本质上是HFP控制面(RFCOMM AT通道)被释放。 本质就是断掉HFP 对应 RFCOMM 的 server channel。

注意区分:

  • AT+CHUP 是“挂断通话”,不等于断开SLC。
  • SLC断开后,后续若要继续HFP控制,需重新建立SLC。
推荐断开顺序(有语音通话时)
  1. 先结束通话业务(若仍在通话)
  2. 释放SCO/eSCO语音链路
  3. 释放RFCOMM控制通道(SLC结束)
  4. 视系统策略决定是否继续断开ACL链路
典型交互(简化)

HF主动断开SLC:

HF -> AG : RFCOMM DISC (DLCI=HFP通道)
AG -> HF : RFCOMM UA

AG主动断开SLC:

AG -> HF : RFCOMM DISC (DLCI=HFP通道)
HF -> AG : RFCOMM UA

若继续释放ACL,常见会看到:

HCI_Disconnect
HCI_Disconnection_Complete (Reason=0x13/0x16/0x08...)
抓包判断要点
  • 看到RFCOMM DISC/UA,即可判定SLC控制通道正常关闭。
  • 只看到AT+CHUP而没有DISC/UA,通常表示“仅通话结束,SLC仍在”。
  • 若直接出现HCI_Disconnection_Complete而无DISC/UA,多为链路异常或底层直接断链。

手机状态信息

手机状态信息(AG Indicators)上报可分为两层控制:

  1. 全局开关(CMER)

    • 开启:AT+CMER=3,0,0,1 ,默认全部的状态信息上报都开启
    • 关闭:AT+CMER=3,0,0,0
      其中最后一位ind才是指示器上报开关。
  2. 单项开关(BIA)
    AT+BIA=<i1>,<i2>,...,<in>AT+CIND=? 返回顺序,对每个indicator逐项控制:

    • 1 = 允许上报
    • 0 = 屏蔽上报

示例:
若有7个indicator,且只想关闭signalbattchg,可发:

AT+BIA=1,1,1,1,0,1,0
信号强度(Strength Indication)

这个特性就是 AG 把本地的信号发送给 HF,值得范围是0-5来表示信号强度,就是手机信号5格表示一样。

漫游状态(Roaming Status Indication)

这个特性就是 AG 把漫游状态发送给 HF,其中漫游状态指的就是手机当前是否在“非归属网络”上注册(比如跨运营商/跨区域网络)

  • roam=1,漫游中
  • roam=0,未漫游
电量信息(Battery Level Indication)

这个特性就是 AG 把电量信息状态发送给 HF,电量信息范围在0-5,分别对应0%、20%、40%、60%、80%、100%。

运营商查询(Query Operator Selection)

这个功能用于让HF查询AG当前注册的蜂窝运营商名称(例如中国移动/中国联通)。

常见交互(简化):

HF -> AG : AT+COPS=3,0           // 设置返回格式为长字符串名称
AG -> HF : OK

HF -> AG : AT+COPS?              // 查询当前运营商
AG -> HF : +COPS: 0,0,"CHINA MOBILE"
AG -> HF : OK

格式说明:

AT+COPS=3,0:设置运营商显示格式(常见为长字母名称)

AT+COPS?:查询当前运营商

+COPS:<mode>,<format>,<oper>:AG返回运营商信息

字段简易说明:

  • <mode>:选择模式,常见 0(自动)
  • <format>:运营商字段格式
    • 0 = 长字母名称(如 "CHINA MOBILE"
    • 1 = 短字母名称
    • 2 = 数字编码(MCC/MNC)
  • <oper>:运营商名称或编码

注意:通常在SLC建立后查询更稳定;若当前无网络服务,<oper>可能为空或不可用。

用户号码信息(Subscriber Number Information)

这个功能用于HF主动查询AG侧“本机号码”信息(若可用)。

常见交互:

HF -> AG : AT+CNUM
AG -> HF : +CNUM: "My Number","+8613800138000",145,7
AG -> HF : OK

格式说明:

AT+CNUM:查询本机号码信息

+CNUM: <alpha>,<number>,<type>,<service>:AG返回号码记录

字段简易说明:

  • <alpha>:号码标签(可为空)
  • <number>:本机号码(可为空)
  • <type>:号码类型(常见129普通,145国际)
  • <service>:业务类型(常见4语音、5传真、7语音+传真,依实现而异)

注意:很多手机/SIM不会返回有效本机号,所以+CNUM为空或不返回都很常见。

扩展错误信息(Extended Audio Gateway Error Results)

这个特性用于让AG在命令失败时返回更详细错误信息,而不是只回一个笼统的ERROR

常见交互:

HF -> AG : AT+CMEE=1		使能
AG -> HF : OK

开启后,若后续命令失败,可能返回:

AG -> HF : +CME ERROR: <err_code>

格式说明:

AT+CMEE=<n>:设置扩展错误返回方式

常见取值(按实现):

  • 0:关闭扩展错误(通常只返回ERROR
  • 1:返回数字错误码(常见)
  • 2:返回文本错误信息(部分实现支持)

+CME ERROR:<err_code>:AG返回具体错误原因码,HF可据此做更精确的失败定位。

注意:是否支持该功能取决于AG能力(通常与+BRSF中的扩展错误位相关)。

电话状态(Transfer of Call Status)

这个特性用于让AG把通话相关状态实时上报给HF,核心是3个indicator:callcallsetupcallheld

Indicator 取值 含义
call 0/1 0无通话;1有通话
callsetup 0~3 0无建立过程;1来电中;2外呼拨号中;3外呼振铃中
callheld 0~2 0无保持;1有保持且有活动通话;2仅有保持通话

这些状态通常通过+CIEV:<index>,<value>上报(indexAT+CIND=?顺序映射)。

来电到挂断示例(假设 2=call3=callsetup):

+CIEV: 3,1   // 来电中(callsetup=1)
+CIEV: 2,1   // 接听后进入通话(call=1)
+CIEV: 3,0   // 建立流程结束(callsetup=0)
+CIEV: 2,0   // 挂断后无通话(call=0)

呼叫控制流程(HF视角)

本章主要关注AT控制面:来电、接听、拒接、外呼、重拨、挂断等流程。

AG侧来电

先了解一下带内铃声(In-band ring):来电铃声由AG(手机)通过蓝牙音频链路传给HF(耳机/车机)播放。它是AG的一个能力位(+BRSF相关bit)。

  • In-band ring = 1:支持带内铃声
  • In-band ring = 0:不支持带内铃声

如果支持带内铃声,通常来电阶段就会建立SCO/eSCO;HF在收到RING/来电状态后可直接听到铃声。
如果不支持带内铃声,来电阶段通常不建立SCO/eSCO,而是在call active后才建立。

**总结:**是否支持带内铃声,主要影响“音频链路是在来电阶段建立,还是在接听后建立”。

AG侧来电时,会主动给HF上报来电提示,常见为:

AG -> HF : RING

若开启来电号码显示(CLIP),通常还会看到:

AG -> HF : +CLIP: "<number>",<type>

注意:RING会不断发送,直到接听、拒接或超时结束。

HF侧接听来电

HF侧接听来电直接发送AT指令即可,之后call进入active状态。

HF -> AG : ATA
AG -> HF : OK

接听后,AG会通过+CIEV继续上报状态变化。

下图为支持带内铃声和不支持带内铃声的交互流程图:

在这里插入图片描述

在这里插入图片描述

通话中第二路来电(Call Waiting Notification)

该场景指的是:当前已经在通话中(call=1),又来了新的来电。

我们在SLC建立过程中如果HF和AG都支持该功能的话,我们后续HF还需要手动开启才可以支持该功能

  • AT+CCWA=1 开启第二路来电
  • AT+CCWA=0 关闭第二路来电

AG常见会给HF上报等待来电通知(若支持):

AG -> HF : +CCWA: "<number>",<type>     //type-129普通号码  type-145国际
AG -> HF : +CIEV: <callsetup_index>,1   // 进入来电建立状态

AG只是负责讲状态上报到HF,HF端可以用CHLD配合进行处:

HF -> AG : AT+CHLD=2      // 保持当前通话并接听待来电
AG -> HF : OK

也可根据策略执行其他CHLD操作,例如:

  • AT+CHLD=0:拒接等待来电
  • AT+CHLD=1:释放当前活动通话并接听等待来电

核心点:这是“第二路来电通知”,不是当前通话结束;call通常保持为1

来电号码显示

来电号码显示就是CLIP(Calling Line Identification Presentation),用于在来电时把主叫号码上报给HF。

常见控制方式:

  • AT+CLIP=1:开启来电号码显示上报
  • AT+CLIP=0:关闭来电号码显示上报

常见交互:

HF -> AG : AT+CLIP=1
AG -> HF : OK

AG -> HF : RING
AG -> HF : +CLIP: "13800138000",129

格式说明:

+CLIP: "<number>",<type>

  • <number>:来电号码
  • <type>:号码类型(TON/NPI)
    • 129:普通号码
    • 145:国际号码(常见带+

注意:是否实际上报+CLIP还取决于网络侧是否提供主叫号码。

来电降噪

来电降噪主要指HFP中的EC/NR能力:

  • EC(Echo Cancelling):回声消除,减少扬声器回灌到麦克风产生的回声
  • NR(Noise Reduction):噪声抑制,降低环境噪声(风噪、路噪、背景声)

该能力通常在BRSF功能交换阶段体现(对应EC/NR相关bit)。

常见控制命令(按实现支持):

HF -> AG : AT+NREC=0
AG -> HF : OK

含义:HF通知AG关闭AG侧EC/NR(常用于HF端自己已做语音处理的场景)。
若AG不支持或不允许控制,可能返回ERROR或忽略该命令。

注意:这个命令本质上是修改AG 内部的 EC/NR(回声消除/噪声抑制)处理链。当然HF侧也可以自己做降噪,常见的就是HF做主处理,AG侧处理弱化或关闭。

语音识别激活(Voice Recognition Activation)

这个功能在耳机/车机场景下:HF可以不拿起手机,直接远程唤起AG(手机)侧语音助手或语音拨号。(功能比较鸡肋

常见控制命令:

HF -> AG : AT+BVRA=1      // 启动语音识别
AG -> HF : OK

HF -> AG : AT+BVRA=0      // 停止语音识别
AG -> HF : OK

部分实现中,AG状态变化时还会主动上报:

AG -> HF : +BVRA: 1       // 语音识别已开启
AG -> HF : +BVRA: 0       // 语音识别已关闭

前提:HF和AG在BRSF能力交换时都声明支持Voice Recognition相关能力。

HF侧拒绝来电/挂断通话

HF侧拒绝来电,或断开正在进行的通话,通常都直接发送挂断命令:

HF -> AG : AT+CHUP
AG -> HF : OK

拒接成功后,AG一般会停止RING并上报状态恢复,例如:

AG -> HF : +CIEV: <callsetup_index>,0   // 来电建立流程结束

常见结果:

  • callsetup 回到 0
  • call 保持 0(未进入通话)

如果AG端拒绝来电/断开通话,AG同样会上报+CIEV状态变化。

HF主动拨号

HF侧主动外呼通常使用ATD<number>;,其中分号;表示语音呼叫。

常见交互(简化):

HF -> AG : ATD10086;
AG -> HF : OK

随后AG会通过+CIEV上报通话建立状态(按常见映射:2=call3=callsetup):

+CIEV: 3,2   // callsetup=2,外呼拨号中
+CIEV: 3,3   // callsetup=3,对端振铃中
+CIEV: 2,1   // call=1,通话建立
+CIEV: 3,0   // callsetup=0,建立流程结束

若对端未接听或失败,常见表现是callsetup回到0

HF重拨(Redial Last Number)

HF可使用重拨命令拨打最近一次号码:

HF -> AG : AT+BLDN
AG -> HF : OK

后续状态上报与主动拨号一致,通常也是callsetup: 2 -> 3 -> 0,接通后call=1

拨号过程按键

AT+VTS用于在通话中发送DTMF按键音(双音多频),常见场景是拨打客服电话后按12#进行菜单选择。

常见格式:

AT+VTS=<dtmf>

示例(通话中输入“1#”):

HF -> AG : AT+VTS=1
AG -> HF : OK
HF -> AG : AT+VTS=#
AG -> HF : OK

注意:

  • 一般在通话建立后使用(call=1)。
  • 多位按键通常逐个发送,不建议一次性拼成长串。
  • 这里需要注意一点,AT+VTS=后面的数字是 acsii 编码,比如你要发送AT+VTS=1,那么这个 1 其实并不是 0x01,而是 0x31。我们自己状态AT包时就直接用字符就可以。
音量控制

音量控制(Remote Audio Volume Control)用于在通话中同步HF与AG的音量状态。

常见命令:

  • AT+VGS=<gain> / +VGS:<gain>:扬声器音量(Speaker Gain)
  • AT+VGM=<gain> / +VGM:<gain>:麦克风音量(Microphone Gain)

<gain>常见范围是0~15

常见方向:

  • HF本地按音量键后,HF可上报给AG:AT+VGS=<gain>
  • 手机侧音量变化后,AG也可能主动通知HF:+VGS:<gain>

示例(通话中把扬声器音量调到10):

HF -> AG : AT+VGS=10
AG -> HF : OK

示例(手机侧主动把音量改到12并通知HF):

AG -> HF : +VGS: 12

示例(手机侧主动把麦克风增益改到8并通知HF):

AG -> HF : +VGM: 8

说明:VGS/VGM通常使用**“绝对音量值”**同步,不是“加一/减一”增量命令。

HF侧结束外呼

在外呼建立过程中或通话中,HF都可通过:

HF -> AG : AT+CHUP
AG -> HF : OK

结束后常见状态回落:

+CIEV: 2,0   // call=0
+CIEV: 3,0   // callsetup=0

音频连接与转移(Audio Connection)

SLC负责控制面(能力协商、状态上报、拨号/接听/挂断等);
Audio连接负责语音面(SCO/eSCO),用于传输真实通话音频数据。

对于SCO/eSCO连接,可以由AG发起,也可以由HF发起;此处主要看HF主动建立。

HF主动建立SCO

前提条件:

  1. ACL链路已建立
  2. SLC已建立
  3. 若走宽带语音(mSBC),通常已完成AT+BAC / +BCS / AT+BCS协商

常见流程:

HF -> AG : AT+BCC                      // HF请求发起音频连接建立(常见实现)
AG -> HF : OK

随后进入HCI同步连接建立(SCO/eSCO)

**注意:**如果在SLC阶段进行了codec协商,AG可能会对codec进行再次确认:

AG -> HF : +BCS:<codec_id>    // 编解码确认
HF -> AG : AT+BCS:<codec_id>
AG -> HF : OK
通话中音频转移

这个场景指的是:通话不断开(call仍为1),只切换语音路径(手机听筒 ↔ HF设备)。

常见有两种方向:

  1. AG本地音频 -> HF设备

    • HF可通过 AT+BCC 请求把音频拉到蓝牙链路
    • 后续建立/恢复 SCO/eSCO
  2. HF设备音频 -> AG本地

    • 通常通过释放 SCO/eSCO 实现(由AG或HF侧策略触发)
    • 通话本身继续进行,SLC一般保持

典型交互(HF把音频拉到本机):

HF -> AG : AT+BCC
AG -> HF : OK
... HCI同步连接建立 ...
... 出现SCO Data ...

转回AG本地音频(通话不断)常见表现:

... HCI同步链路断开(SCO/eSCO release) ...
... 不出现AT+CHUP ...
... call状态通常仍为1 ...

抓包判断要点:

  • 音频转移看的是SCO/eSCO的建立/释放,不是看AT+CHUP
  • 若出现AT+CHUP,那是结束通话,不是“仅转移音频路径”

常用AT指令表

AT指令 用途说明
AT+BRSF=<features> HF上报本端支持能力(SLC能力交换)
AT+BAC=<codec_id1,...> HF上报支持的语音编解码列表
AT+BCS=<codec_id> HF确认AG选择的编解码
AT+BCC HF请求建立/拉起音频链路(SCO/eSCO)
AT+CIND=? 查询AG支持的indicator定义与范围
AT+CIND? 查询AG当前indicator状态值
AT+CMER=<mode>,<keyp>,<disp>,<ind> 控制AG indicator上报总开关(常用AT+CMER=3,0,0,1
AT+BIA=<i1>,<i2>,...,<in> 按indicator顺序逐项开关上报
AT+CHLD=? 查询AG支持的多路通话控制操作
AT+CHLD=<op> 执行多路通话控制(等待/保持/切换/会议)
AT+CCWA=1/0 开启/关闭呼叫等待通知(第二路来电)
AT+CLIP=1/0 开启/关闭来电号码显示
AT+NREC=0/1 控制AG侧EC/NR(回声消除/噪声抑制)
AT+BVRA=1/0 启动/停止AG侧语音识别(语音助手)
ATA 接听来电
AT+CHUP 拒接来电或挂断当前通话
ATD<number>; 主动发起语音呼叫
AT+BLDN 重拨最近一次号码
AT+VTS=<dtmf> 通话中发送DTMF按键音
AT+VGS=<gain> 设置扬声器音量(Speaker Gain)
AT+VGM=<gain> 设置麦克风增益(Microphone Gain)
AT+BIND=<id1,...> HF声明支持的HF Indicators列表
AT+BIND=? 查询AG支持哪些HF Indicators
AT+BIND? 查询当前已启用的HF Indicators
AT+BIEV=<id>,<value> HF上报本地indicator状态(如HF电量)
AT+COPS=3,0 设置运营商名称返回格式(长字符串)
AT+COPS? 查询当前运营商信息
AT+CNUM 查询AG侧本机号码信息(若可用)
AT+CMEE=<n> 设置扩展错误上报方式(返回+CME ERROR
AT+CLCC 查询当前通话列表(常与CHLD联动)
D=?` 查询AG支持的indicator定义与范围
AT+CIND? 查询AG当前indicator状态值
AT+CMER=<mode>,<keyp>,<disp>,<ind> 控制AG indicator上报总开关(常用AT+CMER=3,0,0,1
AT+BIA=<i1>,<i2>,...,<in> 按indicator顺序逐项开关上报
AT+CHLD=? 查询AG支持的多路通话控制操作
AT+CHLD=<op> 执行多路通话控制(等待/保持/切换/会议)
AT+CCWA=1/0 开启/关闭呼叫等待通知(第二路来电)
AT+CLIP=1/0 开启/关闭来电号码显示
AT+NREC=0/1 控制AG侧EC/NR(回声消除/噪声抑制)
AT+BVRA=1/0 启动/停止AG侧语音识别(语音助手)
ATA 接听来电
AT+CHUP 拒接来电或挂断当前通话
ATD<number>; 主动发起语音呼叫
AT+BLDN 重拨最近一次号码
AT+VTS=<dtmf> 通话中发送DTMF按键音
AT+VGS=<gain> 设置扬声器音量(Speaker Gain)
AT+VGM=<gain> 设置麦克风增益(Microphone Gain)
AT+BIND=<id1,...> HF声明支持的HF Indicators列表
AT+BIND=? 查询AG支持哪些HF Indicators
AT+BIND? 查询当前已启用的HF Indicators
AT+BIEV=<id>,<value> HF上报本地indicator状态(如HF电量)
AT+COPS=3,0 设置运营商名称返回格式(长字符串)
AT+COPS? 查询当前运营商信息
AT+CNUM 查询AG侧本机号码信息(若可用)
AT+CMEE=<n> 设置扩展错误上报方式(返回+CME ERROR
AT+CLCC 查询当前通话列表(常与CHLD联动)
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐