您的位置:首页 > 产品设计 > UI/UE

android bluedroid 协议栈里面的各个组件之间的消息处理机制

2016-07-04 15:11 525 查看

1.  蓝牙协议栈里面的各组件的通信是通过消息队列,例如:
btu_task 和bta直接就是通过队列bt/stack/btu/btu_task.c

// Communication queue between btu_task and bta.
extern fixed_queue_t *btu_bta_msg_queue;

这个队列的初始化在
bt/stack/btu/btu_init.c

void BTU_StartUp(void)
{
    memset (&btu_cb, 0, sizeof (tBTU_CB));
    btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL;

    btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);
    if (btu_bta_msg_queue == NULL)
        goto error_exit;

之后需要在btu初始化的时候,把这个队列和相关的线程关联起来,这样发送完消息后,就可以通知相关的线程去队列里面取消息并进行处理
在文件bt/stack/btu/btu_task.c,

void btu_task_start_up(UNUSED_ATTR void *context) {

..................

  fixed_queue_register_dequeue(btu_bta_msg_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_bta_msg_ready,
      NULL);

然后在各个profile使用的话就是通过入列的方式

在bt/bta/sys/bta_sys_main.c中,

void bta_sys_sendmsg(void *p_msg)
{
    // There is a race condition that occurs if the stack is shut down while
    // there is a procedure in progress that can schedule a task via this
    // message queue. This causes |btu_bta_msg_queue| to get cleaned up before
    // it gets used here; hence we check for NULL before using it.
    if (btu_bta_msg_queue)
        fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
}

一般一些profile的消息通过调用如上的方法来发送消息,例如:
HH的profile里面的添加一个虚拟的HID设备的时候,

void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
                  UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
{
    tBTA_HH_MAINT_DEV    *p_buf;
    UINT16  len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;

    p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf(len);

    if (p_buf != NULL)
    {
        memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));

        p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
        p_buf->sub_event            = BTA_HH_ADD_DEV_EVT;
        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;

        p_buf->attr_mask            = (UINT16) attr_mask;
        p_buf->sub_class            = sub_class;
        p_buf->app_id               = app_id;
        bdcpy(p_buf->bda, bda);

        memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
        if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list)
        {
            p_buf->dscp_info.descriptor.dl_len =  dscp_info.descriptor.dl_len;
            p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
            memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
        }
        else
        {
            p_buf->dscp_info.descriptor.dsc_list = NULL;
            p_buf->dscp_info.descriptor.dl_len = 0;
        }

        bta_sys_sendmsg(p_buf);
    }
}

发送完消息到队列后,相关联的线程就会收到这个消息,就行处理,
在bt/stack/btu/btu_task.c中,在这个函数里面就出列,并把相关的消息就行处理,

void btu_bta_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
    BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
    bta_sys_event(p_msg);
}

在bt/bta/sys/bta_sys_main.c中,

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) // 假如调用相关的evt_hdlr成功,则free相关的buf
    {
        GKI_freebuf(p_msg);
    }

}

如上的(*bta_sys_cb.reg[id]->evt_hdlr)这个函数指针是在各个profile初始化的时候赋值的,

各个profile调用如下的函数来进行注册的,在bt/bta/sys/bta_sys_main.c

void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
    bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
    bta_sys_cb.is_reg[id] = TRUE;
}

比如HH的,在bt/bta/hh/bta_hh_api.c中,

void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
{
    tBTA_HH_API_ENABLE *p_buf;

    /* register with BTA system manager */
    bta_sys_register(BTA_ID_HH, &bta_hh_reg);

    LOG_INFO("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
    p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));

    if (p_buf != NULL)
    {
        memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));

        p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
        p_buf->p_cback = p_cback;
        p_buf->sec_mask = sec_mask;

        bta_sys_sendmsg(p_buf);
    }
}

它会注册一个evt_hdlr,那就是bta_hh_reg这个结构体里面的bta_hh_hdl_event

