博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
蓝牙inquiry流程之Inquiry Complete处理
阅读量:5771 次
发布时间:2019-06-18

本文共 30429 字,大约阅读时间需要 101 分钟。

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;...#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE)     p_inq->inqparms.mode &= ~(mode);#endif    btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);//向上传递    /* Ignore any stray or late complete messages if the inquiry is not active */    if (p_inq->inq_active)    {        p_inq->inq_cmpl_info.status = (tBTM_STATUS)((status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING);        /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */        if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)//mode前面已经置0        {#if BLE_INCLUDED == TRUE            btm_clear_all_pending_le_entry();//清除还没有活动scan response的设备消息#endif            p_inq->state = BTM_INQ_INACTIVE_STATE;//设置inquiry的状态            /* Increment so the start of a next inquiry has a new count */            p_inq->inq_counter++;//增加搜索的计数            btm_clr_inq_result_flt();            if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&                controller_get_interface()->supports_rssi_with_inquiry_results())            {                btm_sort_inq_result();//根据rssi排序            }            /* Clear the results callback if set */            p_inq->p_inq_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;            p_inq->inq_active = BTM_INQUIRY_INACTIVE;//设置0            p_inq->p_inq_cmpl_cb = (tBTM_CMPL_CB *) NULL;            if (p_inq_cb)//执行回调函数,在bta_dm_search_start 进行注册bta_dm_inq_cmpl_cb                (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);        }    }    if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete    {        p_inq->scan_type = INQ_NONE;//scan_type置0#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)        /* check if the LE observe is pending */        if(p_inq->p_inq_ble_results_cb != NULL)//==NULL        {            BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan");            BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);        }#endif    }}

 

 

这里主要分三部分:

  1. btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT); 向上层汇报状态
  2. 清各种状态标志位
  3. (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);

我们主要看一下第一部分和第三部分:

1.btm_acl_update_busy_level 

其实现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;

第一部分的分析到此结束,下面开始看inquiry结束之后的回调函数:

3.(p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info) = bta_dm_inq_cmpl_cb

 这个回调函数的注册是在 进行搜索的时候:

void bta_dm_search_start (tBTA_DM_MSG *p_data){...        result.status = BTM_StartInquiry(   (tBTM_INQ_PARMS*)&p_data->search.inq_params,                        bta_dm_inq_results_cb,                        (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);...}

 

我们看看bta_dm_inq_cmpl_cb的实现:

/*********************************************************************************** Function         bta_dm_inq_cmpl_cb**** Description      Inquiry complete callback from BTM**** Returns          void*********************************************************************************/static void bta_dm_inq_cmpl_cb (void * p_result){    tBTA_DM_MSG * p_msg;    if (bta_dm_search_cb.cancel_pending == FALSE)    {        p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG));            p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;            p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;            bta_sys_sendmsg(p_msg);            }

 

这里发现是组建了一个msg,然后发送到btu 线程:

p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;

 p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;

BTA_DM_API_SEARCH_EVT = BTA_SYS_EVT_START(BTA_ID_DM_SEARCH),    BTA_DM_API_SEARCH_CANCEL_EVT,    BTA_DM_API_DISCOVER_EVT,    BTA_DM_INQUIRY_CMPL_EVT,//0x203...

 

处理该event 是handler是:

static const tBTA_SYS_REG bta_dm_search_reg ={    bta_dm_search_sm_execute,    bta_dm_search_sm_disable};

bta_dm_search_sm_execute:

BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg){    tBTA_DM_ST_TBL      state_table;    UINT8               action;    int                 i;/* look up the state table for the current state */    state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];    bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];    /* execute action functions */    for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)    {        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)        {            (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);        }    }    return TRUE;}

 

他的处理流程是先找到该状态的table,然后赋值下一个状态,然后根据event 在table中查找该事件应该执行的action,这些action 有函数和他们一一对应,执行这些函数就行。

我们当前的状态是bta_dm_search_search_active_st_table,需要执行的action = BTA_DM_INQUIRY_CMPL,下一个状态依然是BTA_DM_SEARCH_ACTIVE   

我们看看BTA_DM_INQUIRY_CMPL 对应的函数是什么?

