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