蓝牙inquiry流程之Inquiry Complete处理

inquiry流程一般持续有12s多,当inquiry完成的时候,设备端会上报一个Event: Inquiry Complete 上来,那协议栈是如何把这个事件上传到应用层的呢?本篇文章来分析一下其具体的流程。

void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
{
    UINT8   *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
    UINT8   hci_evt_code, hci_evt_len;
    STREAM_TO_UINT8  (hci_evt_code, p);
    STREAM_TO_UINT8  (hci_evt_len, p);
    switch (hci_evt_code)
    {
        case HCI_INQUIRY_COMP_EVT:
            btu_hcif_inquiry_comp_evt (p);
            break;
...

看btu_hcif_inquiry_comp_evt 的实现:

static void btu_hcif_inquiry_comp_evt (UINT8 *p)
{
    UINT8   status;
    STREAM_TO_UINT8    (status, p);
    /* Tell inquiry processing that we are done */
    btm_process_inq_complete(status, BTM_BR_INQUIRY_MASK);
}

继续看btm_process_inq_complete 的实现:

其中:

#define BTM_BR_INQUIRY_MASK         (BTM_GENERAL_INQUIRY | BTM_LIMITED_INQUIRY)

btm_process_inq_complete 其实现在btm_inq.c里面:

void btm_process_inq_complete (UINT8 status, UINT8 mode)
{
    tBTM_CMPL_CB        *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb;
    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
...
        btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);//往上层汇报
...

主要是看btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT); 做的事情:

其实现btm_acl.c:

void btm_acl_update_busy_level (tBTM_BLI_EVENT event)
{
    tBTM_BL_UPDATE_DATA  evt;
    UINT8 busy_level;
    BTM_TRACE_DEBUG ("btm_acl_update_busy_level");
    BOOLEAN old_inquiry_state = btm_cb.is_inquiry;
    switch (event)
    {
...
        case BTM_BLI_INQ_DONE_EVT:
            BTM_TRACE_DEBUG ("BTM_BLI_INQ_DONE_EVT");
            btm_cb.is_inquiry = FALSE;
            evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
            break;
    }
...
    if ((busy_level != btm_cb.busy_level) ||(old_inquiry_state != btm_cb.is_inquiry))
    {
        evt.event         = BTM_BL_UPDATE_EVT;
        evt.busy_level    = busy_level;
        btm_cb.busy_level = busy_level;
        if (btm_cb.p_bl_changed_cb && (btm_cb.bl_evt_mask & BTM_BL_UPDATE_MASK))
        {
            (*btm_cb.p_bl_changed_cb)((tBTM_BL_EVENT_DATA *)&evt);
        }
    }
}

可以看出,主要做的事情是组建一个evt:

evt.event = BTM_BL_UPDATE_EVT;
evt.busy_level = busy_level;

evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;

然后调用 (*btm_cb.p_bl_changed_cb)((tBTM_BL_EVENT_DATA *)&evt);

看看这个回调函数是在哪里注册的呢?

在btm_acl.c有个注册函数:

tBTM_STATUS BTM_RegBusyLevelNotif (tBTM_BL_CHANGE_CB *p_cb, UINT8 *p_level,
                                   tBTM_BL_EVENT_MASK evt_mask)
{
...
btm_cb.bl_evt_mask = evt_mask; ... btm_cb.p_bl_changed_cb = p_cb;//保存回调 return(BTM_SUCCESS); }

发现该函数是在bta_dm_sys_hw_cback里面注册的:

BTM_RegBusyLevelNotif (bta_dm_bl_change_cback, NULL, BTM_BL_UPDATE_MASK|BTM_BL_ROLE_CHG_MASK);

我们发现这个回调函数就是bta_dm_bl_change_cback ,其实现在bta_dm_act.c中:

根据上面的分析,我们知道这次传入的event = BTM_BL_UPDATE_EVT; 

static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
{
    tBTA_DM_ACL_CHANGE * p_msg;
    if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
    {
        p_msg->event = p_data->event;.//继承上面event
        p_msg->is_new = FALSE;//is_new = false
        switch(p_msg->event)
        {
...
        case BTM_BL_UPDATE_EVT:
            p_msg->busy_level = p_data->update.busy_level;
            p_msg->busy_level_flags = p_data->update.busy_level_flags;
            break;
...
      }
        p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
        bta_sys_sendmsg(p_msg);
    }

}

观其实现,还是组建了一个 tBTA_DM_ACL_CHANGE 这样的事件,然后发送到btu 线程:

p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;

p_msg->event = p_data->event = BTM_BL_UPDATE_EVT; 
p_msg->is_new = FALSE;

这边追踪一下代码,处理这个BTA_DM_ACL_CHANGE_EVT的函数是:

/*******************************************************************************
**
** Function         bta_dm_acl_change
**
** Description      Process BTA_DM_ACL_CHANGE_EVT
**
**
** Returns          void
**
*******************************************************************************/
void bta_dm_acl_change(tBTA_DM_MSG *p_data)
{
    UINT8 i;
    UINT8 *p;
    tBTA_DM_SEC conn;
    BOOLEAN is_new = p_data->acl_change.is_new;
    BD_ADDR_PTR     p_bda = p_data->acl_change.bd_addr;
    BOOLEAN         need_policy_change = FALSE;
    BOOLEAN         issue_unpair_cb = FALSE;

    tBTA_DM_PEER_DEVICE *p_dev;
    memset(&conn, 0, sizeof(tBTA_DM_SEC));

    switch(p_data->acl_change.event)
    {
    case BTM_BL_UPDATE_EVT:     /* busy level update */
        if( bta_dm_cb.p_sec_cback )
        {
            conn.busy_level.level = p_data->acl_change.busy_level;
            conn.busy_level.level_flags = p_data->acl_change.busy_level_flags;
            bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);//回调到上层
        }
        return;
...

这边的核心代码还是组建事件往上层回调,:

conn.busy_level.level = p_data->acl_change.busy_level;
conn.busy_level.level_flags = p_data->acl_change.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);

那我们现在看看bta_dm_cb.p_sec_cback 这个回调函数是在哪里注册的:

void bta_dm_enable(tBTA_DM_MSG *p_data){
...
    /* first, register our callback to SYS HW manager */
    bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
    bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;//注册回调
...
}

发现是在bta_dm_enable 里面注册的,也就是在tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback) 传入的回调函数:

void btif_init_ok(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param) {
  BTIF_TRACE_DEBUG("btif_task: received trigger stack init event");
#if (BLE_INCLUDED == TRUE)
  btif_dm_load_ble_local_keys();
#endif
  BTA_EnableBluetooth(bte_dm_evt);//这里注册
}

那我们知道上面回调的内容如下:

conn.busy_level.level = p_data->acl_change.busy_level;
conn.busy_level.level_flags = p_data->acl_change.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
bte_dm_evt(BTA_DM_BUSY_LEVEL_EVT, &conn);

,下面继续分析bte_dm_evt:

void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data)
{
    /* switch context to btif task context (copy full union size for convenience) */
    bt_status_t status = btif_transfer_context(btif_dm_upstreams_evt, (uint16_t)event,
                                (void*)p_data, sizeof(tBTA_DM_SEC), btif_dm_data_copy);

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

发现该函数就是一个中转,他把事件交与bt_jni_workqueue_thread 线程中的btif_dm_upstreams_evt 函数去执行了。event从btu task 转换到了bt_jni_workqueue_thread ,我们也能感受到,事件正在一层一层往上面走,

看看btif_dm_upstreams_evt 的实现,这里面肯定也是会去处理各种不同的event:我们这种case 要处理的event = BTA_DM_BUSY_LEVEL_EVT,

/*******************************************************************************
**
** Function         btif_dm_upstreams_cback
**
** Description      Executes UPSTREAMS events in btif context
**
** Returns          void
**
*******************************************************************************/
static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
{
    tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param;
    tBTA_SERVICE_MASK service_mask;
    uint32_t i;
    bt_bdaddr_t bd_addr;
    switch (event)
    {   
     case BTA_DM_BUSY_LEVEL_EVT:
        {
            if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK)
            {
                if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_STARTED)
                {
                       HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                BT_DISCOVERY_STARTED);
                       btif_dm_inquiry_in_progress = TRUE;
                }
                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_CANCELLED)
                {
                       HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                BT_DISCOVERY_STOPPED);
                       btif_dm_inquiry_in_progress = FALSE;
                }
                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_COMPLETE)
                {
                       btif_dm_inquiry_in_progress = FALSE;//设置了这个值
                }
            }
        }

从上面的代码分析,这里做的最重要的一件事就是:

btif_dm_inquiry_in_progress = FALSE;

猜你喜欢

转载自www.cnblogs.com/libs-liu/p/9223989.html