static const tBTA_SYS_REG bta_hh_reg =
{
    bta_hh_hdl_event,
    BTA_HhDisable
};

那么如上的bta_sys_event接受到HH发出的消息后就会调用bta_hh_hdl_event来解析消息并进行处理
在文件bt/bta/hh/bta_hh_main.c中,

BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
    UINT8           index = BTA_HH_IDX_INVALID;
    tBTA_HH_DEV_CB *p_cb = NULL;

    switch (p_msg->event)
    {
        case BTA_HH_API_ENABLE_EVT:
            bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
            break;

        case BTA_HH_API_DISABLE_EVT:
            bta_hh_api_disable();
            break;

        case BTA_HH_DISC_CMPL_EVT:          /* disable complete */
            bta_hh_disc_cmpl();
            break;

        default:
            /* all events processed in state machine need to find corresponding
                CB before proceed */
            if (p_msg->event == BTA_HH_API_OPEN_EVT)
            {
                index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
            }
            else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT)
            {
                /* if add device */
                if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT)
                {
                    index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
                }
                else /* else remove device by handle */
                {
                    index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
// btla-specific ++
                    /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
                      * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
                      * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
                      * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
                      * force the index to be IDX_INVALID
                      */
                    if ((index != BTA_HH_IDX_INVALID) &&
                        (bta_hh_cb.kdev[index].in_use == FALSE)) {
                        index = BTA_HH_IDX_INVALID;
                    }
// btla-specific --
                }
            }
            else if (p_msg->event == BTA_HH_INT_OPEN_EVT)
            {
                index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
            }
            else
                index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);

            if (index != BTA_HH_IDX_INVALID)
                p_cb = &bta_hh_cb.kdev[index];

#if BTA_HH_DEBUG
            APPL_TRACE_DEBUG("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
#endif
            bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
    }
    return (TRUE);
}

有一部分的事件是在如上的函数bta_hh_hdl_event中处理的,而还有一部分的事件是在HH 的状态机里面处理的,
 比如发送事件BTA_HH_API_WRITE_DEV_EVT,就是在状态机里面处理的,

static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
                                 UINT16 data, UINT8 rpt_id, BT_HDR  *p_data)
{
    tBTA_HH_CMD_DATA *p_buf;
    UINT16          len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );

    if ((p_buf = (tBTA_HH_CMD_DATA *)GKI_getbuf(len))!= NULL)
    {
        memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));

        p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
        p_buf->t_type   = t_type;
        p_buf->data     = data;
        p_buf->param    = param;
        p_buf->p_data   = p_data;
        p_buf->rpt_id   = rpt_id;

        bta_sys_sendmsg(p_buf);
    }
}

首先要根据index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);找到index索引,然后再找到对应的p_cb
= &bta_hh_cb.kdev[index];之后再调用状态机进行处理了,

