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