博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
蓝牙inquiry流程之Advertising Report
阅读量:6186 次
发布时间:2019-06-21

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

setting 界面开始搜索的时候,通常也会同时进行le scan,这一点在inquiry流程之命令下发中已经讲述。此篇文章主要是分析一下对于controller 搜索到的广播包的处理。这里以Android O的bluedroid的代码作为分析对象。

void btu_hci_msg_process(BT_HDR* p_msg) {  /* Determine the input message type. */  switch (p_msg->event & BT_EVT_MASK) {    case BT_EVT_TO_BTU_HCI_ACL:      /* All Acl Data goes to L2CAP */      l2c_rcv_acl_data(p_msg);      break;    case BT_EVT_TO_BTU_L2C_SEG_XMIT:      /* L2CAP segment transmit complete */      l2c_link_segments_xmitted(p_msg);      break;    case BT_EVT_TO_BTU_HCI_SCO:#if (BTM_SCO_INCLUDED == TRUE)      btm_route_sco_data(p_msg);      break;#endif    case BT_EVT_TO_BTU_HCI_EVT:      btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg);      osi_free(p_msg);      break;    case BT_EVT_TO_BTU_HCI_CMD:      btu_hcif_send_cmd((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg);      break;    default:      osi_free(p_msg);      break;  }}

 

上面可以看出 btu_hci_msg_process 的所有的处理对象。hci event 的处理函数 是btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg); 

void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) {  uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;  uint8_t hci_evt_code, hci_evt_len;  uint8_t ble_sub_code;  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;    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_BLE_EVENT: { //le 相关的event      STREAM_TO_UINT8(ble_sub_code, p);      uint8_t ble_evt_len = hci_evt_len - 1;      switch (ble_sub_code) {  //判断子event        case HCI_BLE_ADV_PKT_RPT_EVT: /* result of inquiry */          HCI_TRACE_EVENT("HCI_BLE_ADV_PKT_RPT_EVT");          btm_ble_process_adv_pkt(ble_evt_len, p);//处理广播包          break;        case HCI_BLE_CONN_COMPLETE_EVT:          btu_ble_ll_conn_complete_evt(p, hci_evt_len);          break;        case HCI_BLE_LL_CONN_PARAM_UPD_EVT:          btu_ble_ll_conn_param_upd_evt(p, hci_evt_len);          break;...

 

从上面可以看出 btu_hcif_process_event可以处理的event 的类型,并且可以看出处理广播包的函数 是 btm_ble_process_adv_pkt(ble_evt_len, p);从函数名称可以看出此时函数已经进入到btm 模块,其实现在btm_ble_gap.cc

/** * This function is called when advertising report event is received. It updates * the inquiry database. If the inquiry database is full, the oldest entry is * discarded. */void btm_ble_process_adv_pkt(uint8_t data_len, uint8_t* data) {  BD_ADDR bda;  uint8_t* p = data;  uint8_t legacy_evt_type, addr_type, num_reports, pkt_data_len;  int8_t rssi;  /* Extract the number of reports in this event. */  STREAM_TO_UINT8(num_reports, p);//一个包里面可能有多个event,但是通常只有一个event  while (num_reports--) {    /* Extract inquiry results */    STREAM_TO_UINT8(legacy_evt_type, p);//event_type    STREAM_TO_UINT8(addr_type, p);//地址类型    STREAM_TO_BDADDR(bda, p);//地址    STREAM_TO_UINT8(pkt_data_len, p);//数据长度    uint8_t* pkt_data = p;    p += pkt_data_len; /* Advance to the the rssi byte */    STREAM_TO_INT8(rssi, p);//此时指针指向数据末尾的rssi    btm_ble_process_adv_addr(bda, addr_type);//处理地址相关    uint16_t event_type;    if (legacy_evt_type == 0x00) {  // ADV_IND;      event_type = 0x0013;    } else if (legacy_evt_type == 0x01) {  // ADV_DIRECT_IND;      event_type = 0x0015;    } else if (legacy_evt_type == 0x02) {  // ADV_SCAN_IND;      event_type = 0x0012;    } else if (legacy_evt_type == 0x03) {  // ADV_NONCONN_IND;      event_type = 0x0010;    } else if (legacy_evt_type == 0x04) {  // SCAN_RSP;      // We can't distinguish between "SCAN_RSP to an ADV_IND", and "SCAN_RSP to      // an ADV_SCAN_IND", so always return "SCAN_RSP to an ADV_IND"      event_type = 0x001B;    }     btm_ble_process_adv_pkt_cont(        event_type, addr_type, bda, PHY_LE_1M, PHY_LE_NO_PACKET, NO_ADI_PRESENT,        TX_POWER_NOT_PRESENT, rssi, 0x00 /* no periodic adv */, pkt_data_len,        pkt_data);//开始处理数据包  }}

可以看出主要的 主要的处理流程是执行btm_ble_process_adv_pkt_cont,我们看看具体的实现:

/*********************************************************************************** Function         btm_ble_process_adv_pkt_cont**** Description      This function is called after random address resolution is**                  done, and proceed to process adv packet.**** Parameters**** Returns          void*********************************************************************************/static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p){    tINQ_DB_ENT          *p_i;    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;    tBTM_INQ_RESULTS_CB  *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;    tBTM_BLE_INQ_CB      *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;    BOOLEAN     update = TRUE;    UINT8       result = 0;    p_i = btm_inq_db_find (bda);    /* Check if this address has already been processed for this inquiry */    if (btm_inq_find_bdaddr(bda))//check 这个地址的设备是否已经被处理过    {        /* never been report as an LE device */        if (p_i &&            (!(p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) ||              /* scan repsonse to be updated */              (!p_i->scan_rsp)))//这里update的判断条件是device type是否已经定位以及是否有scan response        {            update = TRUE;        }        else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))        {            update = FALSE;        }        else        {            /* if yes, skip it */            return; /* assumption: one result per event */        }    }    /* If existing entry, use that, else get  a new one (possibly reusing the oldest) */    if (p_i == NULL)//没有entry,重新分配    {        if ((p_i = btm_inq_db_new (bda)) != NULL)        {            p_inq->inq_cmpl_info.num_resp++;        }        else            return;    }    else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */ /*在这一次的inquiry 中第一次见到该设备*/    {        p_inq->inq_cmpl_info.num_resp++;    }    /* update the LE device information in inquiry database */    if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p))//更新数据库        return;    if ((result = btm_ble_is_discoverable(bda, evt_type, p)) == 0)//检测adv包中标志位    {      LOG_WARN("%s device is no longer discoverable so discarding advertising packet pkt",          __func__);        return;    }    if (!update)        result &= ~BTM_BLE_INQ_RESULT;...    /* background connection in selective connection mode */        BTM_TRACE_WARNING("btm_cb.ble_ctr_cb.bg_conn_type = %d libs_liu",btm_cb.ble_ctr_cb.bg_conn_type);    if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)    {        if (result & BTM_BLE_SEL_CONN_RESULT)            btm_send_sel_conn_callback(bda, evt_type, p, addr_type);        else        {            BTM_TRACE_DEBUG("None LE device, can not initiate selective connection");        }    }    else    {        if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT))        {            (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);//处理结果        }        if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT))        {            (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);        }    }}

 从上面处理流程来看,主要是做了四件事:

  1. 查询设备数据库,并且判断该广播信息已经被处理过。
  2. btm_ble_update_inq_result(p_i, addr_type, evt_type, p) 更新设备数据库中的设备信息
  3. btm_ble_is_discoverable(bda, evt_type, p)  判断设备信息标志位,判断是否是可以发现的类型。
  4. 调用p_inq_results_cb 来处理 设备信息。这个在BTM_StartInquiry的时候传入参数bta_dm_inq_results_cb,调用的也就是这个回调函数。

下面主要分析一下2,3,4三个点:

2.btm_ble_update_inq_result(p_i, addr_type, evt_type, p) 

/*********************************************************************************** Function         btm_ble_update_inq_result**** Description      Update adv packet information into inquiry result.**** Parameters**** Returns          void*********************************************************************************/BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p){    BOOLEAN             to_report = TRUE;    tBTM_INQ_RESULTS     *p_cur = &p_i->inq_info.results;    UINT8               len;    UINT8               *p_flag;    tBTM_INQUIRY_VAR_ST  *p_inq = &btm_cb.btm_inq_vars;    UINT8                data_len, rssi;    tBTM_BLE_INQ_CB     *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;    UINT8 *p1;    UINT8               *p_uuid16;    STREAM_TO_UINT8    (data_len, p);    btm_ble_cache_adv_data(p_cur, data_len, p, evt_type);// cache adv data    p1 = (p + data_len);    STREAM_TO_UINT8 (rssi, p1);    /* Save the info */    p_cur->inq_result_type = BTM_INQ_RESULT_BLE;    p_cur->ble_addr_type    = addr_type;    p_cur->rssi = rssi;    /* active scan, always wait until get scan_rsp to report the result */    if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&  //如果是active scan,那么要等scan response 上来之后才会一起report,一个单独的BTM_BLE_CONNECT_EVT或者BTM_BLE_DISCOVER_EVT是不会上报的         (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))    {        BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\                              scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);        p_i->scan_rsp = FALSE;        to_report = FALSE;    }    else        p_i->scan_rsp = TRUE;//拿到scan response    if (p_i->inq_count != p_inq->inq_counter)        p_cur->device_type = BT_DEVICE_TYPE_BLE;//这次inquiry的第一次处理    else        p_cur->device_type |= BT_DEVICE_TYPE_BLE;//if(p_i->inq_count == p_inq->inq_counter) indicated that has been updated ,至少是BLE    if (evt_type != BTM_BLE_SCAN_RSP_EVT)        p_cur->ble_evt_type     = evt_type;    p_i->inq_count = p_inq->inq_counter;   /* Mark entry for current inquiry */    if (p_le_inq_cb->adv_len != 0)    {        if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_FLAG, &len)) != NULL)//读取flag            p_cur->flag = * p_flag;    }    if (p_le_inq_cb->adv_len != 0)    {        /* Check to see the BLE device has the Appearance UUID in the advertising data.  If it does         * then try to convert the appearance value to a class of device value Bluedroid can use.         * Otherwise fall back to trying to infer if it is a HID device based on the service class.         */        p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_APPEARANCE, &len);        if (p_uuid16 && len == 2)        {            btm_ble_appearance_to_cod((UINT16)p_uuid16[0] | (p_uuid16[1] << 8), p_cur->dev_class);        }        else        {            if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,                                             BTM_BLE_AD_TYPE_16SRV_CMPL, &len)) != NULL)            {                UINT8 i;                for (i = 0; i + 2 <= len; i = i + 2)                {                    /* if this BLE device support HID over LE, set HID Major in class of device */                    if ((p_uuid16[i] | (p_uuid16[i+1] << 8)) == UUID_SERVCLASS_LE_HID)                    {                        p_cur->dev_class[0] = 0;                        p_cur->dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;                        p_cur->dev_class[2] = 0;                        break;                    }                }            }        }    }    /* if BR/EDR not supported is not set, assume is a DUMO device */    if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0 &&         evt_type != BTM_BLE_CONNECT_DIR_EVT)    {        if (p_cur->ble_addr_type != BLE_ADDR_RANDOM)        {            BTM_TRACE_DEBUG("BR/EDR NOT support bit not set, treat as DUMO");            p_cur->device_type |= BT_DEVICE_TYPE_DUMO;        } else {            BTM_TRACE_DEBUG("Random address, treating device as LE only");        }    }    else    {        BTM_TRACE_DEBUG("BR/EDR NOT SUPPORT bit set, LE only device");    }    return to_report;}

 

这里主要就是更新设备的信息。读取adv 包中的 flag等值,判断这个包是否要上报,以及更新device type。另外会根据BTM_BLE_AD_TYPE_APPEARANCE = 0x19 来判断device class-->btm_ble_appearance_to_cod

3.btm_ble_is_discoverable(bda, evt_type, p)

 

/*********************************************************************************** Function         btm_ble_is_discoverable**** Description      check ADV flag to make sure device is discoverable and match**                  the search condition**** Parameters**** Returns          void*********************************************************************************/UINT8 btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p){    UINT8               *p_flag, flag = 0, rt = 0;    UINT8                data_len;    tBTM_INQ_PARMS      *p_cond = &btm_cb.btm_inq_vars.inqparms;    tBTM_BLE_INQ_CB     *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;    /* for observer, always "discoverable */    if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))//这里注意,如果是observation,那么总是可以发现的        rt |= BTM_BLE_OBS_RESULT;    if (BTM_BLE_IS_SEL_CONN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity) &&        (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT))        rt |= BTM_BLE_SEL_CONN_RESULT;    if (p_le_inq_cb->adv_len != 0)    {        if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,            BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL)//读取标志位并且判断        {            flag = * p_flag;            if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&                (flag & (BTM_BLE_LIMIT_DISC_FLAG|BTM_BLE_GEN_DISC_FLAG)) != 0)            {                BTM_TRACE_DEBUG("Find Generable Discoverable device");                rt |= BTM_BLE_INQ_RESULT;            }            else if (btm_cb.btm_inq_vars.inq_active & BTM_BLE_LIMITED_INQUIRY &&                     (flag & BTM_BLE_LIMIT_DISC_FLAG) != 0)            {                BTM_TRACE_DEBUG("Find limited discoverable device");                rt |= BTM_BLE_INQ_RESULT;            }        }    }    return rt;}

 上面代码主要作用就是解析adv包中的标志位,然后做解析。并且决定是否要继续处理这个包,如果rt = 0 ,那么就不会继续处理这个包。这里注意如果是observation ,那么这个包总是可以发现的。

4.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);//填充address    memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);//填充device class    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;//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;//填充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);    if(p_inq_info)    {        /* application indicates if it knows the remote name, inside the callback         copy that to the inquiry data base*/        if(result.inq_res.remt_name_not_required)            p_inq_info->appl_knows_rem_name = TRUE;//如果application已经知道名字    }}

 

