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;