蓝牙inquiry流程之HCI_Inquiry_Result_With_RSSI和HCI Extended Inquiry Result处理
首先介紹一下和inquiry的相關(guān)的流程。
inquiry是從協(xié)議棧下發(fā)的一個(gè)HCI命令。其格式如下:
這里簡(jiǎn)單介紹下第二個(gè)參數(shù),是inquiry的持續(xù)時(shí)間,
從上圖看出 inquiry持續(xù)的時(shí)間是 設(shè)定值乘以1.28s,如果設(shè)定值是10,那么實(shí)際持續(xù)的時(shí)間就是12.8s
那么下了這個(gè)HCI命令之后,控制器端上傳的event是什么呢?這個(gè)要看另外一個(gè)命令:HCI_Write_Inquiry_mode
我們主要關(guān)注一下其中的inquiry mode
根據(jù)這個(gè)設(shè)定值,我們知道controller 可能會(huì)上傳event的類(lèi)型。假如mode = 0x02,那么controller上傳的event的類(lèi)型就可能是Inquiry Result with RSSI format or Extended Inquiry Result format ,如果mode = 1,那么上傳的event只能是Inquiry Result format with RSSI。
那Inquiry Result with RSSI format 和 Extended Inquiry Result format有什么區(qū)別呢?唯一的區(qū)別就是后者比前者多了一個(gè)extended inquiry response的數(shù)據(jù)域。
?下面進(jìn)入到 對(duì)于Inquiry Result with RSSI format 和 Extended Inquiry Result format 的代碼處理流程的分析:
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; #if BLE_INCLUDED == TRUEUINT8 ble_sub_code; #endifSTREAM_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;case HCI_INQUIRY_RESULT_EVT:btu_hcif_inquiry_result_evt (p);break;case HCI_INQUIRY_RSSI_RESULT_EVT:btu_hcif_inquiry_rssi_result_evt (p);break;case HCI_EXTENDED_INQUIRY_RESULT_EVT:btu_hcif_extended_inquiry_result_evt (p);break; ...上面介紹的三種mode,都是調(diào)用同一個(gè)處理函數(shù),只是傳入的參數(shù)不同, 我們發(fā)現(xiàn)HCI_EXTENDED_INQUIRY_RESULT_EVT流程涵蓋了HCI_INQUIRY_RSSI_RESULT_EVT 的流程。
我們只分析:HCI_EXTENDED_INQUIRY_RESULT_EVT的流程
static void btu_hcif_inquiry_rssi_result_evt (UINT8 *p) {/* Store results in the cache */btm_process_inq_results (p, BTM_INQ_RESULT_WITH_RSSI); }?
繼續(xù)看btm_process_inq_results的流程:
/******************************************************************************* ** ** Function btm_process_inq_results ** ** Description This function is called when inquiry results are received from ** the device. It updates the inquiry database. If the inquiry ** database is full, the oldest entry is discarded. ** ** Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD ** BTM_INQ_RESULT_WITH_RSSI ** BTM_INQ_RESULT_EXTENDED ** ** Returns void ** *******************************************************************************/ void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode) {UINT8 num_resp, xx;BD_ADDR bda;tINQ_DB_ENT *p_i;tBTM_INQ_RESULTS *p_cur=NULL;BOOLEAN is_new = TRUE;BOOLEAN update = FALSE;INT8 i_rssi;tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;UINT8 page_scan_rep_mode = 0;UINT8 page_scan_per_mode = 0;UINT8 page_scan_mode = 0;UINT8 rssi = 0;DEV_CLASS dc;UINT16 clock_offset;UINT8 *p_eir_data = NULL; ...STREAM_TO_UINT8 (num_resp, p);//解析出num_respfor (xx = 0; xx < num_resp; xx++)//依次處理,一般只有一個(gè) {update = FALSE;//初始化位false/* Extract inquiry results */STREAM_TO_BDADDR (bda, p);//解析出地址等 STREAM_TO_UINT8 (page_scan_rep_mode, p);STREAM_TO_UINT8 (page_scan_per_mode, p);if (inq_res_mode == BTM_INQ_RESULT_STANDARD){STREAM_TO_UINT8(page_scan_mode, p);}STREAM_TO_DEVCLASS (dc, p);//解析device class STREAM_TO_UINT16 (clock_offset, p);if (inq_res_mode != BTM_INQ_RESULT_STANDARD){STREAM_TO_UINT8(rssi, p);//stand 沒(méi)有rssi }p_i = btm_inq_db_find (bda);//查找數(shù)據(jù)庫(kù),后續(xù)會(huì)判斷是否已經(jīng)處理過(guò) .../* Check if this address has already been processed for this inquiry */if (btm_inq_find_bdaddr(bda))// true 說(shuō)明已經(jīng)處理過(guò),check是否要update {i_rssi = (INT8)rssi;/* If this new RSSI is higher than the last one */if(p_inq->inqparms.report_dup && (rssi != 0) &&p_i && (i_rssi > p_i->inq_info.results.rssi || p_i->inq_info.results.rssi == 0 #if BLE_INCLUDED == TRUE/* BR/EDR inquiry information update */|| (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0 #endif)){p_cur = &p_i->inq_info.results;BTM_TRACE_DEBUG("update RSSI new:%d, old:%d", i_rssi, p_cur->rssi);p_cur->rssi = i_rssi;update = TRUE;}/* If we received a second Extended Inq Event for an already *//* discovered device, this is because for the first one EIR was not received */else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)){p_cur = &p_i->inq_info.results;update = TRUE;}/* If no update needed continue with next response (if any) */elsecontinue;}/* If existing entry, use that, else get a new one (possibly reusing the oldest) */if (p_i == NULL){p_i = btm_inq_db_new (bda);//新建數(shù)據(jù)庫(kù)is_new = TRUE;}/* If an entry for the device already exists, overwrite it ONLY if it is froma previous inquiry. (Ignore it if it is a duplicate response from the sameinquiry.*/else if (p_i->inq_count == p_inq->inq_counter //相等說(shuō)明是本次inquiry #if (BLE_INCLUDED == TRUE )&& (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR) #endif)is_new = FALSE;//不是新的/* keep updating RSSI to have latest value */if( inq_res_mode != BTM_INQ_RESULT_STANDARD )//如果不是標(biāo)準(zhǔn)模式,rssi每次都要更新p_i->inq_info.results.rssi = (INT8)rssi;elsep_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;if (is_new == TRUE)//如果是新設(shè)備,那么保存這些信息 {/* Save the info */p_cur = &p_i->inq_info.results;p_cur->page_scan_rep_mode = page_scan_rep_mode;p_cur->page_scan_per_mode = page_scan_per_mode;p_cur->page_scan_mode = page_scan_mode;p_cur->dev_class[0] = dc[0];p_cur->dev_class[1] = dc[1];p_cur->dev_class[2] = dc[2];p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;p_i->time_of_resp = GKI_get_os_tick_count();//獲取時(shí)間,用以計(jì)算最老的itemif (p_i->inq_count != p_inq->inq_counter)p_inq->inq_cmpl_info.num_resp++; /* A new response was found */#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)p_cur->inq_result_type = BTM_INQ_RESULT_BR;if (p_i->inq_count != p_inq->inq_counter){p_cur->device_type = BT_DEVICE_TYPE_BREDR;p_i->scan_rsp = FALSE;}elsep_cur->device_type |= BT_DEVICE_TYPE_BREDR; #endifp_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */ .../* Initialize flag to FALSE. This flag is set/used by application */p_i->inq_info.appl_knows_rem_name = FALSE;//初始化位false }if (is_new || update){if( inq_res_mode == BTM_INQ_RESULT_EXTENDED ){memset( p_cur->eir_uuid, 0,BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS/8));/* set bit map of UUID list from received EIR */btm_set_eir_uuid( p, p_cur );//將UUID list保存在tBTM_INQ_RESULTS->eir_uuid中p_eir_data = p;}elsep_eir_data = NULL;/* If a callback is registered, call it with the results */if (p_inq_results_cb)//調(diào)用回調(diào)(p_inq_results_cb)((tBTM_INQ_RESULTS *) p_cur, p_eir_data);}} }?上面的流程比較簡(jiǎn)單,主要就是保存inquiry回來(lái)的信息,然后調(diào)用p_inq_results_cb 來(lái)處理 設(shè)備信息。這個(gè)在BTM_StartInquiry的時(shí)候傳入?yún)?shù)bta_dm_inq_results_cb,調(diào)用的也就是這個(gè)回調(diào)函數(shù)。下面繼續(xù)分析bta_dm_inq_results_cb
?
/******************************************************************************* ** ** Function bta_dm_inq_results_cb ** ** Description Inquiry results callback from BTM ** ** Returns void ** *******************************************************************************/ static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir) {tBTA_DM_SEARCH result;tBTM_INQ_INFO *p_inq_info;UINT16 service_class;bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class);result.inq_res.is_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER)?TRUE:FALSE;result.inq_res.rssi = p_inq->rssi;#if (BLE_INCLUDED == TRUE)result.inq_res.ble_addr_type = p_inq->ble_addr_type;result.inq_res.inq_result_type = p_inq->inq_result_type;result.inq_res.device_type = p_inq->device_type;result.inq_res.flag = p_inq->flag; #endif/* application will parse EIR to find out remote device name */result.inq_res.p_eir = p_eir;if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL){/* initialize remt_name_not_required to FALSE so that we get the name by default */result.inq_res.remt_name_not_required = FALSE;}if(bta_dm_search_cb.p_search_cback)bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);//上層會(huì)去解析,并且會(huì)設(shè)置是否知曉名字的標(biāo)志位if(p_inq_info){/* application indicates if it knows the remote name, inside the callbackcopy that to the inquiry data base*/if(result.inq_res.remt_name_not_required)p_inq_info->appl_knows_rem_name = TRUE;//將標(biāo)志位位傳遞到數(shù)據(jù)庫(kù) }}?
上面的邏輯很簡(jiǎn)單,就是組建了一個(gè)?tBTA_DM_SEARCH 然后繼續(xù)向上層匯報(bào) 事件。
我們繼續(xù)看bta_dm_search_cb.p_search_cback 的流程,我們已經(jīng)多次分析:bta_dm_search_cb.p_search_cback =?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;if (p_data)param_len += sizeof(tBTA_DM_SEARCH);/* Allocate buffer to hold the pointers (deep copy). The pointers will point to the end of the tBTA_DM_SEARCH */switch (event){case BTA_DM_INQ_RES_EVT:{if (p_data->inq_res.p_eir)param_len += HCI_EXT_INQ_RESPONSE_LEN;}break; .../* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */if (event == BTA_DM_INQ_RES_EVT){p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL);//解析EIRdata中的名字并設(shè)置標(biāo)志位 }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 }我們繼續(xù)看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_RES_EVT:{/* inquiry result */UINT32 cod;bt_bdname_t bdname;bt_bdaddr_t bdaddr;UINT8 remote_name_len;tBTA_SERVICE_MASK services = 0;bdstr_t bdstr;p_search_data = (tBTA_DM_SEARCH *)p_param;bdcpy(bdaddr.address, p_search_data->inq_res.bd_addr);#if (BLE_INCLUDED == TRUE)p_search_data->inq_res.device_type); #elseBT_DEVICE_TYPE_BREDR); #endifbdname.name[0] = 0;cod = devclass2uint (p_search_data->inq_res.dev_class); ...if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len))//解析名字check_cached_remote_name(p_search_data, bdname.name, &remote_name_len);/* Check EIR for remote name and services */if (p_search_data->inq_res.p_eir){BTA_GetEirService(p_search_data->inq_res.p_eir, &services);BTIF_TRACE_DEBUG("%s()EIR BTA services = %08X", __FUNCTION__, (UINT32)services);/* TODO: Get the service list and check to see which uuids we got and send it back to the client. */}{bt_property_t properties[5];bt_device_type_t dev_type;uint32_t num_properties = 0;bt_status_t status;int addr_type = 0;memset(properties, 0, sizeof(properties));/* BD_ADDR */BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr);num_properties++;/* BD_NAME *//* Don't send BDNAME if it is empty */if (bdname.name[0]){BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_BDNAME,strlen((char *)bdname.name), &bdname);num_properties++;}/* DEV_CLASS */BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod);num_properties++;/* DEV_TYPE */ #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))/* FixMe: Assumption is that bluetooth.h and BTE enums match *//* Verify if the device is dual mode in NVRAM */int stored_device_type = 0;if (btif_get_device_type(bdaddr.address, &stored_device_type) &&((stored_device_type == BT_DEVICE_TYPE_BLE &&p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BREDR) ||(stored_device_type == BT_DEVICE_TYPE_BREDR &&p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE))) {dev_type = BT_DEVICE_TYPE_DUMO;} else {dev_type = p_search_data->inq_res.device_type;}if (p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE)addr_type = p_search_data->inq_res.ble_addr_type; #elsedev_type = BT_DEVICE_TYPE_BREDR; #endifBTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type);num_properties++;/* RSSI */BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t),&(p_search_data->inq_res.rssi));num_properties++;#ifdef BLUETOOTH_RTKBTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],BT_PROPERTY_REMOTE_VERSION_INFO, sizeof(bt_remote_version_t),&info);num_properties++; #endifstatus = btif_storage_add_remote_device(&bdaddr, num_properties, properties);//保存各個(gè)屬性值到文件系統(tǒng)中ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device (inquiry)", status); #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))status = btif_storage_set_remote_addr_type(&bdaddr, addr_type); #endif/* Callback to notify upper layer of device */HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties);//向上層匯報(bào) }}break;?這里注意btif_storage_add_remote_device 是將各個(gè)屬性保存在系統(tǒng)的配置文件中。
上面的代碼和BLE的廣播包的處理 如出一轍,都是組裝成bt_property_t的形式進(jìn)行上報(bào),通過(guò)HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties);?來(lái)上面五個(gè)屬性:設(shè)備地址、設(shè)備名字、設(shè)備類(lèi)、設(shè)備類(lèi)型、設(shè)備rssi
那關(guān)于BREDR 的inquiry 的數(shù)據(jù)包處理流程就分析到這里。
?
轉(zhuǎn)載于:https://www.cnblogs.com/libs-liu/p/9243500.html
總結(jié)
以上是生活随笔為你收集整理的蓝牙inquiry流程之HCI_Inquiry_Result_With_RSSI和HCI Extended Inquiry Result处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 马云的“虚拟信用卡”动了谁的奶酪?
- 下一篇: 听说看了这篇文章就彻底搞懂了什么是OPC