HFP_HF
HFP(Hands-Free Profile),是蓝牙免提协议,可以让蓝牙设备对对端蓝牙设备的通话进行控制,例如蓝牙耳机控制手机通话的接听、挂断、拒接、语音拨号等。HFP中蓝牙两端的数据交互是通过定义好的AT指令来通讯的。HFP定义了音频网关(AG)和免提组件(HF)两个角色:
音频网关(AG):该设备为音频输入/输出的网关 。典型作为网关的设备为手机
免提组件(HF):该设备作为音频网关的远程音频输入/输出机制,并可提供若干遥控功能。典型作为免提组件的设备为车机、蓝牙耳机
AT命令的规则:
一个命令行,只能代表一个AT命令
< cr > carriage return的简写,相当于回车键,ASCII码为 0x0D
< lf > NL line feed, new line的简写,相当于换行键,ASCII码为0x0A
HF -> AG发送AT命令格式:< AT command >< cr >
AG -> HF发送AT命令格式:< cr >< lf >result code< cr >< lf >
AG给HF发送result code的AT命令如果是消息回复,后面都得再回复一条OK消息,除非回复的是+CME ERROR消息,后面的参数代表失败的原因。
本文档主要是基于Sifli SDK,介绍如何使用HF role的基本功能。涉及文件如下:
bts2_app_interface
bts2_app_hfp_hf
HFP_HF初始化
HF初始化的函数:bt_hfp_hf_init,HF相关的状态、标志赋初始值
HF服务启动的函数:bt_hfp_hf_start_enb,配置AT+BRSF相关的属性,用户可以根据需求调整相应的feature值
AT cmd:
AT+BRSF : HF support features (Bluetooth Retrieve Supported Features)
格式:AT+BRSF=< HF support features >
建立连接时,HF侧将自己支持的features发送给AG侧
#define HFP_HF_LOCAL_FEATURES ( HFP_HF_FEAT_ECNR | \
HFP_HF_FEAT_3WAY | \
HFP_HF_FEAT_CLI | \
HFP_HF_FEAT_VREC | \
HFP_HF_FEAT_VOL | \
HFP_HF_FEAT_ECS | \
HFP_HF_FEAT_ECC | \
HFP_HF_FEAT_CODEC | \
HFP_HF_FEAT_ESCO )
/* HFP peer features */
#define HFP_HF_FEAT_ECNR 0x0001 /* Echo cancellation/noise reduction */
#define HFP_HF_FEAT_3WAY 0x0002 /* Call waiting and three-way calling */
#define HFP_HF_FEAT_CLI 0x0004 /* Caller ID presentation capability */
#define HFP_HF_FEAT_VREC 0x0008 /* Voice recognition activation */
#define HFP_HF_FEAT_VOL 0x0010 /* Remote volume control */
#define HFP_HF_FEAT_ECS 0x0020 /* Enhanced Call Status */
#define HFP_HF_FEAT_ECC 0x0040 /* Enhanced Call Control */
#define HFP_HF_FEAT_CODEC 0x0080 /* Codec Negotiation */
#define HFP_HF_FEAT_HF_IND 0x0100 /* HF Indicators */
#define HFP_HF_FEAT_ESCO 0x0200 /* eSCO S4 (and T2) setting supported */
#define HFP_HF_FEAT_ENVR_EXT 0x0400 /*ENHANCED_VOICE_RECOGNITION_ST*/
#define HFP_HF_FEAT_VREC_TEXT 0x0800
/* Proprietary features: using bits after 12 */
/* Pass unknown AT command responses to application */
#define HFP_HF_FEAT_UNAT 0x1000
#define HFP_HF_FEAT_VOIP 0x2000 /* VoIP call */
HFP_HF连接设备
AG 设备和 HF设备建立连接到进行通话,大致会经历一下四个阶段。接下来会根据Specification重点介绍Service Level Connection 和 Audio Connection的过程。
LMP link:首先建立LMP Link,HFP连接中没有固定的master 或者slave
RFCOMM Connection:接着建立仿真串口端口data link channel,用于HF传输用户数据给AG(包括调制器的控制信号和 AT command),AG解析AT command将相应的responses通过仿真串口端口发送给HF
Service Level Connection:服务级别的连接是应用层HF <<>>AG控制和交互信息的基础。
Service Level Connection establishment
Service Level Connection release
Synchronous Connection/Audio Connection:SCO/eSCO 通话的连接通常是指语音数据的连接
Codec Connection
Wide Band Speech Connection
SLC(Service Level Connection)建立连接流程
当LM Link 和 RFCOMM Connection已存在的情况下,用户行为或者其他内部事件想要使用HFP服务就需要先建立SLC(Service Level Connection)连接。建立SLC连接需要进行一下5个阶段,分别是:
Supported features exchange(AT+BRSF)
Codec Negotiation(AT+BAC)
AG Indicators(AT+CIND 、AT+CMER 、+CIEV、AT+CHLD )
HF Indicators(AT+BIND、AT+BIEV)
End of Service Level Connection
Sifli HFP_HF 连接/断开设备
HF连接设备接口为:
bts2_app_interface连接接口:bt_interface_conn_ext
bts2_app_hfp_hf连接接口:bt_hfp_hf_start_connecting
HF连接断开设备接口为:
bts2_app_interface断开连接接口:bt_interface_disc_ext
bts2_app_hfp_hf断开接口:bt_hfp_hf_start_disc
HF连接状态回调event:
HF连接成功:BT_NOTIFY_HF_PROFILE_CONNECTED
HF连接失败:BT_NOTIFY_HF_PROFILE_DISCONNECTED
备注
注意:两个接口传递的地址参数需要进行相应的转换。
// 调用连接HF role的API之后,HF连接成功的消息通过notify给用户
// 用户需要实现接收notify event的hdl函数 如:bt_notify_handle
// SLC的消息:BT_NOTIFY_HF_PROFILE_CONNECTED,用户可以将消息转发到用户task里面处理。
// BT_NOTIFY_HF_PROFILE_CONNECTED event里面包含:地址信息 、profile_type、 res:0(成功)
// 断开设备连接调用bt_hfp_hf_start_disc
//BT_NOTIFY_HF_PROFILE_DISCONNECTED event里面包含:地址信息 、profile_type、 原因
//具体结构体信息参考API注释
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_HFP_HF:
{
bt_sifli_notify_hfp_hf_event_hdl(event_id, data, data_len);
}
break;
}
return 0;
}
int bt_sifli_notify_hfp_hf_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
case BT_NOTIFY_HF_PROFILE_CONNECTED:
{
//handle hf conencted msg(bt_notify_profile_state_info_t *)
break;
}
case BT_NOTIFY_HF_PROFILE_DISCONNECTED:
{
//handle disconneted msg(bt_notify_profile_state_info_t *)
break;
}
}
return 0;
}
HFP_HF基本功能使用
通话音频的建立
HFP specification中Audio Connection通常是指SCO/eSCO语音通路的连接,在SCO/eSCO之前,HF(AT+BCC)需要通知AG先对编解码算法进行选择。
AT cmd:
AT+BCC:Bluetooth Codec Connection
格式:AT+BCC
HF发送给AG,触发AG发起编解码器连接过程
AG决定发起编解码器连接过程,则回复OK;否则ERROR。回复ok之后,AG侧会发出+BCS:< codec_id > HF侧回复:AT+BCS= < codec_id >.之后建立好esco链接
Sifli HFP_HF 连接/断开通话音频
bts2_app_interface中通话音频连接/断开接口:bt_interface_audio_switch
bts2_app_hfp_hf中通话音频连接/断开接口:bt_hfp_hf_audio_transfer
通话音频建立成功的前提条件为:手机端通话状态非空闲;因为通话空闲状态时,手机端会拒绝 AT+BCC建立sco的请求。
通话音频编码包括:CVSD和 msbc,控制msbc codec是否启动的接口:bt_interface_set_wbs_status
通话音频建立成功之后,需要调用audio_open,通话音频断开或者HF断开之后需要调用audio_close,相关实现可以查看:hfp_audio_api
// 通话音频建立连接接口bt_interface_audio_switch中入参 :type 0:connect audio type 1 :disconnect audio
// 通话音频连接成功BT_NOTIFY_COMMON_SCO_CONNECTED event: sco type(区分HF或者AG) status(状态)
//具体结构体解释请参考interface中相关说明
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_COMMON:
{
bt_sifli_notify_common_event_hdl(event_id, data, data_len);
}
break;
}
return 0;
}
int bt_sifli_notify_common_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
case BT_NOTIFY_COMMON_SCO_CONNECTED:
{
//handle hf sco conencted msg(bt_notify_device_sco_info_t *)
break;
}
case BT_NOTIFY_COMMON_SCO_DISCONNECTED:
{
//handle sco disconneted msg(bt_notify_device_sco_info_t *)
break;
}
}
return 0;
}
通话音频音量控制
AT cmd:
AT+VGM:Gain of Microphone
格式: AT+VGM=< gain >
+VGM: Gain of Microphone
格式: +VGM:< gain >
调节audio 通路中MIC的音量,取值范围 0~15
AT cmd:
AT+VGS: Gain of Speaker
格式: AT+VGS=< gain >
+VGS: Gain of Speaker
格式: +VGS:< gain >
调节audio 通路中speaker的音量,取值范围 0~15
主动控制音量接口:
bts2_app_interface speaker音量控制接口:bt_interface_set_speaker_volume
bts2_app_hfp_hf speaker音量控制接口:bt_hfp_hf_update_spk_vol
bts2_app_hfp_hf microphone音量控制接口:bt_hfp_hf_update_mic_vol
设置音量处理结果event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_VGS/HFP_HF_AT_VGM)
对端设备控制音量event:BT_NOTIFY_HF_VOLUME_CHANGE
// 当存在通话音频,控制通话音频音量时,调用bt_interface_set_speaker_volume 传入音量值
// HF 会采用AT+VGS 格式将音量值通知 AG
// AG侧收到音量值之后,处理成功回复OK,处理失败回复ERROR
// 用户对应的事件event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_VGS/HFP_HF_AT_VGM)
// 具体结构体解释请参考interface中相关说明
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_HFP_HF:
{
bt_sifli_notify_hfp_hf_event_hdl(event_id, data, data_len);
}
break;
}
return 0;
}
int bt_sifli_notify_hfp_hf_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
case BT_NOTIFY_HF_VOLUME_CHANGE:
{
//handle volume value
break;
}
case BT_NOTIFY_HF_AT_CMD_CFM:
{
//handle at cmd result msg(bt_notify_at_cmd_cfm_t *)
break;
}
}
return 0;
}
// at cmd_id
enum
{
HFP_HF_AT_NONE = 0x00,
HFP_HF_AT_BRSF,
HFP_HF_AT_BAC,
HFP_HF_AT_CIND,
HFP_HF_AT_CIND_STATUS,
HFP_HF_AT_CMER,
HFP_HF_AT_CHLD,
HFP_HF_AT_CHLD_CMD,
HFP_HF_AT_CMEE,
HFP_HF_AT_BIA,
HFP_HF_AT_CLIP,
HFP_HF_AT_CCWA,
HFP_HF_AT_COPS,
HFP_HF_AT_COPS_CMD,
HFP_HF_AT_CLCC,
HFP_HF_AT_BVRA,
HFP_HF_AT_VGS, //speaker音量控制cmd_id
HFP_HF_AT_VGM, //microphone音量控制cmd_id
HFP_HF_AT_ATD,
HFP_HF_AT_BLDN,
HFP_HF_AT_ATA,
HFP_HF_AT_CHUP,
HFP_HF_AT_BTRH,
HFP_HF_AT_BTRH_MODE,
HFP_HF_AT_VTS,
HFP_HF_AT_BCC,
HFP_HF_AT_BCS,
HFP_HF_AT_CNUM,
HFP_HF_AT_NREC,
HFP_HF_AT_BINP,
HFP_HF_AT_CBC,
HFP_HF_AT_BIND,
HFP_HF_AT_BIEV,
HFP_HF_AT_BATT_UPDATE,
HFP_HS_AT_CKPD,
HFP_AT_EXTERN_AT_CMD
};
语音识别功能
AT cmd:
AT+BVRA: Voice Recognition Activation
格式: AT+BVRA=< status >
status
0(Disable Voice recognition in the AG)
1(Enable voice recognition in the AG)
2(Enable voice recognition in the AG with esco exist)
AT cmd:
+BVRA: Voice Recognition Activation
格式: +BVRA:< status >
status
0(Voice recognition is disabled in the AG)
1(Voice recognition is enabled in the AG)
HF通过发送AT+BVRA命令给AG来发起激活语音识别应用。语音识别应用安装在AG中。除了audio的路由、语音识别的激活控制等功能需要用到蓝牙功能,其余都依赖于语音识别应用的实现。
对端设备支持语音识别功能event:BT_NOTIFY_HF_VOICE_RECOG_CAP_UPDATE
对端设备主动使用语音识别功能状态同步event:BT_NOTIFY_HF_VOICE_RECOG_STATUS_CHANGE
主动唤醒/关闭语音功能接口:
bts2_app_interface语音识别接口:bt_interface_voice_recog
bts2_app_hfp_hf中语音识别接口: bt_hfp_hf_voice_recog_send
语音cmd处理结果的event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_BVRA)
// step1 : HF 主动唤醒语音识别调用 bt_interface_voice_recog(1);
// step2 : HF 发出 AT+BVRA=1
// step3 :AG 收到 AT+BVRA=1,处理结束之后发送ok/ERROR
// step4 :HF 收到AG 回复,notify event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_BVRA)
// 关闭流程类似开启流程
// 对端设备主动唤醒语音识别,HF收到之后notify event :BT_NOTIFY_HF_VOICE_RECOG_STATUS_CHANGE
// 具体结构体解释请参考interface中相关说明
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_HFP_HF:
{
bt_sifli_notify_hfp_hf_event_hdl(event_id, data, data_len);
}
break;
}
return 0;
}
int bt_sifli_notify_hfp_hf_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
case BT_NOTIFY_HF_VOICE_RECOG_CAP_UPDATE:
{
//handle
break;
}
case BT_NOTIFY_HF_VOICE_RECOG_STATUS_CHANGE:
{
//handle
break;
}
case BT_NOTIFY_HF_AT_CMD_CFM:
{
//handle at cmd result msg(bt_notify_at_cmd_cfm_t *)
//cmd_id:HFP_HF_AT_BVRA
break;
}
}
return 0;
}
电话控制相关功能
电话状态更新相关AT cmd
AT cmd:
AT+CIND: (Standard indicator update AT command)
格式:
AT+CIND=?测试指令。HF获取AG侧支持的指示器索引值和范围。在发送关于指示器的相关指令(AT+CIND? 或 AT_CMER)前,至少请求一次。
AT+CIND? 读指令,HF读取AG侧当前的指示器各个值
AT cmd:
+CIEV: unsolicited result code(Standard indicator events reporting unsolicited result code)
格式:+CIEV: < ind >,< value >
当AG测indicators发生变化时,AG需要主动用+ciev AT cmd 通知HF侧
手机端状态主动更新:
HF连接成功,同步手机电话状态event(call/callsetup/callheld):BT_NOTIFY_HF_CALL_STATUS_UPDATE
连接过程中,主动获取电话状态:
bts2_app_interface中获取电话状态接口bt_interface_get_remote_call_status
手机状态同步event:BT_NOTIFY_HF_CALL_STATUS_UPDATE
手机状态cmd处理结果的event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_CIND_STATUS)
连接过程中,手机电话状态主动更新通过event:BT_NOTIFY_HF_INDICATOR_UPDATE
电话控制相关AT cmd
AT cmd:
AT+CNUM: Subscriber Number Information
格式:AT+CNUM
该指令用于查询本机号码
+CNUM: Subscriber Number Information
格式:+CNUM: ,< number >,< type >[, < service >]
AG收到该请求之后,会将手机本机号码通过+CNUM回复给HF侧。
AT cmd:
AT+CLIP: Calling Line Identification notification
格式:AT+CLIP=(0/1)
+CLIP: Calling Line Identification notification
格式:+CLIP: < number >,< type >
使能或关闭主叫号码显示通知,使能后AG侧在来电时通过“+CLIP”指令将当前来电的号码和类型发送到HF
AT cmd:
AT+CCWA:Three-Way Call Handling
格式:AT+CCWA =(0/1)
使能或关闭三方电话waiting 提醒
+CCWA :Call Waiting Notification
格式:+CCWA: < number >,< type >
使能后,当已有一个接通电话,那么再进来电话时,AG就会发出+CCWA
AT cmd:
ATD:Dial call req
格式:ATDdd…dd
HF主动请求拨打电话
AT+BLDN:Bluetooth Last Dialed Number
格式:AT+BLDN
请求AG侧回拨最后一通电话。收到该请求后,AG根据最近一次拨打的号码,发起打电话。
AT cmd:
ATA: call answer
格式:ATA
应答电话,当接通后,出现+CIEV:< call_ind >, < 1 > 和 +CIEV:< call_setup_ind >, < 0 >
AT cmd:
AT+CHUP: Reject an Incoming Call/Terminate a Call Process
格式:AT+CHUP
拒接或者挂断电话,出现+CIEV:< call_setup_ind >, < 0 > / +CIEV:< call_ind >, < 0 >
AT cmd:
AT+CLCC: Standard list current calls command
格式:AT+CLCC
+CLCC:Standard list current calls command
格式:+CLCC: < idx >,< dir >,< status >,< mode >,< mpty >,< number >,< type >
HF请求当前的电话信息列表,AG侧通过”+CLCC”回复当前的电话信息列表。如果当前没有电话,AG侧也需回复OK指令。
电话控制功能使用
电话控制
获取手机本机号码(AT+CNUM):
bts2_app_interface获取本地电话号码接口:bt_interface_get_ph_num
bts2_app_hfp_hf获取本地电话号码接口: bt_hfp_hf_at_cnum_send
本机号码信息event:BT_NOTIFY_HF_LOCAL_PHONE_NUMBER
获取本机号码cmd处理结果的消息event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_CNUM)
拨打电话
回拨电话(AT+BLDN)
bts2_app_interface回拨电话接口:bt_interface_start_last_num_dial_req_send
bts2_app_hfp_hf回拨电话接口: bt_hfp_hf_last_num_dial_send
回拨电话处理结果的消息结果event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_BLDN)
通过电话号码拨打电话(ATD10086)
bts2_app_interface电话号码拨打电话接口:bt_interface_hf_out_going_call
bts2_app_hfp_hf电话号码拨打电话接口: bt_hfp_hf_make_call_by_number_send
通过电话号码拨打电话处理结果的消息结果event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_ATD)
获取手机端当前通话中电话的所有信息(AT+CLCC)
bts2_app_interface获取所有电话信息接口:bt_interface_get_remote_ph_num
bts2_app_hfp_hf中获取所有电话信息接口: bt_hfp_hf_at_clcc_send
电话的状态信息event:BT_NOTIFY_HF_REMOTE_CALL_INFO_IND进行通知
获取当前通话中电话的信息cmd处理结果event:BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_CLCC)
// step1: 当HF与AG连接成功之后,可以通过bt_interface_get_ph_num获取AG端电话号码
// step2: 当AG通过+CNUM将本机号码发送到HF,以及对应OK。
// step3: HF会收到本地号码(BT_NOTIFY_HF_LOCAL_PHONE_NUMBER),以及BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_CNUM)处理结果
// AG端不一定会有本机号码发送过来,但是一定会有BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_CNUM) event
//step4: 拨打电话时,将号码长度和号码传入bt_interface_hf_out_going_call
//step5: AG收到电话号码请求之后,先将处理结果BT_NOTIFY_HF_AT_CMD_CFM中cmd_id(HFP_HF_AT_ATD)发送给HF
//step6: 如果拨打电话成功,HF侧会在这个event之后,收到BT_NOTIFY_HF_INDICATOR_UPDATE
//step7: 用户收到BT_NOTIFY_HF_INDICATOR_UPDATE之后,可以通过bt_interface_get_remote_ph_num获取当前电话的所有信息
//step8:AG侧通过"+CLCC"回复当前的电话信息列表。如果当前没有电话,AG侧也需回复OK指令。
//step9: HF收到信息之后,会通过event:BT_NOTIFY_HF_REMOTE_CALL_INFO_IND,用户可以处理该消息
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_HFP_HF:
{
bt_sifli_notify_hfp_hf_event_hdl(event_id, data, data_len);
}
break;
}
return 0;
}
int bt_sifli_notify_hfp_hf_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
case BT_NOTIFY_HF_INDICATOR_UPDATE:
{
//handle msg
break;
}
case BT_NOTIFY_HF_CALL_STATUS_UPDATE:
{
//handle msg
break;
}
case BT_NOTIFY_HF_REMOTE_CALL_INFO_IND:
{
//handle msg
break;
}
case BT_NOTIFY_HF_LOCAL_PHONE_NUMBER:
{
//handle msg
break;
}
case BT_NOTIFY_HF_AT_CMD_CFM:
{
//handle at cmd result msg(bt_notify_at_cmd_cfm_t *)
//cmd_id:HFP_HF_AT_CLCC
//cmd_id:HFP_HF_AT_ATD
//cmd_id:HFP_HF_AT_BLDN
//cmd_id:HFP_HF_AT_CNUM
break;
}
}
return 0;
}
备注
注意:HF部分可扩展的接口在bts2_app_hfp_hf中,用户可以根据需求进行功能扩展,将接口按照需求在interface里进行封装。 另外每个cmd发送之后需等待cmd_cfm的消息,避免协议栈消息队列太多,触发保护机制。
HFP_HF通话功能使用demo
首先在工程初始化时,注册接收notify event 的处理函数
输入需要连接手机的mac地址,等待连接成功的消息
收到连接成功之后,输入拨打电话的号码以及长度
//register notify event handle function start
// HF侧收到AG侧处理 at cmd id的处理结果:0(成功)1(失败) 2(超时,没有收到AG端回复)
static void bt_sifli_notify_hdl_at_cmd(uint8_t cmd_id, uint8_t res)
{
switch (cmd_id)
{
//(语音识别cmd处理结果)
case HFP_HF_AT_BVRA:
{
break;
}
//(获取当前电话信息列表处理完成)
case HFP_HF_AT_CLCC:
{
//step5.request phone call information complete then hangup call
bt_interface_handup_call();
break;
}
//(AG侧处理拨打电话请求结果)
case HFP_HF_AT_ATD:
{
//step2.make a call request result
break;
}
//(AG侧处理回拨电话请求结果)
case HFP_HF_AT_BLDN:
{
break;
}
//(AG侧DTMF语音按键处理结果)
case HFP_HF_AT_VTS:
{
break;
}
//(AG侧音量控制处理结果)
case HFP_HF_AT_VGS:
{
break;
}
//(AG挂断电话处理结果)
case HFP_HF_AT_CHUP:
{
//step6.hangup call over and recv phone call status change:BT_NOTIFY_HF_INDICATOR_UPDATE
break;
}
default:
break;
}
}
int bt_sifli_notify_hfp_hf_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
// SLC CONNECTED
case BT_NOTIFY_HF_PROFILE_CONNECTED:
{
bt_notify_profile_state_info_t *profile_info = (bt_notify_profile_state_info_t *)data;
//step1.make a call request
char *phone_number = "10086";
bt_interface_hf_out_going_call(strlen(phone_number),phone_number);
break;
}
//SLC DISCONNECTED
case BT_NOTIFY_HF_PROFILE_DISCONNECTED:
{
bt_notify_profile_state_info_t *profile_info = (bt_notify_profile_state_info_t *)data;
break;
}
// notify AG是否支持语音识别功能
case BT_NOTIFY_HF_VOICE_RECOG_CAP_UPDATE:
{
break;
}
// notify AG语音识别功能状态
case BT_NOTIFY_HF_VOICE_RECOG_STATUS_CHANGE:
{
break;
}
// notify 本机号码
case BT_NOTIFY_HF_LOCAL_PHONE_NUMBER:
{
break;
}
// notify 当前电话所有信息
case BT_NOTIFY_HF_REMOTE_CALL_INFO_IND:
{
bt_notify_clcc_ind_t *clcc_info = (bt_notify_clcc_ind_t *)data;
//step4.recv phone call information
break;
}
// 音量发生变化
case BT_NOTIFY_HF_VOLUME_CHANGE:
{
break;
}
// 所有电话状态
case BT_NOTIFY_HF_CALL_STATUS_UPDATE:
{
bt_notify_all_call_status *call_status = (bt_notify_all_call_status *)data;
break;
}
// 电话状态发生变化
case BT_NOTIFY_HF_INDICATOR_UPDATE:
{
bt_notify_cind_ind_t *cind_status = (bt_notify_cind_ind_t *)data;
//step3.recv phone call status change and then get call information
bt_interface_get_remote_call_status();
break;
}
case BT_NOTIFY_HF_AT_CMD_CFM:
{
bt_notify_at_cmd_cfm_t *at_cmd_cfm = (bt_notify_at_cmd_cfm_t *) data;
bt_sifli_notify_hdl_at_cmd(at_cmd_cfm->at_cmd_id, at_cmd_cfm->res);
break;
}
default:
return -1;
}
return 0;
}
static int bt_sifli_notify_common_event_hdl(uint16_t event_id, uint8_t *data, uint16_t data_len)
{
switch (event_id)
{
//bt功能开启成功,可以正常使用
case BT_NOTIFY_COMMON_BT_STACK_READY:
{
break;
}
//bt关闭成功
case BT_NOTIFY_COMMON_CLOSE_COMPLETE:
{
break;
}
// ACL 连接成功
case BT_NOTIFY_COMMON_ACL_CONNECTED:
{
bt_notify_device_acl_conn_info_t *acl_info = (bt_notify_device_acl_conn_info_t *) data;
//device acl connected
break;
}
// ACL 断开连接成功
case BT_NOTIFY_COMMON_ACL_DISCONNECTED:
{
bt_notify_device_base_info_t *device_info = (bt_notify_device_base_info_t *)data;
//device acl disconnected
break;
}
// SCO 连接成功
case BT_NOTIFY_COMMON_SCO_CONNECTED:
{
bt_notify_device_sco_info_t *sco_info = (bt_notify_device_sco_info_t *)data;
break;
}
// SCO 断开连接成功
case BT_NOTIFY_COMMON_SCO_DISCONNECTED:
{
bt_notify_device_sco_info_t *sco_info = (bt_notify_device_sco_info_t *)data;
break;
}
default:
return -1;
}
return 0;
}
static int bt_notify_handle(uint16_t type, uint16_t event_id, uint8_t *data, uint16_t data_len)
{
int ret = -1;
switch (type)
{
case BT_NOTIFY_COMMON:
{
ret = bt_sifli_notify_common_event_hdl(event_id, data, data_len);
}
break;
case BT_NOTIFY_HFP_HF:
{
bt_sifli_notify_hfp_hf_event_hdl(event_id, data, data_len);
}
break;
default:
break;
}
return 0;
}
int app_bt_notify_init(void)
{
bt_interface_register_bt_event_notify_callback(bt_notify_handle);
return BT_EOK;
}
INIT_ENV_EXPORT(app_bt_notify_init);
//register notify event handle function end
// start connect with phone:001bdcf4b6bd
unsigned char mac[6] = {0x00,0x1b,0xdc,0xf4,0xb6,0xbd}
bt_interface_conn_ext((unsigned char *)(mac), BT_PROFILE_HFP);
//