**
*******************************************************************************/
void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data)
{
    tBTA_HH_ST_TBL  state_table;
    UINT8           action;
    tBTA_HH         cback_data;
    tBTA_HH_EVT     cback_event = 0;
#if BTA_HH_DEBUG == TRUE
    tBTA_HH_STATE   in_state ;
    UINT16          debug_event = event;
#endif

    memset(&cback_data, 0, sizeof(tBTA_HH));

    /* handle exception, no valid control block was found */
    if (!p_cb)
    {
        /* BTA HH enabled already? otherwise ignore the event although it's bad*/
        if (bta_hh_cb.p_cback != NULL)
        {
            switch (event)
            {
            /* no control block available for new connection */
            case BTA_HH_API_OPEN_EVT:
                cback_event = BTA_HH_OPEN_EVT;
                /* build cback data */
                bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
                cback_data.conn.status  = BTA_HH_ERR_DB_FULL;
                cback_data.conn.handle  = BTA_HH_INVALID_HANDLE;
                break;
            /* DB full, BTA_HhAddDev */
            case BTA_HH_API_MAINT_DEV_EVT:
                cback_event = p_data->api_maintdev.sub_event;

                if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
                {
                    bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
                    cback_data.dev_info.status    = BTA_HH_ERR_DB_FULL;
                    cback_data.dev_info.handle    = BTA_HH_INVALID_HANDLE;
                }
                else
                {
                    cback_data.dev_info.status    = BTA_HH_ERR_HDL;
                    cback_data.dev_info.handle    = (UINT8)p_data->api_maintdev.hdr.layer_specific;
                }
                break;
            case BTA_HH_API_WRITE_DEV_EVT:
                cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
                        BTA_HH_FST_TRANS_CB_EVT;
                if (p_data->api_sndcmd.p_data != NULL)
                {
                    GKI_freebuf(p_data->api_sndcmd.p_data);
                }
                if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
                    p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
                    p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
                {
                    cback_data.dev_status.status = BTA_HH_ERR_HDL;
                    cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
                }
                else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
                    p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
                {
                    cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
                    cback_data.hs_data.status = BTA_HH_ERR_HDL;
                    /* hs_data.rsp_data will be all zero, which is not valid value */
                }
                else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
                         p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
                {
                    cback_data.status = BTA_HH_ERR_HDL;
                    cback_event = BTA_HH_VC_UNPLUG_EVT;
                }
                else
                    cback_event = 0;
                break;

            case BTA_HH_API_CLOSE_EVT:
                cback_event = BTA_HH_CLOSE_EVT;

                cback_data.dev_status.status = BTA_HH_ERR_HDL;
                cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
                break;

            default:
                /* invalid handle, call bad API event */
                APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
                /* Free the callback buffer now */
                if (p_data != NULL && p_data->hid_cback.p_data != NULL)
                {
                    GKI_freebuf(p_data->hid_cback.p_data);
                    p_data->hid_cback.p_data = NULL;
                }
                break;
            }
           if (cback_event)
               (* bta_hh_cb.p_cback)(cback_event, &cback_data);
        }
    }
    /* corresponding CB is found, go to state machine */
    else
    {
#if BTA_HH_DEBUG == TRUE
        in_state = p_cb->state;
        APPL_TRACE_EVENT("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
                          in_state, bta_hh_state_code(in_state),
                          bta_hh_evt_code(debug_event));
#endif

        if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST))
        {
            APPL_TRACE_ERROR("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d",
                              p_cb->state,event);
            return;
        }
        state_table = bta_hh_st_tbl[p_cb->state - 1];

        event &= 0xff;

        p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;

        if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
        {
            (*bta_hh_action[action])(p_cb, p_data);
        }

#if BTA_HH_DEBUG == TRUE
        if (in_state != p_cb->state)
        {
            APPL_TRACE_DEBUG("HH State Change: [%s] -> [%s] after Event [%s]",
                          bta_hh_state_code(in_state),
                          bta_hh_state_code(p_cb->state),
                          bta_hh_evt_code(debug_event));
        }
#endif
    }

    return;

    return;
}

最后会调用bta_hh_action这个函数数组里面的相关函数,bta_hh_write_dev_act,这个函数执行完成之后,就到

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) // 假如调用相关的evt_hdlr成功,则free相关的buf

    {

        GKI_freebuf(p_msg);

    }

}

=======>如上的BTA_HH_API_WRITE_DEV_EVT这个事件的调用流程如下:

1. bta_sys_sendmsg(p_buf);先通过bta
sys发送消息

2. 消息入列后调用了btu_bta_msg_ready将消息出列

3.
调用bta_sys_event(p_msg)处理消息

4.
根据不同的profile的消息会在bta sys系统里面寻找到相应的事件处理器evt_hdlr,而如上的事件是HH的,那么HH在bta初始化的时候

会调用 bta_sys_register
注册 bta_hh_reg的成员bta_hh_hdl_event作为evt_hdlr

5.
 bta_hh_hdl_event最后在状态机里面调用了bta_hh_write_dev_act这个函数,然后最后返回为true,即freebuf=true

6. 上面的调用完成后会free之前使用sendmsg申请的p_buf

