蓝牙HFP协议主要是指HF和AG之间的信令交互,我们知道蓝牙耳机和手机配对之后,耳机会发三个最基本的AT命令,分别是
AT+BRSF, AT+CIND=?, AT+CIND?
协议栈接收AT命令的流程
1 BTA层从rfcomn接收蓝牙耳机发送过来的AT命令,在bta_ag_rfc_data里面会运行一个无线循环,调用PORT_ReadData函数不断的读取AT命令,读取到AT指令后,调用bta_ag_at_parse函数解析AT命令,该函数的功能是用来判断是否是合适的AT命令
void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
UINT16 len;
char buf[BTA_AG_RFC_READ_MAX];
UNUSED(p_data);
memset(buf, 0, BTA_AG_RFC_READ_MAX);
APPL_TRACE_DEBUG("bta_ag_rfc_data");
/* do the following */
for(;;)
{
/* read data from rfcomm; if bad status, we're done */
if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS)
{
break;
}
/* if no data, we're done */
if (len == 0)
{
break;
}
/* run AT command interpreter on data */
bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
bta_ag_at_parse(&p_scb->at_cb, buf, len);
bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
/* no more data to read, we're done */
if (len < BTA_AG_RFC_READ_MAX)
{
break;
}
}
}
2 在bta_ag_at_parse函数里面,如果AT命令正确,就调用bta_ag_process_at函数解析AT命令,如果AT命令正确,就调用callback函数,如代码中的(*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
{
int i = 0;
char* p_save;
if (p_cb->p_cmd_buf == NULL)
{
if ((p_cb->p_cmd_buf = (char *) GKI_getbuf(p_cb->cmd_max_len)) == NULL)
{
APPL_TRACE_ERROR("%s: GKI_getbuf() failed allocation", __func__);
return;
}
p_cb->cmd_pos = 0;
}
for (i = 0; i < len;)
{
while (p_cb->cmd_pos < p_cb->cmd_max_len-1 && i < len)
{
/* Skip null characters between AT commands. */
if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0))
{
i++;
continue;
}
p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
if ( p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n')
{
p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
if ((p_cb->cmd_pos > 2) &&
(p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
(p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
{
p_save = p_cb->p_cmd_buf;
p_cb->p_cmd_buf += 2;
bta_ag_process_at(p_cb);
p_cb->p_cmd_buf = p_save;
}
p_cb->cmd_pos = 0;
}
else if( p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B )
{
p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
(*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
p_cb->cmd_pos = 0;
}
else
{
++p_cb->cmd_pos;
}
}
if (i < len)
p_cb->cmd_pos = 0;
}
}
3 而这个callback函数的初始化是在打开蓝牙后,bta里面的bta_ag_rfc_open函数里面,如下代码所示:
p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service];
const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] =
{
bta_ag_at_hsp_cback,
bta_ag_at_hfp_cback
};
4 所以对于HFP协议,将会调用到bta_ag_at_hfp_cback函数,在这个函数里面,将会对AT命令进行处理.调用btif_context_switched函数将消息传递到btif层,然后通过btif_hf_upstreams_evth函数对消息进行处理,以判断是否上传到
JNI层,进一步上报给APP层。
下面的Log可以印证上面的4步
01-03 21:38:50.500 9401 9447 I bt_btif : bta_sys_event: Event 0x50b
01-03 21:38:50.500 9401 9447 D bt_btif : bta_ag_rfc_data
01-03 21:38:50.500 9401 9447 D bt_btif : bta_ag_at_hfp_cback: AT command 14, arg_type 8, int_arg 0, arg =?
01-03 21:38:50.560 9401 9431 D bt_btif : btif_context_switched for event: 14
01-03 21:38:50.560 9401 9431 D bt_btif : btif_hf_upstreams_evt: event=BTA_AG_AT_CIND_EVT
01-03 21:38:50.560 9401 9431 I bt_btif : HAL bt_hf_callbacks->cind_cmd_cb
01-03 21:38:50.560 9401 9431 D HeadsetStateMachine: Enter onAtCind()
APP下发AT命令到协议栈的流程
以CIND命令为例,看看onAtCind函数,这个函数会发一个EVENT_TYPE_AT_CIND消息,而处理这个消息的函数是processAtCind,而这个processAtCind函数最终会调用一个native方法:cindResponseNative,这个native方法最终会调用到协议栈btif层的cind_response方法,cind_response方法会调用到BTA_AgResult方法
private void onAtCind(byte[] address) {
StackEvent event = new StackEvent(EVENT_TYPE_AT_CIND);
event.device = getDevice(address);
sendMessage(STACK_EVENT, event);
}
private void processAtCind(BluetoothDevice device) {
int call, call_setup;
if(device == null) {
Log.w(TAG, "processAtCind device is null");
return;
}
/* Handsfree carkits expect that +CIND is properly responded to
Hence we ensure that a proper response is sent
for the virtual call too.*/
if (isVirtualCallInProgress()) {
call = 1;
call_setup = 0;
} else {
// regular phone call
call = mPhoneState.getNumActiveCall();
call_setup = mPhoneState.getNumHeldCall();
}
cindResponseNative(mPhoneState.getService(), call,
call_setup, mPhoneState.getCallState(),
mPhoneState.getSignal(), mPhoneState.getRoam(),
mPhoneState.getBatteryCharge(), getByteAddress(device));
}
看看BTA_AgResult方法,这个方法会向BTA发送BTA_AG_API_RESULT_EVT的event,而处理这个event的方法是bta_sys_event
void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data)
{
tBTA_AG_API_RESULT *p_buf;
if ((p_buf = (tBTA_AG_API_RESULT *) GKI_getbuf(sizeof(tBTA_AG_API_RESULT))) != NULL)
{
p_buf->hdr.event = BTA_AG_API_RESULT_EVT;
p_buf->hdr.layer_specific = handle;
p_buf->result = result;
if(p_data)
{
memcpy(&p_buf->data, p_data, sizeof(p_buf->data));
}
bta_sys_sendmsg(p_buf);
}
}
看看bta_sys_event方法,而这个方法里面会调用bta_ag的bta_ag_hdl_event方法进行处理相应的event,而这个event的处理函数是bta_ag_api_result,这个函数向协议栈下发AT命令
void bta_sys_event(BT_HDR *p_msg)
{
UINT8 id;
BOOLEAN freebuf = TRUE;
APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);
/* get subsystem id from event */
id = (UINT8) (p_msg->event >> 8);
/* verify id and call subsystem event handler */
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
{
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
}
else
{
APPL_TRACE_WARNING("BTA got unregistered event id %d", id);
}
if (freebuf)
{
GKI_freebuf(p_msg);
}
}
log印证上述的分析
01-03 21:38:50.560 9401 9453 D bt_btif : BTHF: cind_response
01-03 21:38:50.560 9401 9447 I bt_btif : bta_sys_event: Event 0x506
01-03 21:38:50.560 9401 9447 D bt_btif : bta_ag_hdl_event: Event 0x0506
01-03 21:38:50.560 9401 9447 D bt_btif : bta_ag_api_result: p_scb 0x9a446648
01-03 21:38:50.560 9401 9447 I bt_btif : bta_ag_sm_execute: Handle 0x0001, State 2, Event 0x0506
01-03 21:38:50.560 9401 9447 D bt_btif : bta_ag_hfp_result : res = 3