From f96da0ee19d8eb9d159b965338bdd15d327cb474 Mon Sep 17 00:00:00 2001 From: Zhihai Xu Date: Fri, 21 Feb 2014 18:20:37 -0800 Subject: [PATCH] Allow simultaneous LE Observe and BTM Inquiry/Scan This patch allows BTM inquiry and LE observe to be launched and overlap each others' occurance by redirecting results and handling states accordingly. CRs-Fixed: 579505 Conflicts: stack/btm/btm_ble_gap.c bug 12939764 Change-Id: Ifde73f17f8d40e9ebfff3b49e409591189574ee0 --- stack/btm/btm_ble_gap.c | 85 +++++++++++++++++++++++++++++++++---------------- stack/btm/btm_inq.c | 47 ++++++++++++++++++++++++--- stack/btm/btm_int.h | 11 +++++++ 3 files changed, 112 insertions(+), 31 deletions(-) diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c index 6963e2ade..608fa7eba 100644 --- a/stack/btm/btm_ble_gap.c +++ b/stack/btm/btm_ble_gap.c @@ -157,7 +157,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_NO_RESOURCES; - BTM_TRACE_EVENT0 ("BTM_BleObserve "); + BTM_TRACE_EVENT1 ("BTM_BleObserve : scan_type:%d",btm_cb.btm_inq_vars.scan_type); if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) return BTM_ILLEGAL_VALUE; @@ -166,10 +166,22 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, { /* shared inquiry database, do not allow observe if any inquiry is active */ if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE) - return BTM_BUSY; - - btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb; - btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb; + { + /*check if an interleave scan is already in progress*/ + if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL + && btm_cb.btm_inq_vars.p_inq_results_cb != NULL) + { + BTM_TRACE_EVENT0 ("BTM_BleObserve general inq in progress, redirecting the results"); + btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb; + btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb; + return BTM_SUCCESS; + } + else + return BTM_BUSY; + } + btm_cb.btm_inq_vars.scan_type = INQ_LE_OBSERVE; + btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb; + btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb; p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type; /* allow config scanning type */ @@ -194,10 +206,19 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, } } } - else if (p_inq->proc_mode == BTM_BLE_OBSERVE) + else/*start = 0*/ { - btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE; - btm_ble_stop_scan(); + if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL) + { + //Dont stop the scan. Just nullify the cbs + btm_cb.btm_inq_vars.p_inq_ble_results_cb = NULL; + btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = NULL; + } + else if (p_inq->proc_mode == BTM_BLE_OBSERVE) + { + btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE; + btm_ble_stop_scan(); + } } return status; @@ -1595,6 +1616,8 @@ BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_t if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI && (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT))) { + BTM_TRACE_DEBUG1("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; } @@ -1748,6 +1771,8 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) btm_cb.ble_ctr_cb.p_select_cback == NULL)) return; + BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x", + bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]); #if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE) #if SMP_INCLUDED == TRUE /* always do RRA resolution on host */ @@ -1779,9 +1804,12 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt { tINQ_DB_ENT *p_i; BOOLEAN to_report = FALSE; + BOOLEAN to_report_LE = TRUE; //var for reporting to LE observe 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_inq_ble_results_cb = p_inq->p_inq_ble_results_cb; tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var; + BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: addr_type: %d, evt_type: %d", addr_type, evt_type); p_i = btm_inq_db_find (bda); @@ -1801,11 +1829,10 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } else { - /* if yes, skip it */ - return; /* assumption: one result per event */ + to_report = FALSE; } } - else /* not been processed int his round */ + else /* not been processed in this round */ { to_report = TRUE; } @@ -1813,33 +1840,31 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt /* If existing entry, use that, else get a new one (possibly reusing the oldest) */ if (p_i == NULL) { - if (btm_ble_is_discoverable(bda, evt_type, p)) + if ((p_i = btm_inq_db_new (bda)) != NULL) { - if ((p_i = btm_inq_db_new (bda)) != NULL) - { - p_inq->inq_cmpl_info.num_resp++; - to_report = TRUE; - } - else - return; + p_inq->inq_cmpl_info.num_resp++; + } + else + return; + + if (to_report && btm_ble_is_discoverable(bda, evt_type, p)) + { + to_report = TRUE; } else { BTM_TRACE_ERROR0("discard adv pkt"); - return; + to_report = FALSE; } } else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */ { p_inq->inq_cmpl_info.num_resp++; } - /* update the LE device information in inquiry database */ + to_report_LE = btm_ble_update_inq_result(p_i, addr_type, evt_type, p); if (to_report) - { - to_report = btm_ble_update_inq_result(p_i, addr_type, evt_type, p); - } - + to_report = to_report_LE; #if BTM_USE_INQ_RESULTS_FILTER == TRUE /* If the number of responses found and limited, issue a cancel inquiry */ if (p_inq->inqparms.max_resps && @@ -1867,6 +1892,8 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } #endif + BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: to_report =%d, to_report_le=%d", + to_report, to_report_LE); /* background connection in selective connection mode */ if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) { @@ -1878,9 +1905,13 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection"); } } - else if (p_inq_results_cb && to_report) + else if (to_report || to_report_LE) { - (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); + if(p_inq_results_cb && to_report) + (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); + if(p_inq_ble_results_cb && to_report_LE) + (p_inq_ble_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, + p_le_inq_cb->adv_data_cache); } } diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c index 4c5eecb4c..24f91a86d 100644 --- a/stack/btm/btm_inq.c +++ b/stack/btm/btm_inq.c @@ -810,8 +810,8 @@ tBTM_STATUS BTM_CancelInquiry(void) */ #endif - p_inq->inq_counter++; - btm_clr_inq_result_flt(); + p_inq->inq_counter++; + btm_clr_inq_result_flt(); } return (status); @@ -860,7 +860,27 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p /* Only one active inquiry is allowed in this implementation. Also do not allow an inquiry if the inquiry filter is being updated */ if (p_inq->inq_active || p_inq->inqfilt_active) - return (BTM_BUSY); + { +#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) + /*check if LE observe is already running*/ + if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL) + { + BTM_TRACE_API0("BTM_StartInquiry: LE observe in progress"); + p_inq->scan_type = INQ_GENERAL; + p_inq->inq_active = BTM_INQUIRY_INACTIVE; + btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; + btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE; + btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); + } + else +#endif + { + return (BTM_BUSY); + BTM_TRACE_API0("BTM_StartInquiry: return BUSY"); + } + } + else + p_inq->scan_type = INQ_GENERAL; /*** Make sure the device is ready ***/ if (!BTM_IsDeviceUp()) @@ -2402,7 +2422,13 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) p_inq->inqparms.mode &= ~(mode); #endif - + if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) + { + /*end of LE observe*/ + p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; + p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL; + p_inq->scan_type=INQ_NONE; + } #if (BTM_INQ_DEBUG == TRUE) @@ -2473,9 +2499,22 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) p_inq->inq_active = BTM_INQUIRY_INACTIVE; /* call the inquiry again */ BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb); + return; } #endif } + if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete + { + p_inq->scan_type = INQ_NONE; +#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) + /* check if the LE observe is pending */ + if(p_inq->p_inq_ble_results_cb != NULL) + { + BTM_TRACE_DEBUG0("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 + } #if (BTM_INQ_DEBUG == TRUE) BTM_TRACE_DEBUG3 ("inq_active:0x%x state:%d inqfilt_active:%d", btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active); diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h index 5129efc7c..7865b3eb3 100644 --- a/stack/btm/btm_int.h +++ b/stack/btm/btm_int.h @@ -271,6 +271,14 @@ typedef struct } tINQ_DB_ENT; +enum +{ + INQ_NONE, + INQ_LE_OBSERVE, + INQ_GENERAL +}; +typedef UINT8 tBTM_INQ_TYPE; + typedef struct { tBTM_CMPL_CB *p_remname_cmpl_cb; @@ -288,6 +296,7 @@ typedef struct UINT16 inq_scan_period; UINT16 inq_scan_type; UINT16 page_scan_type; /* current page scan type */ + tBTM_INQ_TYPE scan_type; BD_ADDR remname_bda; /* Name of bd addr for active remote name request */ #define BTM_RMT_NAME_INACTIVE 0 @@ -298,6 +307,8 @@ typedef struct tBTM_CMPL_CB *p_inq_cmpl_cb; tBTM_INQ_RESULTS_CB *p_inq_results_cb; + tBTM_CMPL_CB *p_inq_ble_cmpl_cb; /*completion callback exclusively for LE Observe*/ + tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb;/*results callback exclusively for LE observe*/ tBTM_CMPL_CB *p_inqfilter_cmpl_cb; /* Called (if not NULL) after inquiry filter completed */ tBTM_INQ_DB_CHANGE_CB *p_inq_change_cb; /* Inquiry database changed callback */ UINT32 inq_counter; /* Counter incremented each time an inquiry completes */ -- 2.11.0