/* action function list */const tBTA_DM_ACTION bta_dm_search_action[] ={  bta_dm_search_start,              /* 0 BTA_DM_API_SEARCH */  bta_dm_search_cancel,             /* 1 BTA_DM_API_SEARCH_CANCEL */  bta_dm_discover,                  /* 2 BTA_DM_API_DISCOVER */  bta_dm_inq_cmpl,                  /* 3 BTA_DM_INQUIRY_CMPL */  bta_dm_rmt_name,                  /* 4 BTA_DM_REMT_NAME */

 

看看 回调函数的具体实现:

/*********************************************************************************** Function         bta_dm_inq_cmpl**** Description      Process the inquiry complete event from BTM**** Returns          void*********************************************************************************/void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data){    tBTA_DM_MSG * p_msg;    tBTA_DM_SEARCH  data;    APPL_TRACE_DEBUG("bta_dm_inq_cmpl");    data.inq_cmpl.num_resps = p_data->inq_cmpl.num;    bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);//执行回调,向上层通知    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbFirst()) != NULL)//如果搜索到设备了,对设备做discover的动作    {        /* start name and service discovery from the first device on inquiry result */        bta_dm_search_cb.name_discover_done = FALSE;        bta_dm_search_cb.peer_name[0]       = 0;        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);    }    else //否则结束,向上层传 BTA_DM_SEARCH_CMPL_EVT;    {        /* no devices, search complete */        bta_dm_search_cb.services = 0;        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)        {            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;            bta_sys_sendmsg(p_msg);        }        }    }

 

这一部分的内容也可以分为三部分:

  1. bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);
  2. 有搜索到设备,进行discovery
  3. 没有搜索到设备,上报BTA_DM_SEARCH_CMPL_EVT 

首先来看看 第一部分:

3.1 bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);

bta_dm_search_cb.p_search_cback 在BTA_DmSearch 中赋值的,为bte_search_devices_evt ,我们看看其实现:

/*********************************************************************************** Function         bte_search_devices_evt**** Description      Switches context from BTE to BTIF for DM search events**** Returns          void*********************************************************************************/static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data){    UINT16 param_len = 0;...    btif_transfer_context (btif_dm_search_devices_evt , (UINT16) event, (void *)p_data, param_len,        (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);}

 

发现其直接被transfer 到btif线程 中执行btif_dm_search_devices_evt:

/********************************************************************************** Function         btif_dm_search_devices_evt**** Description      Executes search devices callback events in btif context**** Returns          void********************************************************************************/static void btif_dm_search_devices_evt (UINT16 event, char *p_param){    tBTA_DM_SEARCH *p_search_data;    BTIF_TRACE_EVENT("%s event=%s", __FUNCTION__, dump_dm_search_event(event));    switch (event)    {...        case BTA_DM_INQ_CMPL_EVT://并没有进一步去通知上层        {#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))            tBTA_DM_BLE_PF_FILT_PARAMS adv_filt_param;            memset(&adv_filt_param, 0, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS));            BTA_DmBleScanFilterSetup(BTA_DM_BLE_SCAN_COND_DELETE, 0, &adv_filt_param, NULL,                                     bte_scan_filt_param_cfg_evt, 0);#endif        }         break;        case BTA_DM_DISC_CMPL_EVT:        {            HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED);//如果是BTA_DM_DISC_CMPL_EVT:会进一步通知上层        }        break;

 

这里发现,BTA_DM_INQ_CMPL_EVT:并不会一直往上面传,而 BTA_DM_DISC_CMPL_EVT:则是会上报给上层。那如果一直搜索不到设备就不会给上层答复吗?我们看看第三部分的行为。

3.2 有搜索到设备,进行discovery

 再次贴上代码:

if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbFirst()) != NULL)    {        /* start name and service discovery from the first device on inquiry result */        bta_dm_search_cb.name_discover_done = FALSE;        bta_dm_search_cb.peer_name[0]       = 0;        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);    }

 

看代码的注释,是开始名字和service 的discovery 的工作。看看 这个函数的实现:

首先简述一下该函数的作用:

  1. 判断是否需要去获取对端设备的名字。不需要跳过,需要就去获取名字并返回,这里猜想服务方面的搜索肯定是在获取名字返回的函数里面进行。
  2. 判断是否需要进行服务的搜索,需要则 进行,从开始 的discovery的接口看,应该是不需要进行服务的搜索。
  3. 发出服务完成的event,发送到btu 线程。