这里的逻辑也比较简单,构造了一个tBTA_DM_SEARCH来上报事件,上报的事件的函数就是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);//这里check data 里面是否有名字,如果有的话,设置result 的标志位,协议栈就不会去查询名字        }    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);}

 

这里主要就是check 名字。然后transfer 到btif 线程去执行,我们继续看:

/********************************************************************************** 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);//获得地址            bdname.name[0] = 0;            cod = devclass2uint (p_search_data->inq_res.dev_class);//cod            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);//如果data里面没有名字,那么就查找cache里面的名字            /* 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);//保存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;#else                dev_type = BT_DEVICE_TYPE_BREDR;#endif                BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],                                    BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &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));//保存rssi                num_properties++;                status = btif_storage_add_remote_device(&bdaddr, num_properties, properties);//将各个属性保存在文件系统中#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))                status = btif_storage_set_remote_addr_type(&bdaddr, addr_type);                ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote addr type (inquiry)", status);#endif                /* Callback to notify upper layer of device */                HAL_CBACK(bt_hal_cbacks, device_found_cb,                                 num_properties, properties);//向上汇报            }        }        break;...

 这里注意btif_storage_add_remote_device 是将各个属性保存在系统的配置文件中。然后 通过HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties); 来上面五个属性:设备地址、设备名字、设备类、设备类型、设备rssi