=======================================================================================================

bta_hh_cb.p_cback这个结构体成员变量的赋值是调用了如下的方法:

在文件bta_hh_act.c中,

void bta_hh_api_enable(tBTA_HH_DATA *p_data)
{
    tBTA_HH_STATUS      status = BTA_HH_ERR;
    UINT8               xx;

    /* initialize BTE HID */
    HID_HostInit();

    memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));

    HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);

    /* Register with L2CAP */
    if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
    {
        /* store parameters */
        bta_hh_cb.p_cback = p_data->api_enable.p_cback;

        status = BTA_HH_OK;
        /* initialize device CB */
        for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
        {
            bta_hh_cb.kdev[xx].state        = BTA_HH_IDLE_ST;
            bta_hh_cb.kdev[xx].hid_handle   = BTA_HH_INVALID_HANDLE;
            bta_hh_cb.kdev[xx].index        = xx;
        }

        /* initialize control block map */
        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
            bta_hh_cb.cb_index[xx]          = BTA_HH_IDX_INVALID;
    }

#if (BTA_HH_LE_INCLUDED == TRUE)
    if (status == BTA_HH_OK)
    {
        bta_hh_le_enable();
    }
    else
#endif
        /* signal BTA call back event */
        (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
}

那bta_hh_api_enable()方法又是如下的方法调用的,在文件bta_hh_main.c中,

BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
    UINT8           index = BTA_HH_IDX_INVALID;
    tBTA_HH_DEV_CB *p_cb = NULL;

    switch (p_msg->event)
    {
        case BTA_HH_API_ENABLE_EVT:
            bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
            break;

那上面的case又是BTA_HhEnable()这个方法发出的msg触发的,

void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
{
    tBTA_HH_API_ENABLE *p_buf;

    /* register with BTA system manager */
    bta_sys_register(BTA_ID_HH, &bta_hh_reg);

    LOG_INFO("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
    p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));

    if (p_buf != NULL)
    {
        memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));

        p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
        p_buf->p_cback = p_cback;
        p_buf->sec_mask = sec_mask;

        bta_sys_sendmsg(p_buf);
    }
}

上面的BTA_HhEnable的方法又是btif/src/btif_hh.c里面的方法btif_hh_execute_service()调用的,如下:

bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
{
     if (b_enable)
     {
          /* Enable and register with BTA-HH */
          BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt);
     }
     else {
         /* Disable HH */
         BTA_HhDisable();
     }
     return BT_STATUS_SUCCESS;
}

那么可以看出那个bta_hh_cb.p_cback函数指针所指向的函数就是bte_hh_evt,这个函数又是在btif/src/btif_hh.c里面的定义的,

static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
{
    bt_status_t status;
    int param_len = 0;

    if (BTA_HH_ENABLE_EVT == event)
        param_len = sizeof(tBTA_HH_STATUS);
    else if (BTA_HH_OPEN_EVT == event)
        param_len = sizeof(tBTA_HH_CONN);
    else if (BTA_HH_DISABLE_EVT == event)
        param_len = sizeof(tBTA_HH_STATUS);
    else if (BTA_HH_CLOSE_EVT == event)
        param_len = sizeof(tBTA_HH_CBDATA);
    else if (BTA_HH_GET_DSCP_EVT == event)
        param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
    else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event)|| (BTA_HH_GET_IDLE_EVT == event))
        param_len = sizeof(tBTA_HH_HSDATA);
    else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) || (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
        param_len = sizeof(tBTA_HH_CBDATA);
    else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event) )
        param_len = sizeof(tBTA_HH_DEV_INFO);
    else if (BTA_HH_API_ERR_EVT == event)
        param_len = 0;
    /* switch context to btif task context (copy full union size for convenience) */
    status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);

    /* catch any failed context transfers */
    ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}

之后就会调用static void btif_hh_upstreams_evt(UINT16 event, char* p_param)来通过回调(callback)上报告相关的事件,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android bluedroid bt