下面看代码:

/*********************************************************************************** Function         bta_dm_discover_device**** Description      Starts name and service discovery on the device**** Returns          void*********************************************************************************/static void bta_dm_discover_device(BD_ADDR remote_bd_addr){    tBTA_DM_MSG * p_msg;    tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;#if BLE_INCLUDED == TRUE    if (bta_dm_search_cb.transport == BTA_TRANSPORT_UNKNOWN)//一开始都是unkown,会BTM_ReadDevInfo来判断transport    {        tBT_DEVICE_TYPE dev_type;        tBLE_ADDR_TYPE  addr_type;        BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);        if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM)            transport = BT_TRANSPORT_LE;    } else {        transport = bta_dm_search_cb.transport;    }#endif    /* Reset transport state for next discovery */    bta_dm_search_cb.transport = BTA_TRANSPORT_UNKNOWN;//reset    bdcpy(bta_dm_search_cb.peer_bdaddr, remote_bd_addr);    if (bta_dm_search_cb.p_btm_inq_info)    {        APPL_TRACE_DEBUG("%s appl_knows_rem_name %d", __func__,                            bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name);//显示app是否已经知道名字,这是inquiry db里面的数据    }    if((bta_dm_search_cb.p_btm_inq_info)       && (bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE)       && (bta_dm_search_cb.state == BTA_DM_SEARCH_ACTIVE))    {        /* Do not perform RNR for LE devices at inquiry complete*/        bta_dm_search_cb.name_discover_done = TRUE; //不要去查找LE 设备的名字    }    /* if name discovery is not done and application needs remote name */    if ((!bta_dm_search_cb.name_discover_done)       && (( bta_dm_search_cb.p_btm_inq_info == NULL )            ||(bta_dm_search_cb.p_btm_inq_info && (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name))))//需要名字则进行名字的搜索    {        if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, transport) == TRUE)            return;//返回        /* starting name discovery failed */        bta_dm_search_cb.name_discover_done = TRUE;    }    /* if application wants to discover service */    if ( bta_dm_search_cb.services )//一般是0    {        /* initialize variables */        bta_dm_search_cb.service_index      = 0;        bta_dm_search_cb.services_found     = 0;        bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE        bta_dm_search_cb.uuid_to_search     = bta_dm_search_cb.num_uuid;#endif        if ((bta_dm_search_cb.p_btm_inq_info != NULL) &&            bta_dm_search_cb.services != BTA_USER_SERVICE_MASK            &&(bta_dm_search_cb.sdp_search == FALSE))        {            /* check if EIR provides the information of supported services */            bta_dm_eir_search_services( &bta_dm_search_cb.p_btm_inq_info->results,                                        &bta_dm_search_cb.services_to_search,                                        &bta_dm_search_cb.services_found );        }        /* if seaching with EIR is not completed */        if(bta_dm_search_cb.services_to_search)        {            /* check whether connection already exists to the device               if connection exists, we don't have to wait for ACL               link to go down to start search on next device */            if (BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR))                bta_dm_search_cb.wait_disc = FALSE;            else                bta_dm_search_cb.wait_disc = TRUE;#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))            if ( bta_dm_search_cb.p_btm_inq_info )            {                APPL_TRACE_DEBUG("%s p_btm_inq_info 0x%x results.device_type 0x%x services_to_search 0x%x",                                    __func__,                                    bta_dm_search_cb.p_btm_inq_info,                                    bta_dm_search_cb.p_btm_inq_info->results.device_type,                                    bta_dm_search_cb.services_to_search);            }            if (transport == BT_TRANSPORT_LE)            {                if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)                {                    //set the raw data buffer here                    memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));                    bta_dm_search_cb.p_ble_rawdata = g_disc_raw_data_buf;                    bta_dm_search_cb.ble_raw_size = MAX_DISC_RAW_DATA_BUF;                    bta_dm_search_cb.ble_raw_used = 0;                    /* start GATT for service discovery */                    btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr);                    return;                }            }            else#endif            {                bta_dm_search_cb.sdp_results = FALSE;                bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);                return;            }        }    }    /* name discovery and service discovery are done for this device */    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)    {        p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;//发送event到btu 线程        /* initialize the data structure - includes p_raw_data and raw_data_size */        memset(&(p_msg->disc_result.result), 0, sizeof(tBTA_DM_DISC_RES));        p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;        p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;        bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);        BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name,  sizeof(BD_NAME),                      (char*)bta_dm_search_cb.peer_name, (BD_NAME_LEN-1));        /* make sure the string is terminated */        p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;        bta_sys_sendmsg(p_msg);    }}

 

服务方面 ok了之后是 会向btu 线程发送event:

p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;

p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);

