1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #include <string.h>
19 //#include <stdio.h>
20 #include <stddef.h>
21 #include "common/bt_target.h"
22 
23 #include "stack/btm_ble_api.h"
24 #include "stack/bt_types.h"
25 //#include "bt_utils.h"
26 #include "stack/btu.h"
27 #include "btm_int.h"
28 #include "device/controller.h"
29 #include "stack/hcimsgs.h"
30 
31 #if (BLE_INCLUDED == TRUE)
32 
33 #if BTM_DYNAMIC_MEMORY == FALSE
34 tBTM_BLE_BATCH_SCAN_CB      ble_batchscan_cb;
35 tBTM_BLE_ADV_TRACK_CB       ble_advtrack_cb;
36 #else
37 tBTM_BLE_BATCH_SCAN_CB      *ble_batchscan_cb_ptr;
38 tBTM_BLE_ADV_TRACK_CB       *ble_advtrack_cb_ptr;
39 #define ble_batchscan_cb    (*ble_batchscan_cb_ptr)
40 #define ble_advtrack_cb     (*ble_advtrack_cb_ptr)
41 #endif
42 
43 /* length of each batch scan command */
44 #define BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN      4
45 #define BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN    12
46 #define BTM_BLE_BATCH_SCAN_ENB_DISB_LEN         2
47 #define BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN     2
48 
49 #define BTM_BLE_BATCH_SCAN_CB_EVT_MASK       0xF0
50 #define BTM_BLE_BATCH_SCAN_SUBCODE_MASK      0x0F
51 
52 /*******************************************************************************
53 **  Local functions
54 *******************************************************************************/
55 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params);
56 void btm_ble_batchscan_cleanup(void);
57 
58 /*******************************************************************************
59 **
60 ** Function         btm_ble_batchscan_filter_track_adv_vse_cback
61 **
62 ** Description      VSE callback for batch scan, filter, and tracking events.
63 **
64 ** Returns          None
65 **
66 *******************************************************************************/
btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len,UINT8 * p)67 void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p)
68 {
69     tBTM_BLE_TRACK_ADV_DATA adv_data;
70 
71     UINT8   sub_event = 0;
72     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
73     STREAM_TO_UINT8(sub_event, p);
74 
75     BTM_TRACE_EVENT("btm_ble_batchscan_filter_track_adv_vse_cback called with event:%x", sub_event);
76     if (HCI_VSE_SUBCODE_BLE_THRESHOLD_SUB_EVT == sub_event &&
77             NULL != ble_batchscan_cb.p_thres_cback) {
78         ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value);
79         return;
80     }
81 
82     if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback) {
83         if (len < 10) {
84             return;
85         }
86 
87         memset(&adv_data, 0 , sizeof(tBTM_BLE_TRACK_ADV_DATA));
88         BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
89         adv_data.client_if = (UINT8)ble_advtrack_cb.ref_value;
90         if (cmn_ble_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION) {
91             STREAM_TO_UINT8(adv_data.filt_index, p);
92             STREAM_TO_UINT8(adv_data.advertiser_state, p);
93             STREAM_TO_UINT8(adv_data.advertiser_info_present, p);
94             STREAM_TO_BDADDR(adv_data.bd_addr.address, p);
95             STREAM_TO_UINT8(adv_data.addr_type, p);
96 
97             /* Extract the adv info details */
98             if (ADV_INFO_PRESENT == adv_data.advertiser_info_present) {
99                 STREAM_TO_UINT8(adv_data.tx_power, p);
100                 STREAM_TO_UINT8(adv_data.rssi_value, p);
101                 STREAM_TO_UINT16(adv_data.time_stamp, p);
102 
103                 STREAM_TO_UINT8(adv_data.adv_pkt_len, p);
104                 if (adv_data.adv_pkt_len > 0) {
105                     adv_data.p_adv_pkt_data = osi_malloc(adv_data.adv_pkt_len);
106                     memcpy(adv_data.p_adv_pkt_data, p, adv_data.adv_pkt_len);
107                 }
108 
109                 STREAM_TO_UINT8(adv_data.scan_rsp_len, p);
110                 if (adv_data.scan_rsp_len > 0) {
111                     adv_data.p_scan_rsp_data = osi_malloc(adv_data.scan_rsp_len);
112                     memcpy(adv_data.p_scan_rsp_data, p, adv_data.scan_rsp_len);
113                 }
114             }
115         } else {
116             /* Based on L-release version */
117             STREAM_TO_UINT8(adv_data.filt_index, p);
118             STREAM_TO_UINT8(adv_data.addr_type, p);
119             STREAM_TO_BDADDR(adv_data.bd_addr.address, p);
120             STREAM_TO_UINT8(adv_data.advertiser_state, p);
121         }
122 
123         BTM_TRACE_EVENT("track_adv_vse_cback called: %d, %d, %d", adv_data.filt_index,
124                         adv_data.addr_type, adv_data.advertiser_state);
125         ble_advtrack_cb.p_track_cback(&adv_data);
126         return;
127     }
128 }
129 
130 /*******************************************************************************
131 **
132 ** Function         btm_ble_batchscan_enq_op_q
133 **
134 ** Description      enqueue a batchscan operation in q to check command complete
135 **                  status
136 **
137 ** Returns          void
138 **
139 *******************************************************************************/
btm_ble_batchscan_enq_op_q(UINT8 opcode,tBTM_BLE_BATCH_SCAN_STATE cur_state,UINT8 cb_evt,tBTM_BLE_REF_VALUE ref_value)140 void btm_ble_batchscan_enq_op_q(UINT8 opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state,
141                                 UINT8 cb_evt, tBTM_BLE_REF_VALUE ref_value)
142 {
143     ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode | (cb_evt << 4));
144     ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state;
145     ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value;
146     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d",
147                     ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx],
148                     ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx],
149                     ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]);
150     ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1)
151                                      % BTM_BLE_BATCH_SCAN_MAX;
152 }
153 
154 /*******************************************************************************
155 **
156 ** Function         btm_ble_batchscan_enq_rep_q
157 **
158 ** Description      enqueue a batchscan report operation in q to check command complete
159 **                  status
160 **
161 ** Returns          void
162 **
163 *******************************************************************************/
btm_ble_batchscan_enq_rep_q(UINT8 report_format,tBTM_BLE_REF_VALUE ref_value)164 tBTM_STATUS btm_ble_batchscan_enq_rep_q(UINT8 report_format, tBTM_BLE_REF_VALUE ref_value)
165 {
166     int i = 0;
167     for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++) {
168         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i]) {
169             return BTM_ILLEGAL_VALUE;
170         }
171     }
172 
173     ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format;
174     ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value;
175     ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0;
176     ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0;
177     ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL;
178     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d",
179                     ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value);
180 
181     ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1)
182                                            % BTM_BLE_BATCH_REP_MAIN_Q_SIZE;
183     return BTM_SUCCESS;
184 }
185 
186 /*******************************************************************************
187 **
188 ** Function         btm_ble_batchscan_enq_rep_data
189 **
190 ** Description      setup the data in the main report queue
191 **
192 ** Returns          void
193 **
194 *******************************************************************************/
btm_ble_batchscan_enq_rep_data(UINT8 report_format,UINT8 num_records,UINT8 * p_data,UINT8 data_len)195 void btm_ble_batchscan_enq_rep_data(UINT8 report_format, UINT8 num_records, UINT8 *p_data,
196                                     UINT8 data_len)
197 {
198     int index = 0, len = 0;
199     UINT8 *p_orig_data = NULL, *p_app_data = NULL;
200 
201     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
202         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) {
203             break;
204         }
205     }
206 
207     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d",
208                     index, report_format, num_records, data_len);
209 
210     if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0) {
211         len = ble_batchscan_cb.main_rep_q.data_len[index];
212         p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index];
213         if (NULL != p_orig_data) {
214             p_app_data = osi_malloc(len + data_len);
215             memcpy(p_app_data, p_orig_data, len);
216             memcpy(p_app_data + len, p_data, data_len);
217             osi_free(p_orig_data);
218             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
219             ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
220             ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
221         } else {
222             p_app_data = osi_malloc(data_len);
223             memcpy(p_app_data, p_data, data_len);
224             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
225             ble_batchscan_cb.main_rep_q.num_records[index] = num_records;
226             ble_batchscan_cb.main_rep_q.data_len[index] = data_len;
227         }
228     }
229 }
230 
231 /*******************************************************************************
232 **
233 ** Function         btm_ble_batchscan_deq_rep_q
234 **
235 ** Description      dequeue a batchscan report  in q when command complete
236 **                  is received
237 **
238 ** Returns          void
239 **
240 *******************************************************************************/
btm_ble_batchscan_deq_rep_data(UINT8 report_format,tBTM_BLE_REF_VALUE * p_ref_value,UINT8 * p_num_records,UINT8 ** p_data,UINT16 * p_data_len)241 void btm_ble_batchscan_deq_rep_data(UINT8 report_format, tBTM_BLE_REF_VALUE *p_ref_value,
242                                     UINT8 *p_num_records, UINT8 **p_data, UINT16 *p_data_len)
243 {
244     int index = 0;
245 
246     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
247         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) {
248             break;
249         }
250     }
251 
252     if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index) {
253         BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format);
254         return;
255     }
256 
257     *p_num_records = ble_batchscan_cb.main_rep_q.num_records[index];
258     *p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index];
259     *p_data = ble_batchscan_cb.main_rep_q.p_data[index];
260     *p_data_len = ble_batchscan_cb.main_rep_q.data_len[index];
261 
262     ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
263     ble_batchscan_cb.main_rep_q.data_len[index] = 0;
264     ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
265     ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
266     ble_batchscan_cb.main_rep_q.num_records[index] = 0;
267 
268     BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d",
269                     index, report_format, *p_num_records, *p_data_len);
270 
271     ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1)
272             % BTM_BLE_BATCH_SCAN_MAX;
273 }
274 
275 /*******************************************************************************
276 **
277 ** Function         btm_ble_batchscan_deq_op_q
278 **
279 ** Description      dequeue a batch scan operation from q when command complete
280 **                  is received
281 **
282 ** Returns          void
283 **
284 *******************************************************************************/
btm_ble_batchscan_deq_op_q(UINT8 * p_opcode,tBTM_BLE_BATCH_SCAN_STATE * cur_state,UINT8 * p_cb_evt,tBTM_BLE_REF_VALUE * p_ref)285 void btm_ble_batchscan_deq_op_q(UINT8 *p_opcode, tBTM_BLE_BATCH_SCAN_STATE *cur_state,
286                                 UINT8 *p_cb_evt, tBTM_BLE_REF_VALUE *p_ref)
287 {
288     *p_cb_evt = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] >> 4);
289     *p_opcode = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx]
290                  & BTM_BLE_BATCH_SCAN_SUBCODE_MASK);
291     *p_ref = ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.pending_idx];
292     *cur_state = (ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.pending_idx]);
293     ble_batchscan_cb.op_q.pending_idx = (ble_batchscan_cb.op_q.pending_idx + 1)
294                                         % BTM_BLE_BATCH_SCAN_MAX;
295 }
296 
297 /*******************************************************************************
298 **
299 ** Function         btm_ble_read_batchscan_reports
300 **
301 ** Description      This function reads the reports from controller
302 **
303 ** Parameters       scan_mode - The mode for which the reports are to be read out from the controller
304 **                  ref_value - Reference value
305 **
306 ** Returns          status
307 **
308 *******************************************************************************/
btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,tBTM_BLE_REF_VALUE ref_value)309 tBTM_STATUS btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
310         tBTM_BLE_REF_VALUE ref_value)
311 {
312     tBTM_STATUS     status = BTM_NO_RESOURCES;
313     UINT8 param[BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN], *pp;
314     pp = param;
315 
316     memset(param, 0, BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN);
317 
318     UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_READ_RESULTS);
319     UINT8_TO_STREAM (pp, scan_mode);
320 
321     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
322                   BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN, param, btm_ble_batchscan_vsc_cmpl_cback))
323             != BTM_CMD_STARTED) {
324         BTM_TRACE_ERROR("btm_ble_read_batchscan_reports %d", status);
325         return BTM_ILLEGAL_VALUE;
326     }
327 
328     if (BTM_CMD_STARTED == status) {
329         /* The user needs to be provided scan read reports event */
330         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_READ_RESULTS, ble_batchscan_cb.cur_state,
331                                    BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, ref_value);
332     }
333 
334     return status;
335 }
336 
337 /*******************************************************************************
338 **
339 ** Function         btm_ble_batchscan_vsc_cmpl_cback
340 **
341 ** Description      Batch scan VSC complete callback
342 **
343 ** Parameters       p_params - VSC completed callback parameters
344 **
345 ** Returns          void
346 **
347 *******************************************************************************/
btm_ble_batchscan_vsc_cmpl_cback(tBTM_VSC_CMPL * p_params)348 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
349 {
350     UINT8  *p = p_params->p_param_buf;
351     UINT16  len = p_params->param_len;
352     tBTM_BLE_REF_VALUE ref_value = 0;
353 
354     UINT8  status = 0, subcode = 0, opcode = 0;
355     UINT8 report_format = 0, num_records = 0, cb_evt = 0;
356     UINT16 data_len = 0;
357     tBTM_BLE_BATCH_SCAN_STATE cur_state = 0;
358     tBTM_STATUS btm_status = 0;
359     UINT8 *p_data = NULL;
360 
361     if (len < 2) {
362         BTM_TRACE_ERROR("wrong length for btm_ble_batch_scan_vsc_cmpl_cback");
363         btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
364         return;
365     }
366 
367     STREAM_TO_UINT8(status, p);
368     STREAM_TO_UINT8(subcode, p);
369 
370     btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
371 
372     BTM_TRACE_DEBUG("btm_ble_batchscan op_code = %02x state = %02x cb_evt = %02x,ref_value=%d",
373                     opcode, cur_state, cb_evt, ref_value);
374 
375     if (opcode != subcode) {
376         BTM_TRACE_ERROR("Got unexpected VSC cmpl, expected: %d got: %d", subcode, opcode);
377         return;
378     }
379 
380     switch (subcode) {
381     case BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE: {
382         if (BTM_SUCCESS == status && BTM_BLE_SCAN_ENABLE_CALLED == cur_state) {
383             ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLED_STATE;
384         } else if (BTM_BLE_SCAN_ENABLE_CALLED == cur_state) {
385             BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after enb");
386             ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
387         }
388 
389         BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d",
390                         status, ble_batchscan_cb.cur_state, cb_evt);
391 
392         if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
393             ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
394         }
395         break;
396     }
397 
398     case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM: {
399         BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d",
400                         status, cb_evt);
401         if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
402             ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
403         }
404         break;
405     }
406 
407     case BTM_BLE_BATCH_SCAN_SET_PARAMS: {
408         BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt);
409 
410         if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state) {
411             if (BTM_SUCCESS == status) {
412                 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
413             } else {
414                 BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled");
415                 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
416             }
417         }
418 
419         if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
420             ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
421         }
422         break;
423     }
424 
425     case BTM_BLE_BATCH_SCAN_READ_RESULTS: {
426         if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback) {
427             STREAM_TO_UINT8(report_format, p);
428             STREAM_TO_UINT8(num_records, p);
429             p = (uint8_t *)(p_params->p_param_buf + 4);
430             BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d",
431                             status, len - 4, num_records);
432 
433             if (0 == num_records) {
434                 btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
435                                                &p_data, &data_len);
436                 if (NULL != ble_batchscan_cb.p_scan_rep_cback) {
437                     ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format, num_records,
438                                                       data_len, p_data, status);
439                 }
440             } else {
441                 if ((len - 4) > 0) {
442                     btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len - 4);
443                     /* More records could be in the buffer and needs to be pulled out */
444                     btm_status = btm_ble_read_batchscan_reports(report_format, ref_value);
445                     if (BTM_CMD_STARTED != btm_status) {
446                         btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
447                                                        &p_data, &data_len);
448                         /* Send whatever is available, in case of a command failure */
449                         if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data) {
450                             ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format,
451                                                               num_records, data_len, p_data, status);
452                         }
453                     }
454                 }
455             }
456         }
457         break;
458     }
459 
460     default:
461         break;
462     }
463 
464     return;
465 }
466 
467 /*******************************************************************************
468 **
469 ** Function         btm_ble_set_storage_config
470 **
471 ** Description      This function writes the storage configuration in controller
472 **
473 ** Parameters       batch_scan_full_max -Max storage space (in %) allocated to full scanning
474 **                  batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
475 **                  batch_scan_notify_threshold - Setup notification level based on total space
476 **
477 ** Returns          status
478 **
479 *******************************************************************************/
btm_ble_set_storage_config(UINT8 batch_scan_full_max,UINT8 batch_scan_trunc_max,UINT8 batch_scan_notify_threshold)480 tBTM_STATUS btm_ble_set_storage_config(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
481                                        UINT8 batch_scan_notify_threshold)
482 {
483     tBTM_STATUS     status = BTM_NO_RESOURCES;
484     UINT8 param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp;
485 
486     pp = param;
487     memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN);
488 
489     UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM);
490     UINT8_TO_STREAM (pp, batch_scan_full_max);
491     UINT8_TO_STREAM (pp, batch_scan_trunc_max);
492     UINT8_TO_STREAM (pp, batch_scan_notify_threshold);
493 
494     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
495                   BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param,
496                   btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
497         BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status);
498         return BTM_ILLEGAL_VALUE;
499     }
500 
501     return status;
502 }
503 
504 /*******************************************************************************
505 **
506 ** Function         btm_ble_set_batchscan_param
507 **
508 ** Description      This function writes the batch scan params in controller
509 **
510 ** Parameters       scan_mode -Batch scan mode
511 **                  scan_interval - Scan interval
512 **                  scan_window  - Scan window
513 **                  discard_rule -Discard rules
514 **                  addr_type - Address type
515 **
516 ** Returns          status
517 **
518 *******************************************************************************/
btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,UINT32 scan_interval,UINT32 scan_window,tBLE_ADDR_TYPE addr_type,tBTM_BLE_DISCARD_RULE discard_rule)519 tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
520                                         UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
521                                         tBTM_BLE_DISCARD_RULE discard_rule)
522 {
523     tBTM_STATUS     status = BTM_NO_RESOURCES;
524     UINT8 scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan;
525 
526     pp_scan = scan_param;
527     memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN);
528 
529     // Override param and decide addr_type based on own addr type
530     // TODO: Remove upper layer parameter?
531     addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
532 
533     UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS);
534     UINT8_TO_STREAM (pp_scan, scan_mode);
535     UINT32_TO_STREAM (pp_scan, scan_window);
536     UINT32_TO_STREAM (pp_scan, scan_interval);
537     UINT8_TO_STREAM (pp_scan, addr_type);
538     UINT8_TO_STREAM (pp_scan, discard_rule);
539 
540     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
541                   BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN,
542                   scan_param, btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
543         BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status);
544         return BTM_ILLEGAL_VALUE;
545     }
546 
547     return status;
548 }
549 
550 /*******************************************************************************
551 **
552 ** Function         btm_ble_enable_disable_batchscan
553 **
554 ** Description      This function enables the customer specific feature in controller
555 **
556 ** Parameters       enable_disable: true - enable, false - disable
557 **
558 ** Returns          status
559 **
560 *******************************************************************************/
btm_ble_enable_disable_batchscan(BOOLEAN should_enable)561 tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable)
562 {
563     tBTM_STATUS     status = BTM_NO_RESOURCES;
564     UINT8 shld_enable = 0x01;
565     UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable;
566 
567     if (!should_enable) {
568         shld_enable = 0x00;
569     }
570 
571     if (should_enable) {
572         pp_enable = enable_param;
573         memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
574 
575         UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
576         UINT8_TO_STREAM (pp_enable, shld_enable);
577 
578         if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF,
579                                                 BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
580                                                 btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
581             status = BTM_MODE_UNSUPPORTED;
582             BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
583             return BTM_ILLEGAL_VALUE;
584         }
585     } else if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE,
586                          ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window,
587                          ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED) {
588         status = BTM_MODE_UNSUPPORTED;
589         BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
590         return BTM_ILLEGAL_VALUE;
591     }
592 
593     if (should_enable) {
594         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
595     } else {
596         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED;
597     }
598     return status;
599 }
600 
601 /*******************************************************************************
602 **
603 ** Function         BTM_BleSetStorageConfig
604 **
605 ** Description      This function is called to write storage config params.
606 **
607 ** Parameters:      batch_scan_full_max - Max storage space (in %) allocated to full style
608 **                  batch_scan_trunc_max - Max storage space (in %) allocated to trunc style
609 **                  batch_scan_notify_threshold - Setup notification level based on total space
610 **                  p_setup_cback - Setup callback pointer
611 **                  p_thres_cback - Threshold callback pointer
612 **                  p_rep_cback - Reports callback pointer
613 **                  ref_value - Reference value
614 **
615 ** Returns          tBTM_STATUS
616 **
617 *******************************************************************************/
BTM_BleSetStorageConfig(UINT8 batch_scan_full_max,UINT8 batch_scan_trunc_max,UINT8 batch_scan_notify_threshold,tBTM_BLE_SCAN_SETUP_CBACK * p_setup_cback,tBTM_BLE_SCAN_THRESHOLD_CBACK * p_thres_cback,tBTM_BLE_SCAN_REP_CBACK * p_rep_cback,tBTM_BLE_REF_VALUE ref_value)618 tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
619                                     UINT8 batch_scan_notify_threshold,
620                                     tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback,
621                                     tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
622                                     tBTM_BLE_SCAN_REP_CBACK *p_rep_cback,
623                                     tBTM_BLE_REF_VALUE ref_value)
624 {
625     tBTM_STATUS     status = BTM_NO_RESOURCES;
626     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
627 
628     BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d",
629                      ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max,
630                      batch_scan_notify_threshold);
631 
632     if (!controller_get_interface()->supports_ble()) {
633         return BTM_ILLEGAL_VALUE;
634     }
635 
636     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
637 
638     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
639         BTM_TRACE_ERROR("Controller does not support batch scan");
640         return BTM_ERR_PROCESSING;
641     }
642 
643     ble_batchscan_cb.p_setup_cback = p_setup_cback;
644     ble_batchscan_cb.p_thres_cback = p_thres_cback;
645     ble_batchscan_cb.p_scan_rep_cback = p_rep_cback;
646     ble_batchscan_cb.ref_value = ref_value;
647 
648     if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX ||
649             batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX ||
650             batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX) {
651         BTM_TRACE_ERROR("Illegal set storage config params");
652         return BTM_ILLEGAL_VALUE;
653     }
654 
655     if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
656             BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
657             BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
658         status = btm_ble_enable_disable_batchscan(TRUE);
659         if (BTM_CMD_STARTED != status) {
660             return status;
661         }
662 
663         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
664         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
665                                    BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
666     }
667 
668     status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max,
669                                         batch_scan_notify_threshold);
670     if (BTM_CMD_STARTED != status) {
671         return status;
672     }
673     /* The user needs to be provided scan config storage event */
674     btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state,
675                                BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value);
676 
677     return status;
678 }
679 
680 
681 /*******************************************************************************
682 **
683 ** Function         BTM_BleEnableBatchScan
684 **
685 ** Description      This function is called to configure and enable batch scanning
686 **
687 ** Parameters:      scan_mode -Batch scan mode
688 **                  scan_interval - Scan interval value
689 **                  scan_window - Scan window value
690 **                  discard_rule - Data discard rule
691 **                  ref_value - Reference value
692 **
693 ** Returns          tBTM_STATUS
694 **
695 *******************************************************************************/
BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,UINT32 scan_interval,UINT32 scan_window,tBLE_ADDR_TYPE addr_type,tBTM_BLE_DISCARD_RULE discard_rule,tBTM_BLE_REF_VALUE ref_value)696 tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
697                                    UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
698                                    tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value)
699 {
700     tBTM_STATUS     status = BTM_NO_RESOURCES;
701     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
702     BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d",
703                      scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value);
704 
705     if (!controller_get_interface()->supports_ble()) {
706         return BTM_ILLEGAL_VALUE;
707     }
708 
709     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
710 
711     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
712         BTM_TRACE_ERROR("Controller does not support batch scan");
713         return BTM_ERR_PROCESSING;
714     }
715 
716     BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval,
717                     scan_window, discard_rule, ble_batchscan_cb.cur_state);
718 
719     /* Only 16 bits will be used for scan interval and scan window as per agreement with Google */
720     /* So the standard LE range would suffice for scan interval and scan window */
721     if ((BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) ||
722             BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
723             && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode
724                 || BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode)
725             && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
726                 BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule)) {
727         if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
728                 BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
729                 BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
730             status = btm_ble_enable_disable_batchscan(TRUE);
731             if (BTM_CMD_STARTED != status) {
732                 return status;
733             }
734             btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
735                                        BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
736         }
737 
738         ble_batchscan_cb.scan_mode = scan_mode;
739         ble_batchscan_cb.scan_interval = scan_interval;
740         ble_batchscan_cb.scan_window = scan_window;
741         ble_batchscan_cb.addr_type = addr_type;
742         ble_batchscan_cb.discard_rule = discard_rule;
743         /* This command starts batch scanning, if enabled */
744         status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
745                                              discard_rule);
746         if (BTM_CMD_STARTED != status) {
747             return status;
748         }
749 
750         /* The user needs to be provided scan enable event */
751         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state,
752                                    BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value);
753     } else {
754         BTM_TRACE_ERROR("Illegal enable scan params");
755         return BTM_ILLEGAL_VALUE;
756     }
757     return status;
758 }
759 
760 /*******************************************************************************
761 **
762 ** Function         BTM_BleDisableBatchScan
763 **
764 ** Description      This function is called to disable batch scanning
765 **
766 ** Parameters:      ref_value - Reference value
767 **
768 ** Returns          tBTM_STATUS
769 **
770 *******************************************************************************/
BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value)771 tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value)
772 {
773     tBTM_STATUS     status = BTM_NO_RESOURCES;
774     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
775     BTM_TRACE_EVENT (" BTM_BleDisableBatchScan");
776 
777     if (!controller_get_interface()->supports_ble()) {
778         return BTM_ILLEGAL_VALUE;
779     }
780 
781     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
782 
783     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
784         BTM_TRACE_ERROR("Controller does not support batch scan");
785         return BTM_ERR_PROCESSING;
786     }
787 
788     status = btm_ble_enable_disable_batchscan(FALSE);
789     if (BTM_CMD_STARTED == status) {
790         /* The user needs to be provided scan disable event */
791         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS,
792                                    BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT,
793                                    ref_value);
794     }
795 
796     return status;
797 }
798 
799 /*******************************************************************************
800 **
801 ** Function         BTM_BleReadScanReports
802 **
803 ** Description      This function is called to start reading batch scan reports
804 **
805 ** Parameters:      scan_mode - Batch scan mode
806 **                  ref_value - Reference value
807 **
808 ** Returns          tBTM_STATUS
809 **
810 *******************************************************************************/
BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,tBTM_BLE_REF_VALUE ref_value)811 tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
812                                    tBTM_BLE_REF_VALUE ref_value)
813 {
814     tBTM_STATUS     status = BTM_NO_RESOURCES;
815     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
816     UINT8 read_scan_mode = 0;
817     UINT8  *p_data = NULL, num_records = 0;
818     UINT16 data_len = 0;
819 
820     BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value);
821 
822     if (!controller_get_interface()->supports_ble()) {
823         return BTM_ILLEGAL_VALUE;
824     }
825 
826     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
827 
828     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
829         BTM_TRACE_ERROR("Controller does not support batch scan");
830         return BTM_ERR_PROCESSING;
831     }
832 
833     /*  Check if the requested scan mode has already been setup by the user */
834     read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI;
835     if (0 == read_scan_mode) {
836         read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS;
837     }
838 
839     /* Check only for modes, as scan reports can be called after disabling batch scan */
840     if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
841                                BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode)) {
842         status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value);
843         if (BTM_SUCCESS == status) {
844             status = btm_ble_read_batchscan_reports(scan_mode, ref_value);
845             if (BTM_CMD_STARTED != status) {
846                 btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
847                                                &num_records, &p_data, &data_len);
848             }
849         }
850     } else {
851         BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode,
852                         ble_batchscan_cb.cur_state);
853         return BTM_ILLEGAL_VALUE;
854     }
855     return status;
856 }
857 
858 
859 /*******************************************************************************
860 **
861 ** Function         BTM_BleTrackAdvertiser
862 **
863 ** Description      This function is called to setup the callback for tracking advertisers
864 **
865 ** Parameters:      p_track_cback - Tracking callback pointer
866 **                  ref_value - Reference value
867 **
868 ** Returns          tBTM_STATUS
869 **
870 *******************************************************************************/
BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK * p_track_cback,tBTM_BLE_REF_VALUE ref_value)871 tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback,
872                                    tBTM_BLE_REF_VALUE ref_value)
873 {
874     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
875     BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser");
876     if (!controller_get_interface()->supports_ble()) {
877         return BTM_ILLEGAL_VALUE;
878     }
879 
880     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
881 
882     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
883         BTM_TRACE_ERROR("Controller does not support scan storage");
884         return BTM_ERR_PROCESSING;
885     }
886 
887     ble_advtrack_cb.p_track_cback = p_track_cback;
888     ble_advtrack_cb.ref_value = ref_value;
889     return BTM_CMD_STARTED;
890 }
891 
892 /*******************************************************************************
893 **
894 ** Function         btm_ble_batchscan_init
895 **
896 ** Description      This function initialize the batch scan control block.
897 **
898 ** Parameters       None
899 **
900 ** Returns          status
901 **
902 *******************************************************************************/
btm_ble_batchscan_init(void)903 void btm_ble_batchscan_init(void)
904 {
905 #if BTM_DYNAMIC_MEMORY == TRUE
906     ble_batchscan_cb_ptr = (tBTM_BLE_BATCH_SCAN_CB *)osi_malloc(sizeof(tBTM_BLE_BATCH_SCAN_CB));
907     ble_advtrack_cb_ptr = (tBTM_BLE_ADV_TRACK_CB *)osi_malloc(sizeof(tBTM_BLE_ADV_TRACK_CB));
908     if (ble_batchscan_cb_ptr == NULL || ble_advtrack_cb_ptr == NULL) {
909         BTM_TRACE_ERROR("%s malloc failed", __func__);
910         return;
911     }
912 #endif
913     BTM_TRACE_EVENT (" btm_ble_batchscan_init");
914     memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
915     memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
916     BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE);
917 }
918 
919 /*******************************************************************************
920 **
921 ** Function         btm_ble_batchscan_cleanup
922 **
923 ** Description      This function cleans the batch scan control block.
924 **
925 ** Parameters       None
926 **
927 ** Returns          void
928 **
929 *******************************************************************************/
btm_ble_batchscan_cleanup(void)930 void btm_ble_batchscan_cleanup(void)
931 {
932     int index = 0;
933     BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup");
934 
935     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
936         if (NULL != ble_batchscan_cb.main_rep_q.p_data[index]) {
937             osi_free(ble_batchscan_cb.main_rep_q.p_data[index]);
938             ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
939         }
940     }
941 
942     memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
943     memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
944 
945 #if BTM_DYNAMIC_MEMORY == TRUE
946     osi_free(ble_batchscan_cb_ptr);
947     osi_free(ble_advtrack_cb_ptr);
948     ble_batchscan_cb_ptr = NULL;
949     ble_advtrack_cb_ptr = NULL;
950 #endif
951 }
952 
953 #endif
954