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