BTA_DM_DISCOVERY_RESULT_EVT = 0x207

执行的action = BTA_DM_SEARCH_RESULT,对应的函数是bta_dm_search_result,看看其具体的实现:

/*********************************************************************************** Function         bta_dm_search_result**** Description      Service discovery result while searching for devices**** Returns          void*********************************************************************************/void bta_dm_search_result (tBTA_DM_MSG *p_data){    /* call back if application wants name discovery or found services that application is searching */    if (( !bta_dm_search_cb.services )      ||(( bta_dm_search_cb.services ) && ( p_data->disc_result.result.disc_res.services )))    {        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);//回调    }    /* if searching did not initiate to create link */    if(!bta_dm_search_cb.wait_disc )//如果没有pending    {        /* if service searching is done with EIR, don't search next device */        if( bta_dm_search_cb.p_btm_inq_info )        bta_dm_discover_next_device();//去搜索下一个设备的服务    }    else    {        /* wait until link is disconnected or timeout */        bta_dm_search_cb.sdp_results = TRUE;        bta_dm_search_cb.search_timer.p_cback = (TIMER_CBACK*)&bta_dm_search_timer_cback;        bta_sys_start_timer(&bta_dm_search_cb.search_timer, 0, 1000*(L2CAP_LINK_INACTIVITY_TOUT+1) );//如果pending了,那么设置定时器,并且在回调函数里面继续执行搜索下一个设备的服务    }}

 

这里简单分析两点:

  1. bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result)  
  2. bta_dm_discover_next_device,如果有数据库里面还有设备的话,那么继续搜索服务,如果没有设备的话,向上面传:BTA_DM_SEARCH_CMPL_EVT,最终也会上报到java层。前面已经分析过。‘

分析一下bta_dm_search_cb.p_search_cback,我们又遇到这个函数了,其实是bte_search_devices_evt-->btif_dm_search_devices_evt:

