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