OSDN Git Service

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