协议栈对于ble 设备广播包的处理就分析到这里。

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

你可能感兴趣的文章
众说区块链:区块链应用的可能与不可能
查看>>
hyperledger开发分享——一线开发者在超级账本项目开发实践(实录)
查看>>
如何创建一个“纯净”的对象
查看>>
开源跨平台移动项目Ngui【视图与布局系统】
查看>>
cookie有关的知识
查看>>
搞定Go单元测试(二)—— mock框架(gomock)
查看>>
2019前端面试题 | JS部分(附带答案)
查看>>
koa+mysql+vue+socket.io全栈开发之数据访问篇
查看>>
HTML 水平线
查看>>
入门大疆 SDK 开发前,你需要了解这些…
查看>>
不要这样写简历
查看>>
iOS 实现按钮倒计时 GCD的方法
查看>>
【JavaScript】前端必会的代码整理
查看>>
2019.01.10|区块链技术头条
查看>>
【报表制作技巧】报告式报表的制作
查看>>
觉得Python中的生成器(yield)晦涩难懂?看完本文你就知道了
查看>>
Consul1.5.0 带ACL控制集群搭建
查看>>
二维码编解码 Python调用示例代码
查看>>
Vuex之热更新
查看>>
分布式系统解耦模式:用事件代表时间触发Cron计划任务
查看>>