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