蓝牙HFP协议AT命令流程

蓝牙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

你可能感兴趣的:(蓝牙HFP协议AT命令流程)