/********************************************************************************** Function         btif_dm_search_devices_evt**** Description      Executes search devices callback events in btif context**** Returns          void********************************************************************************/static void btif_dm_search_devices_evt (UINT16 event, char *p_param){    tBTA_DM_SEARCH *p_search_data;    switch (event)    {        case BTA_DM_DISC_RES_EVT:        {            p_search_data = (tBTA_DM_SEARCH *)p_param;            /* Remote name update */            if (strlen((const char *) p_search_data->disc_res.bd_name))//如果早先已经知道了名字,这里的名字的长度0            {                bt_property_t properties[1];                bt_bdaddr_t bdaddr;                bt_status_t status;                properties[0].type = BT_PROPERTY_BDNAME;                properties[0].val = p_search_data->disc_res.bd_name;                properties[0].len = strlen((char *)p_search_data->disc_res.bd_name);                bdcpy(bdaddr.address, p_search_data->disc_res.bd_addr);                status = btif_storage_set_remote_device_property(&bdaddr, &properties[0]);                ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device property", status);                HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,                                 status, &bdaddr, 1, properties);            }

 

现在简单看下:bta_dm_discover_next_device:

/*********************************************************************************** Function         bta_dm_discover_next_device**** Description      Starts discovery on the next device in Inquiry data base**** Returns          void*********************************************************************************/static void bta_dm_discover_next_device(void){    tBTA_DM_MSG * p_msg;    /* searching next device on inquiry result */    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbNext(bta_dm_search_cb.p_btm_inq_info)) != NULL)    {        bta_dm_search_cb.name_discover_done = FALSE;        bta_dm_search_cb.peer_name[0]       = 0;        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);//继续搜索服务    }    else    {        /* no devices, search complete */        bta_dm_search_cb.services = 0;        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)        {            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;//都搜索我弄成之后上报event,结束discovery的流程            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;            bta_sys_sendmsg(p_msg);        }    }}

 

 服务搜索部分就介绍到这里。

3.3  没有搜索到设备或者搜索完成,上报BTA_DM_SEARCH_CMPL_EVT 

 再附上这段代码:

{        /* no devices, search complete */        bta_dm_search_cb.services = 0;        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)        {            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;            bta_sys_sendmsg(p_msg);        }

 

这边还是组装了一个event:

p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;

p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;

相应的log也就是:BTA got event 0x206 

const tBTA_DM_ACTION bta_dm_search_action[] ={  bta_dm_search_start,              /* 0 BTA_DM_API_SEARCH */  bta_dm_search_cancel,             /* 1 BTA_DM_API_SEARCH_CANCEL */  bta_dm_discover,                  /* 2 BTA_DM_API_DISCOVER */  bta_dm_inq_cmpl,                  /* 3 BTA_DM_INQUIRY_CMPL */  bta_dm_rmt_name,                  /* 4 BTA_DM_REMT_NAME */  bta_dm_sdp_result,                /* 5 BTA_DM_SDP_RESULT */  bta_dm_search_cmpl,               /* 6 BTA_DM_SEARCH_CMPL */

 

执行的就是bta_dm_search_cmpl:

/*********************************************************************************** Function         bta_dm_search_cmpl**** Description      Sends event to application**** Returns          void*********************************************************************************/void bta_dm_search_cmpl (tBTA_DM_MSG *p_data){    APPL_TRACE_EVENT("%s", __func__);...    if (p_data->hdr.layer_specific == BTA_DM_API_DI_DISCOVER_EVT)        bta_dm_di_disc_cmpl(p_data);    else        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, NULL);#endif}

 

函数如注释阐明的那样:Sends event to application 

我们前面已经分析过bta_dm_search_cb.p_search_cback=bte_search_devices_evt ,这次传入的事件是BTA_DM_DISC_CMPL_EVT

bte_search_devices_evt --->继续进入到btif_dm_search_devices_evt:

/********************************************************************************** Function         btif_dm_search_devices_evt**** Description      Executes search devices callback events in btif context**** Returns          void********************************************************************************/static void btif_dm_search_devices_evt (UINT16 event, char *p_param){    tBTA_DM_SEARCH *p_search_data;    BTIF_TRACE_EVENT("%s event=%s", __FUNCTION__, dump_dm_search_event(event));    switch (event)    {...    case BTA_DM_DISC_CMPL_EVT:        {            HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED);        }        break;...

 

这一段其实再第一部分已经分析过,当传入的事件是BTA_DM_DISC_CMPL_EVT,那么就会调用:HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED); 来通知上层 。

其实也就是说,即便一条设备信息也搜索不到,那么也会发送BTA_DM_SEARCH_CMPL_EVT---->BTA_DM_DISC_CMPL_EVT --->调用HAL_CBACK:BT_DISCOVERY_STOPPED 来通知上层。

到这里 inquiry complete的流程就已经分析完毕了。

总结:

  Inquiry Complete

  1. update level busy,(btm_acl_update_busy_level)并不会上报到java层
  2. 执行bta_dm_inq_cmpl_cb 
    1. bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data); 该函数不会通知上层,
    2. 有搜索到设备,进行discovery
    3. 没有搜索到设备,上报BTA_DM_SEARCH_CMPL_EVT ,并通知到上层。

 

转载于:https://www.cnblogs.com/libs-liu/p/9223989.html

你可能感兴趣的文章
Python URL中文的编解码
查看>>
centos安装msmtp,利用gmail发送
查看>>
asp.net application life cycle
查看>>
Spark的性能调优
查看>>
入职新人技术引导之我见
查看>>
linux下mongo启动关闭重启方法
查看>>
一些网站
查看>>
语音特征参数MFCC提取过程详解
查看>>
使用GitHub进行版本管理
查看>>
如何选择适合你的渲染软件
查看>>
c++动态规划解决硬币换零钱的问题
查看>>
Qt下几个线程函数介绍
查看>>
Passware Kit和AOPR哪个更厉害?
查看>>
:focus 选择器用于选取获得焦点的元素。
查看>>
从MySQL全库备份中恢复某个库和某张表
查看>>
spark-性能调优
查看>>
Loading XML with Javascript
查看>>
Sublime配置Python3运行环境
查看>>
路由器密码破解记
查看>>
C++、Java、JavaScript中迭代器的用法
查看>>