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