1 /******************************************************************************
3 * Copyright (C) 2014 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
21 #include "bt_target.h"
23 #include "btm_ble_api.h"
28 #include "device/include/controller.h"
31 #if (BLE_INCLUDED == TRUE)
33 tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb;
34 tBTM_BLE_ADV_TRACK_CB ble_advtrack_cb;
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
43 #define BTM_BLE_BATCH_SCAN_CB_EVT_MASK 0xF0
44 #define BTM_BLE_BATCH_SCAN_SUBCODE_MASK 0x0F
46 /*******************************************************************************
48 *******************************************************************************/
49 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params);
50 void btm_ble_batchscan_cleanup(void);
52 /*******************************************************************************
54 ** Function btm_ble_batchscan_filter_track_adv_vse_cback
56 ** Description VSE callback for batch scan, filter, and tracking events.
60 *******************************************************************************/
61 void btm_ble_batchscan_filter_track_adv_vse_cback(uint8_t len, uint8_t *p)
63 tBTM_BLE_TRACK_ADV_DATA adv_data;
65 uint8_t sub_event = 0;
66 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
67 STREAM_TO_UINT8(sub_event, p);
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)
73 ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value);
77 if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback)
82 memset(&adv_data, 0 , sizeof(tBTM_BLE_TRACK_ADV_DATA));
83 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
84 adv_data.client_if = (uint8_t)ble_advtrack_cb.ref_value;
85 if (cmn_ble_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION)
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);
93 /* Extract the adv info details */
94 if (ADV_INFO_PRESENT == adv_data.advertiser_info_present)
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);
100 STREAM_TO_UINT8(adv_data.adv_pkt_len, p);
101 if (adv_data.adv_pkt_len > 0)
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);
107 STREAM_TO_UINT8(adv_data.scan_rsp_len, p);
108 if (adv_data.scan_rsp_len > 0)
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);
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);
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);
127 // Make sure the device is known
128 BTM_SecAddBleDevice(adv_data.bd_addr.address, NULL, BT_DEVICE_TYPE_BLE, adv_data.addr_type);
130 ble_advtrack_cb.p_track_cback(&adv_data);
135 /*******************************************************************************
137 ** Function btm_ble_batchscan_enq_op_q
139 ** Description enqueue a batchscan operation in q to check command complete
144 *******************************************************************************/
145 void btm_ble_batchscan_enq_op_q(uint8_t opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state,
146 uint8_t cb_evt, tBTM_BLE_REF_VALUE ref_value)
148 ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode |(cb_evt << 4));
149 ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state;
150 ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value;
151 BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d",
152 ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx],
153 ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx],
154 ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]);
155 ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1)
156 % BTM_BLE_BATCH_SCAN_MAX;
159 /*******************************************************************************
161 ** Function btm_ble_batchscan_enq_rep_q
163 ** Description enqueue a batchscan report operation in q to check command complete
168 *******************************************************************************/
169 tBTM_STATUS btm_ble_batchscan_enq_rep_q(uint8_t report_format, tBTM_BLE_REF_VALUE ref_value)
172 for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++)
174 if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i])
175 return BTM_ILLEGAL_VALUE;
178 ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format;
179 ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value;
180 ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0;
181 ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0;
182 ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL;
183 BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d",
184 ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value);
186 ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1)
187 % BTM_BLE_BATCH_REP_MAIN_Q_SIZE;
191 /*******************************************************************************
193 ** Function btm_ble_batchscan_enq_rep_data
195 ** Description setup the data in the main report queue
199 *******************************************************************************/
200 void btm_ble_batchscan_enq_rep_data(uint8_t report_format, uint8_t num_records, uint8_t *p_data,
205 for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
207 if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index])
211 BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d",
212 index, report_format, num_records, data_len);
214 if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0)
216 int len = ble_batchscan_cb.main_rep_q.data_len[index];
217 uint8_t *p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index];
220 if (NULL != p_orig_data)
222 p_app_data = osi_malloc(len + data_len);
223 memcpy(p_app_data, p_orig_data, len);
224 memcpy(p_app_data+len, p_data, data_len);
225 osi_free(p_orig_data);
226 ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
227 ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
228 ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
232 p_app_data = osi_malloc(data_len);
233 memcpy(p_app_data, p_data, data_len);
234 ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
235 ble_batchscan_cb.main_rep_q.num_records[index] = num_records;
236 ble_batchscan_cb.main_rep_q.data_len[index] = data_len;
241 /*******************************************************************************
243 ** Function btm_ble_batchscan_deq_rep_q
245 ** Description dequeue a batchscan report in q when command complete
250 *******************************************************************************/
251 void btm_ble_batchscan_deq_rep_data(uint8_t report_format, tBTM_BLE_REF_VALUE *p_ref_value,
252 uint8_t *p_num_records, uint8_t **p_data, uint16_t *p_data_len)
256 for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
258 if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index])
262 if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index)
264 BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format);
268 *p_num_records = ble_batchscan_cb.main_rep_q.num_records[index];
269 *p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index];
270 *p_data = ble_batchscan_cb.main_rep_q.p_data[index];
271 *p_data_len = ble_batchscan_cb.main_rep_q.data_len[index];
273 ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
274 ble_batchscan_cb.main_rep_q.data_len[index] = 0;
275 ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
276 ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
277 ble_batchscan_cb.main_rep_q.num_records[index] = 0;
279 BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d",
280 index, report_format, *p_num_records, *p_data_len);
282 ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1)
283 % BTM_BLE_BATCH_SCAN_MAX;
286 /*******************************************************************************
288 ** Function btm_ble_batchscan_deq_op_q
290 ** Description dequeue a batch scan operation from q when command complete
295 *******************************************************************************/
296 void btm_ble_batchscan_deq_op_q(uint8_t *p_opcode,tBTM_BLE_BATCH_SCAN_STATE *cur_state,
297 uint8_t *p_cb_evt, tBTM_BLE_REF_VALUE *p_ref)
299 *p_cb_evt = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] >> 4);
300 *p_opcode = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx]
301 & BTM_BLE_BATCH_SCAN_SUBCODE_MASK);
302 *p_ref = ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.pending_idx];
303 *cur_state = (ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.pending_idx]);
304 ble_batchscan_cb.op_q.pending_idx = (ble_batchscan_cb.op_q.pending_idx + 1)
305 % BTM_BLE_BATCH_SCAN_MAX;
308 /*******************************************************************************
310 ** Function btm_ble_read_batchscan_reports
312 ** Description This function reads the reports from controller
314 ** Parameters scan_mode - The mode for which the reports are to be read out from the controller
315 ** ref_value - Reference value
319 *******************************************************************************/
320 tBTM_STATUS btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
321 tBTM_BLE_REF_VALUE ref_value)
323 tBTM_STATUS status = BTM_NO_RESOURCES;
324 uint8_t param[BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN], *pp;
327 memset(param, 0, BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN);
329 UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_READ_RESULTS);
330 UINT8_TO_STREAM (pp, scan_mode);
332 if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
333 BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN, param, btm_ble_batchscan_vsc_cmpl_cback))
336 BTM_TRACE_ERROR("btm_ble_read_batchscan_reports %d", status);
337 return BTM_ILLEGAL_VALUE;
340 if (BTM_CMD_STARTED == status)
342 /* The user needs to be provided scan read reports event */
343 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_READ_RESULTS, ble_batchscan_cb.cur_state,
344 BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, ref_value);
350 /*******************************************************************************
352 ** Function btm_ble_batchscan_vsc_cmpl_cback
354 ** Description Batch scan VSC complete callback
356 ** Parameters p_params - VSC completed callback parameters
360 *******************************************************************************/
361 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
363 uint8_t *p = p_params->p_param_buf;
364 uint16_t len = p_params->param_len;
365 tBTM_BLE_REF_VALUE ref_value = 0;
367 uint8_t status = 0, subcode = 0, opcode = 0;
368 uint8_t report_format = 0, num_records = 0, cb_evt = 0;
369 uint16_t data_len = 0;
370 tBTM_BLE_BATCH_SCAN_STATE cur_state = 0;
371 tBTM_STATUS btm_status = 0;
372 uint8_t *p_data = NULL;
376 BTM_TRACE_ERROR("wrong length for btm_ble_batch_scan_vsc_cmpl_cback");
377 btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
381 STREAM_TO_UINT8(status, p);
382 STREAM_TO_UINT8(subcode, p);
384 btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
386 BTM_TRACE_DEBUG("btm_ble_batchscan op_code = %02x state = %02x cb_evt = %02x,ref_value=%d",
387 opcode, cur_state, cb_evt, ref_value);
389 if (opcode != subcode)
391 BTM_TRACE_ERROR("Got unexpected VSC cmpl, expected: %d got: %d",subcode,opcode);
397 case BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE:
399 if (BTM_SUCCESS == status && BTM_BLE_SCAN_ENABLE_CALLED == cur_state)
400 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLED_STATE;
402 if (BTM_BLE_SCAN_ENABLE_CALLED == cur_state)
404 BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after enb");
405 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
408 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d",
409 status, ble_batchscan_cb.cur_state, cb_evt);
411 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
412 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
416 case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM:
418 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d",
420 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
421 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
425 case BTM_BLE_BATCH_SCAN_SET_PARAMS:
427 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt);
429 if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
431 if (BTM_SUCCESS == status)
433 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
437 BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled");
438 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
442 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
443 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
447 case BTM_BLE_BATCH_SCAN_READ_RESULTS:
449 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback)
451 STREAM_TO_UINT8(report_format,p);
452 STREAM_TO_UINT8(num_records, p);
453 p = (uint8_t *)(p_params->p_param_buf + 4);
454 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d",
455 status, len-4, num_records);
457 if (0 == num_records)
459 btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
461 if (NULL != ble_batchscan_cb.p_scan_rep_cback)
462 ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format, num_records,
463 data_len, p_data, status);
469 btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len-4);
470 /* More records could be in the buffer and needs to be pulled out */
471 btm_status = btm_ble_read_batchscan_reports(report_format, ref_value);
472 if (BTM_CMD_STARTED != btm_status)
474 btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
476 /* Send whatever is available, in case of a command failure */
477 if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data)
478 ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format,
479 num_records, data_len, p_data, status);
494 /*******************************************************************************
496 ** Function btm_ble_set_storage_config
498 ** Description This function writes the storage configuration in controller
500 ** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning
501 ** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
502 ** batch_scan_notify_threshold - Setup notification level based on total space
506 *******************************************************************************/
507 tBTM_STATUS btm_ble_set_storage_config(uint8_t batch_scan_full_max, uint8_t batch_scan_trunc_max,
508 uint8_t batch_scan_notify_threshold)
510 tBTM_STATUS status = BTM_NO_RESOURCES;
511 uint8_t param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp;
514 memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN);
516 UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM);
517 UINT8_TO_STREAM (pp, batch_scan_full_max);
518 UINT8_TO_STREAM (pp, batch_scan_trunc_max);
519 UINT8_TO_STREAM (pp, batch_scan_notify_threshold);
521 if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
522 BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param,
523 btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED)
525 BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status);
526 return BTM_ILLEGAL_VALUE;
532 /*******************************************************************************
534 ** Function btm_ble_set_batchscan_param
536 ** Description This function writes the batch scan params in controller
538 ** Parameters scan_mode -Batch scan mode
539 ** scan_interval - Scan interval
540 ** scan_window - Scan window
541 ** discard_rule -Discard rules
542 ** addr_type - Address type
546 *******************************************************************************/
547 tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
548 uint32_t scan_interval, uint32_t scan_window, tBLE_ADDR_TYPE addr_type,
549 tBTM_BLE_DISCARD_RULE discard_rule)
551 tBTM_STATUS status = BTM_NO_RESOURCES;
552 uint8_t scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan;
554 pp_scan = scan_param;
555 memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN);
557 // Override param and decide addr_type based on own addr type
558 // TODO: Remove upper layer parameter?
559 addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
561 UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS);
562 UINT8_TO_STREAM (pp_scan, scan_mode);
563 UINT32_TO_STREAM (pp_scan, scan_window);
564 UINT32_TO_STREAM (pp_scan, scan_interval);
565 UINT8_TO_STREAM (pp_scan, addr_type);
566 UINT8_TO_STREAM (pp_scan, discard_rule);
568 if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
569 BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN,
570 scan_param, btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED)
572 BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status);
573 return BTM_ILLEGAL_VALUE;
579 /*******************************************************************************
581 ** Function btm_ble_enable_disable_batchscan
583 ** Description This function enables the customer specific feature in controller
585 ** Parameters enable_disable: true - enable, false - disable
589 *******************************************************************************/
590 tBTM_STATUS btm_ble_enable_disable_batchscan(bool should_enable)
592 tBTM_STATUS status = BTM_NO_RESOURCES;
593 uint8_t shld_enable = 0x01;
594 uint8_t enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable;
601 pp_enable = enable_param;
602 memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
604 UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
605 UINT8_TO_STREAM (pp_enable, shld_enable);
607 if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF,
608 BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
609 btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED)
611 status = BTM_MODE_UNSUPPORTED;
612 BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
613 return BTM_ILLEGAL_VALUE;
617 if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE,
618 ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window,
619 ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED)
621 status = BTM_MODE_UNSUPPORTED;
622 BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
623 return BTM_ILLEGAL_VALUE;
627 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
629 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED;
633 /*******************************************************************************
635 ** Function BTM_BleSetStorageConfig
637 ** Description This function is called to write storage config params.
639 ** Parameters: batch_scan_full_max - Max storage space (in %) allocated to full style
640 ** batch_scan_trunc_max - Max storage space (in %) allocated to trunc style
641 ** batch_scan_notify_threshold - Setup notification level based on total space
642 ** p_setup_cback - Setup callback pointer
643 ** p_thres_cback - Threshold callback pointer
644 ** p_rep_cback - Reports callback pointer
645 ** ref_value - Reference value
647 ** Returns tBTM_STATUS
649 *******************************************************************************/
650 tBTM_STATUS BTM_BleSetStorageConfig(uint8_t batch_scan_full_max, uint8_t batch_scan_trunc_max,
651 uint8_t batch_scan_notify_threshold,
652 tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback,
653 tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
654 tBTM_BLE_SCAN_REP_CBACK* p_rep_cback,
655 tBTM_BLE_REF_VALUE ref_value)
657 tBTM_STATUS status = BTM_NO_RESOURCES;
658 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
660 BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d",
661 ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max,
662 batch_scan_notify_threshold);
664 if (!controller_get_interface()->supports_ble())
665 return BTM_ILLEGAL_VALUE;
667 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
669 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
671 BTM_TRACE_ERROR("Controller does not support batch scan");
672 return BTM_ERR_PROCESSING;
675 ble_batchscan_cb.p_setup_cback = p_setup_cback;
676 ble_batchscan_cb.p_thres_cback = p_thres_cback;
677 ble_batchscan_cb.p_scan_rep_cback = p_rep_cback;
678 ble_batchscan_cb.ref_value = ref_value;
680 if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX ||
681 batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX ||
682 batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX)
684 BTM_TRACE_ERROR("Illegal set storage config params");
685 return BTM_ILLEGAL_VALUE;
688 if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
689 BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
690 BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
692 status = btm_ble_enable_disable_batchscan(true);
693 if (BTM_CMD_STARTED != status)
696 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
697 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
698 BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
701 status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max,
702 batch_scan_notify_threshold);
703 if (BTM_CMD_STARTED != status)
705 /* The user needs to be provided scan config storage event */
706 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state,
707 BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value);
713 /*******************************************************************************
715 ** Function BTM_BleEnableBatchScan
717 ** Description This function is called to configure and enable batch scanning
719 ** Parameters: scan_mode -Batch scan mode
720 ** scan_interval - Scan interval value
721 ** scan_window - Scan window value
722 ** discard_rule - Data discard rule
723 ** ref_value - Reference value
725 ** Returns tBTM_STATUS
727 *******************************************************************************/
728 tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
729 uint32_t scan_interval, uint32_t scan_window, tBLE_ADDR_TYPE addr_type,
730 tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value)
732 tBTM_STATUS status = BTM_NO_RESOURCES;
733 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
734 BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d",
735 scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value);
737 if (!controller_get_interface()->supports_ble())
738 return BTM_ILLEGAL_VALUE;
740 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
742 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
744 BTM_TRACE_ERROR("Controller does not support batch scan");
745 return BTM_ERR_PROCESSING;
748 BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval,
749 scan_window, discard_rule, ble_batchscan_cb.cur_state);
751 /* Only 16 bits will be used for scan interval and scan window as per agreement with Google */
752 /* So the standard LE range would suffice for scan interval and scan window */
753 if ((BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) ||
754 BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
755 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode
756 || BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode)
757 && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
758 BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule))
760 if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
761 BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
762 BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
764 status = btm_ble_enable_disable_batchscan(true);
765 if (BTM_CMD_STARTED != status)
767 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
768 BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
771 ble_batchscan_cb.scan_mode = scan_mode;
772 ble_batchscan_cb.scan_interval = scan_interval;
773 ble_batchscan_cb.scan_window = scan_window;
774 ble_batchscan_cb.addr_type = addr_type;
775 ble_batchscan_cb.discard_rule = discard_rule;
776 /* This command starts batch scanning, if enabled */
777 status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
779 if (BTM_CMD_STARTED != status)
782 /* The user needs to be provided scan enable event */
783 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state,
784 BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value);
788 BTM_TRACE_ERROR("Illegal enable scan params");
789 return BTM_ILLEGAL_VALUE;
794 /*******************************************************************************
796 ** Function BTM_BleDisableBatchScan
798 ** Description This function is called to disable batch scanning
800 ** Parameters: ref_value - Reference value
802 ** Returns tBTM_STATUS
804 *******************************************************************************/
805 tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value)
807 tBTM_STATUS status = BTM_NO_RESOURCES;
808 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
809 BTM_TRACE_EVENT (" BTM_BleDisableBatchScan");
811 if (!controller_get_interface()->supports_ble())
812 return BTM_ILLEGAL_VALUE;
814 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
816 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
818 BTM_TRACE_ERROR("Controller does not support batch scan");
819 return BTM_ERR_PROCESSING;
822 status = btm_ble_enable_disable_batchscan(false);
823 if (BTM_CMD_STARTED == status)
825 /* The user needs to be provided scan disable event */
826 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS,
827 BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT,
834 /*******************************************************************************
836 ** Function BTM_BleReadScanReports
838 ** Description This function is called to start reading batch scan reports
840 ** Parameters: scan_mode - Batch scan mode
841 ** ref_value - Reference value
843 ** Returns tBTM_STATUS
845 *******************************************************************************/
846 tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
847 tBTM_BLE_REF_VALUE ref_value)
849 tBTM_STATUS status = BTM_NO_RESOURCES;
850 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
851 uint8_t read_scan_mode = 0;
852 uint8_t *p_data = NULL, num_records = 0;
853 uint16_t data_len = 0;
855 BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value);
857 if (!controller_get_interface()->supports_ble())
858 return BTM_ILLEGAL_VALUE;
860 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
862 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
864 BTM_TRACE_ERROR("Controller does not support batch scan");
865 return BTM_ERR_PROCESSING;
868 /* Check if the requested scan mode has already been setup by the user */
869 read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI;
870 if (0 == read_scan_mode)
871 read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS;
873 /* Check only for modes, as scan reports can be called after disabling batch scan */
874 if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
875 BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode))
877 status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value);
878 if (BTM_SUCCESS == status)
880 status = btm_ble_read_batchscan_reports(scan_mode, ref_value);
881 if (BTM_CMD_STARTED != status)
883 btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
884 &num_records, &p_data, &data_len);
890 BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode,
891 ble_batchscan_cb.cur_state);
892 return BTM_ILLEGAL_VALUE;
898 /*******************************************************************************
900 ** Function BTM_BleTrackAdvertiser
902 ** Description This function is called to setup the callback for tracking advertisers
904 ** Parameters: p_track_cback - Tracking callback pointer
905 ** ref_value - Reference value
907 ** Returns tBTM_STATUS
909 *******************************************************************************/
910 tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback,
911 tBTM_BLE_REF_VALUE ref_value)
913 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
914 BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser");
915 if (!controller_get_interface()->supports_ble())
916 return BTM_ILLEGAL_VALUE;
918 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
920 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
922 BTM_TRACE_ERROR("Controller does not support scan storage");
923 return BTM_ERR_PROCESSING;
926 ble_advtrack_cb.p_track_cback = p_track_cback;
927 ble_advtrack_cb.ref_value = ref_value;
928 return BTM_CMD_STARTED;
931 /*******************************************************************************
933 ** Function btm_ble_batchscan_init
935 ** Description This function initialize the batch scan control block.
941 *******************************************************************************/
942 void btm_ble_batchscan_init(void)
944 BTM_TRACE_EVENT (" btm_ble_batchscan_init");
945 memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
946 memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
947 BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, true);
950 /*******************************************************************************
952 ** Function btm_ble_batchscan_cleanup
954 ** Description This function cleans the batch scan control block.
960 *******************************************************************************/
961 void btm_ble_batchscan_cleanup(void)
964 BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup");
966 for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
967 osi_free_and_reset((void **)&ble_batchscan_cb.main_rep_q.p_data[index]);
969 memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
970 memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));