android HFPclient的相关分析
Posted Fresh_Air_Life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android HFPclient的相关分析相关的知识,希望对你有一定的参考价值。
在高通平台和三星平台上调过这个功能,基于安卓6.0,该功能是将手机上的蓝牙功能用成和蓝牙耳机一样的功能。蓝牙电话和蓝牙音乐它们之间的差异较大,蓝牙电话要求实时性比较高,其和A2DP使用的物理通路并不一致,蓝牙电话走pcm物理通路,而蓝牙音乐走uart通路。
关键词
Hfpclient BT SCO ATA command
在调试该功能时,最好能先测试一下,如下信号指标是否符合要求,以免带来卡顿和断连等不可靠因素。
此外,还要测试频偏,其晶振以及外围的电容等器件也会影响,一般在正负10之内,否则也可能会导致卡顿或断连等现象。
开启HFP client支持
首先将hfp client角色功能打开。
packages/apps/Bluetooth/res/values/config.xml
<bool name="profile_supported_hs_hfp">false</bool>
<bool name="profile_supported_hfpclient">true</bool>
首先将hfp client角色功能打开。
修改后以支持电话功能,但是手机连接后会断开,并有如下错误信息:
01-12 17:51:58.850 3319 3572 E bt_rfcomm: PORT_DataInd, p_port:0xe2ece48c, p_data_co_callback is null
01-12 17:51:58.850 3319 3572 E bt_btif : HFPClient: Failed to create SLC due to AT error, disconnecting (2)
截屏如下:
出错信息提示是
01-12 17:51:58.850 3319 3572 E bt_rfcomm: PORT_DataInd, p_port:0xe2ece48c, p_data_co_callback is null
01-12 17:51:58.850 3319 3572 E bt_btif : HFPClient: Failed to create SLC due to AT error, disconnecting (2)
这是提示AT命令错误,蓝牙电话使用AT命令子集。这是因为不支持codec negotiate特点,修改如下:
system/bt/bta/hf_client/bta_hf_client_at.c
static void bta_hf_client_handle_brsf(UINT32 value)
APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, value);
- bta_hf_client_cb.scb.peer_features = value;
+ bta_hf_client_cb.scb.peer_features = value & ~0x200;
到这里应该有蓝牙提示音出现了。也就是蓝牙的呼叫事件能够正常响应了,但是呼叫响应是通过UART走的是AT command协议,提示音是hfp client自带的。
codec negotiate是为了支持宽带语音信号,支持16KHz的语音信号,在支持这一feature时,hfpclient和设备之间会进行协商,以期望使用wbs方式数据。
HeadsetClientStateMachine.java
如果想更改蓝牙提示音,修改如下文件;
@@ -126,7 +126,7 @@ final class HeadsetClientStateMachine extends StateMachine
private int mIndicatorCallHeld;
private boolean mVgsFromStack = false;
private boolean mVgmFromStack = false;
- private Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
+ private Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
有+++号的是调试信息,Enter AudioOn是进入蓝牙电话的语音了,可以看到语音的采样率是8KHz。
蓝牙语音的物理通路
正如开篇提到的,语音数据不走UART,而是走PCM或者IIS,这一信息在:
hardware/broadcom/libbt/src/hardware.c
当然高通平台未使用博通的芯片时,不会有这个问题,而且目录和代码的差异性也非常大,基本上高通将底层细节都屏蔽了,走高通adsp通路时,开发者甚至都不需要关系语音走的底层物理通路。
<code class="language-plain">#define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E
#define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D
#define HCI_VSC_ENABLE_WBS 0xFC7E</code>
这是三星平台使用博通芯片定义的数据格式,这在使用btsnoop工具抓数据时,可以看到这类的命令。btsnoop抓到的数据可以使用comprobe工具进行解析查看。
#define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C
/* do we need this VSC for I2S??? */
UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
*p++ = SCO_PCM_PARAM_SIZE;
memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
ALOGI("SCO PCM configure 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3],
bt_sco_param[4]);
if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf,
hw_sco_i2spcm_cfg_cback)) == FALSE)
bt_vendor_cbacks->dealloc(p_buf);
else
return;
如果是基于手机方案的,基本以上设置基本就可以了。手机方案的图如下(略去了基带)
但是如果BT的PCM没有和codec直接连接,而是像UART一样和AP直接相连接,这样就要涉及到驱动的改动了。
首先ap侧需要编写驱动程序以将codec实现的功能由ap完成,并且,codec和headset设备的连接也变成了ap和headset设备的连接,这样就存在对audiopolicy的部分了,毕竟最基本的是audio engin对audio device的选择,由于是通话场景,需要使用low latency buffer,或之类似的,AOSP中就有这一类。gao 高通的ADSP也有从硬件到软件的架构支持。
内核的修改涉及的是alsa驱动的编写,主要包括设备树,pcm驱动,machine驱动以及bt虚拟出来的codec驱动,因为bt的硬件配置等在安卓6.0时放在了蓝牙协议栈中,所以这里使用虚拟codec实现是一个好的解决方案。
1)hardware/broadcom/libbt/include/vnd_avl8890.txt
SCO_I2SPCM_IF_ROLE = 1
SCO_PCM_IF_CLOCK_MODE = 1
SCO_PCM_IF_SYNC_MODE = 1
1改成0 --》0是slave,1是master
2)上面txt里的flag最终影响bt_vendor_brcm.h,需要检查里面的bt设置跟AP侧PCM设置是否一样
如:
/* PCM_DATA_FMT_SHIFT_MODE 0 : MSB first 1 : LSB first */
#ifndef PCM_DATA_FMT_SHIFT_MODE
#define PCM_DATA_FMT_SHIFT_MODE 0
#endif</code>
以上是关于android HFPclient的相关分析的主要内容,如果未能解决你的问题,请参考以下文章
android5.0(Lollipop) BLE Peripheral牛刀小试