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 32 tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb; 33 tBTM_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 *******************************************************************************/ 50 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params); 51 void btm_ble_batchscan_cleanup(void); 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 *******************************************************************************/ 62 void 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 *******************************************************************************/ 101 void 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 *******************************************************************************/ 125 tBTM_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 *******************************************************************************/ 156 void 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 if (NULL != p_orig_data) 176 { 177 p_app_data = GKI_getbuf(len + data_len); 178 memcpy(p_app_data, p_orig_data, len); 179 memcpy(p_app_data+len, p_data, data_len); 180 GKI_freebuf(p_orig_data); 181 ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; 182 ble_batchscan_cb.main_rep_q.num_records[index] += num_records; 183 ble_batchscan_cb.main_rep_q.data_len[index] += data_len; 184 } 185 else 186 { 187 p_app_data = GKI_getbuf(data_len); 188 memcpy(p_app_data, p_data, data_len); 189 ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; 190 ble_batchscan_cb.main_rep_q.num_records[index] = num_records; 191 ble_batchscan_cb.main_rep_q.data_len[index] = data_len; 192 } 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 *******************************************************************************/ 206 void 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 *******************************************************************************/ 251 void 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 *******************************************************************************/ 275 tBTM_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 *******************************************************************************/ 316 void 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 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d", 365 status, ble_batchscan_cb.cur_state, cb_evt); 366 367 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) 368 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); 369 break; 370 } 371 372 case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM: 373 { 374 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d", 375 status, cb_evt); 376 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) 377 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); 378 break; 379 } 380 381 case BTM_BLE_BATCH_SCAN_SET_PARAMS: 382 { 383 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt); 384 385 if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state) 386 { 387 if (BTM_SUCCESS == status) 388 { 389 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE; 390 } 391 else 392 { 393 BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled"); 394 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE; 395 } 396 } 397 398 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) 399 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); 400 break; 401 } 402 403 case BTM_BLE_BATCH_SCAN_READ_RESULTS: 404 { 405 if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback) 406 { 407 STREAM_TO_UINT8(report_format,p); 408 STREAM_TO_UINT8(num_records, p); 409 p = (uint8_t *)(p_params->p_param_buf + 4); 410 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d", 411 status, len-4, num_records); 412 413 if (0 == num_records) 414 { 415 btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records, 416 &p_data, &data_len); 417 if (NULL != ble_batchscan_cb.p_scan_rep_cback) 418 ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format, num_records, 419 data_len, p_data, status); 420 } 421 else 422 { 423 if ((len-4) > 0) 424 { 425 btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len-4); 426 /* More records could be in the buffer and needs to be pulled out */ 427 btm_status = btm_ble_read_batchscan_reports(report_format, ref_value); 428 if (BTM_CMD_STARTED != btm_status) 429 { 430 btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records, 431 &p_data, &data_len); 432 /* Send whatever is available, in case of a command failure */ 433 if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data) 434 ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format, 435 num_records, data_len, p_data, status); 436 } 437 } 438 } 439 } 440 break; 441 } 442 443 default: 444 break; 445 } 446 447 return; 448 } 449 450 /******************************************************************************* 451 ** 452 ** Function btm_ble_set_storage_config 453 ** 454 ** Description This function writes the storage configuration in controller 455 ** 456 ** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning 457 ** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning 458 ** batch_scan_notify_threshold - Setup notification level based on total space 459 ** 460 ** Returns status 461 ** 462 *******************************************************************************/ 463 tBTM_STATUS btm_ble_set_storage_config(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max, 464 UINT8 batch_scan_notify_threshold) 465 { 466 tBTM_STATUS status = BTM_NO_RESOURCES; 467 UINT8 param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp; 468 469 pp = param; 470 memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN); 471 472 UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM); 473 UINT8_TO_STREAM (pp, batch_scan_full_max); 474 UINT8_TO_STREAM (pp, batch_scan_trunc_max); 475 UINT8_TO_STREAM (pp, batch_scan_notify_threshold); 476 477 if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF, 478 BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param, 479 btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED) 480 { 481 BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status); 482 return BTM_ILLEGAL_VALUE; 483 } 484 485 return status; 486 } 487 488 /******************************************************************************* 489 ** 490 ** Function btm_ble_set_batchscan_param 491 ** 492 ** Description This function writes the batch scan params in controller 493 ** 494 ** Parameters scan_mode -Batch scan mode 495 ** scan_interval - Scan interval 496 ** scan_window - Scan window 497 ** discard_rule -Discard rules 498 ** addr_type - Address type 499 ** 500 ** Returns status 501 ** 502 *******************************************************************************/ 503 tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode, 504 UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type, 505 tBTM_BLE_DISCARD_RULE discard_rule) 506 { 507 tBTM_STATUS status = BTM_NO_RESOURCES; 508 UINT8 scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan; 509 510 pp_scan = scan_param; 511 memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN); 512 513 UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS); 514 UINT8_TO_STREAM (pp_scan, scan_mode); 515 UINT32_TO_STREAM (pp_scan, scan_window); 516 UINT32_TO_STREAM (pp_scan, scan_interval); 517 UINT8_TO_STREAM (pp_scan, addr_type); 518 UINT8_TO_STREAM (pp_scan, discard_rule); 519 520 if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF, 521 BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN, 522 scan_param, btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED) 523 { 524 BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status); 525 return BTM_ILLEGAL_VALUE; 526 } 527 528 return status; 529 } 530 531 /******************************************************************************* 532 ** 533 ** Function btm_ble_enable_disable_batchscan 534 ** 535 ** Description This function enables the customer specific feature in controller 536 ** 537 ** Parameters enable_disable: true - enable, false - disable 538 ** 539 ** Returns status 540 ** 541 *******************************************************************************/ 542 tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable) 543 { 544 tBTM_STATUS status = BTM_NO_RESOURCES; 545 UINT8 shld_enable = 0x01; 546 UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable; 547 548 if (!should_enable) 549 shld_enable = 0x00; 550 551 if (should_enable) 552 { 553 pp_enable = enable_param; 554 memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN); 555 556 UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE); 557 UINT8_TO_STREAM (pp_enable, shld_enable); 558 559 if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF, 560 BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param, 561 btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) 562 { 563 status = BTM_MODE_UNSUPPORTED; 564 BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status); 565 return BTM_ILLEGAL_VALUE; 566 } 567 } 568 else 569 if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE, 570 ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window, 571 ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED) 572 { 573 status = BTM_MODE_UNSUPPORTED; 574 BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status); 575 return BTM_ILLEGAL_VALUE; 576 } 577 578 if (should_enable) 579 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED; 580 else 581 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED; 582 return status; 583 } 584 585 /******************************************************************************* 586 ** 587 ** Function BTM_BleSetStorageConfig 588 ** 589 ** Description This function is called to write storage config params. 590 ** 591 ** Parameters: batch_scan_full_max - Max storage space (in %) allocated to full style 592 ** batch_scan_trunc_max - Max storage space (in %) allocated to trunc style 593 ** batch_scan_notify_threshold - Setup notification level based on total space 594 ** p_setup_cback - Setup callback pointer 595 ** p_thres_cback - Threshold callback pointer 596 ** p_rep_cback - Reports callback pointer 597 ** ref_value - Reference value 598 ** 599 ** Returns tBTM_STATUS 600 ** 601 *******************************************************************************/ 602 tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max, 603 UINT8 batch_scan_notify_threshold, 604 tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback, 605 tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback, 606 tBTM_BLE_SCAN_REP_CBACK* p_rep_cback, 607 tBTM_BLE_REF_VALUE ref_value) 608 { 609 tBTM_STATUS status = BTM_NO_RESOURCES; 610 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 611 612 BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d", 613 ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max, 614 batch_scan_notify_threshold); 615 616 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 617 return BTM_ILLEGAL_VALUE; 618 619 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 620 621 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) 622 { 623 BTM_TRACE_ERROR("Controller does not support batch scan"); 624 return BTM_ERR_PROCESSING; 625 } 626 627 ble_batchscan_cb.p_setup_cback = p_setup_cback; 628 ble_batchscan_cb.p_thres_cback = p_thres_cback; 629 ble_batchscan_cb.p_scan_rep_cback = p_rep_cback; 630 ble_batchscan_cb.ref_value = ref_value; 631 632 if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX || 633 batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX || 634 batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX) 635 { 636 BTM_TRACE_ERROR("Illegal set storage config params"); 637 return BTM_ILLEGAL_VALUE; 638 } 639 640 if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state || 641 BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state || 642 BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) 643 { 644 status = btm_ble_enable_disable_batchscan(TRUE); 645 if (BTM_CMD_STARTED != status) 646 return status; 647 648 ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED; 649 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE, 650 BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value); 651 } 652 653 status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max, 654 batch_scan_notify_threshold); 655 if (BTM_CMD_STARTED != status) 656 return status; 657 /* The user needs to be provided scan config storage event */ 658 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state, 659 BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value); 660 661 return status; 662 } 663 664 665 /******************************************************************************* 666 ** 667 ** Function BTM_BleEnableBatchScan 668 ** 669 ** Description This function is called to configure and enable batch scanning 670 ** 671 ** Parameters: scan_mode -Batch scan mode 672 ** scan_interval - Scan interval value 673 ** scan_window - Scan window value 674 ** discard_rule - Data discard rule 675 ** ref_value - Reference value 676 ** 677 ** Returns tBTM_STATUS 678 ** 679 *******************************************************************************/ 680 tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode, 681 UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type, 682 tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value) 683 { 684 tBTM_STATUS status = BTM_NO_RESOURCES; 685 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 686 BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d", 687 scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value); 688 689 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 690 return BTM_ILLEGAL_VALUE; 691 692 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 693 694 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) 695 { 696 BTM_TRACE_ERROR("Controller does not support batch scan"); 697 return BTM_ERR_PROCESSING; 698 } 699 700 BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval, 701 scan_window, discard_rule, ble_batchscan_cb.cur_state); 702 703 /* Only 16 bits will be used for scan interval and scan window as per agreement with Google */ 704 /* So the standard LE range would suffice for scan interval and scan window */ 705 if ((BTM_BLE_VALID_PRAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) || 706 BTM_BLE_VALID_PRAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX)) 707 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode 708 || BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode) 709 && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule || 710 BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule)) 711 { 712 if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state || 713 BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state || 714 BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) 715 { 716 status = btm_ble_enable_disable_batchscan(TRUE); 717 if (BTM_CMD_STARTED != status) 718 return status; 719 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE, 720 BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value); 721 } 722 723 ble_batchscan_cb.scan_mode = scan_mode; 724 ble_batchscan_cb.scan_interval = scan_interval; 725 ble_batchscan_cb.scan_window = scan_window; 726 ble_batchscan_cb.addr_type = addr_type; 727 ble_batchscan_cb.discard_rule = discard_rule; 728 /* This command starts batch scanning, if enabled */ 729 status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type, 730 discard_rule); 731 if (BTM_CMD_STARTED != status) 732 return status; 733 734 /* The user needs to be provided scan enable event */ 735 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state, 736 BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value); 737 } 738 else 739 { 740 BTM_TRACE_ERROR("Illegal enable scan params"); 741 return BTM_ILLEGAL_VALUE; 742 } 743 return status; 744 } 745 746 /******************************************************************************* 747 ** 748 ** Function BTM_BleDisableBatchScan 749 ** 750 ** Description This function is called to disable batch scanning 751 ** 752 ** Parameters: ref_value - Reference value 753 ** 754 ** Returns tBTM_STATUS 755 ** 756 *******************************************************************************/ 757 tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value) 758 { 759 tBTM_STATUS status = BTM_NO_RESOURCES; 760 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 761 BTM_TRACE_EVENT (" BTM_BleDisableBatchScan"); 762 763 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 764 return BTM_ILLEGAL_VALUE; 765 766 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 767 768 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) 769 { 770 BTM_TRACE_ERROR("Controller does not support batch scan"); 771 return BTM_ERR_PROCESSING; 772 } 773 774 status = btm_ble_enable_disable_batchscan(FALSE); 775 if (BTM_CMD_STARTED == status) 776 { 777 /* The user needs to be provided scan disable event */ 778 btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, 779 BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT, 780 ref_value); 781 } 782 783 return status; 784 } 785 786 /******************************************************************************* 787 ** 788 ** Function BTM_BleReadScanReports 789 ** 790 ** Description This function is called to start reading batch scan reports 791 ** 792 ** Parameters: scan_mode - Batch scan mode 793 ** ref_value - Reference value 794 ** 795 ** Returns tBTM_STATUS 796 ** 797 *******************************************************************************/ 798 tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode, 799 tBTM_BLE_REF_VALUE ref_value) 800 { 801 tBTM_STATUS status = BTM_NO_RESOURCES; 802 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 803 UINT8 read_scan_mode = 0; 804 UINT8 *p_data = NULL, report_format = 0, num_records = 0; 805 UINT16 data_len = 0; 806 807 BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value); 808 809 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 810 return BTM_ILLEGAL_VALUE; 811 812 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 813 814 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) 815 { 816 BTM_TRACE_ERROR("Controller does not support batch scan"); 817 return BTM_ERR_PROCESSING; 818 } 819 820 /* Check if the requested scan mode has already been setup by the user */ 821 read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI; 822 if (0 == read_scan_mode) 823 read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS; 824 825 /* Check only for modes, as scan reports can be called after disabling batch scan */ 826 if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || 827 BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode)) 828 { 829 status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value); 830 if (BTM_SUCCESS == status) 831 { 832 status = btm_ble_read_batchscan_reports(scan_mode, ref_value); 833 if (BTM_CMD_STARTED != status) 834 { 835 btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value, 836 &num_records, &p_data, &data_len); 837 } 838 } 839 } 840 else 841 { 842 BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode, 843 ble_batchscan_cb.cur_state); 844 return BTM_ILLEGAL_VALUE; 845 } 846 return status; 847 } 848 849 850 /******************************************************************************* 851 ** 852 ** Function BTM_BleTrackAdvertiser 853 ** 854 ** Description This function is called to setup the callback for tracking advertisers 855 ** 856 ** Parameters: p_track_cback - Tracking callback pointer 857 ** ref_value - Reference value 858 ** 859 ** Returns tBTM_STATUS 860 ** 861 *******************************************************************************/ 862 tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback, 863 tBTM_BLE_REF_VALUE ref_value) 864 { 865 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 866 BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser"); 867 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 868 return BTM_ILLEGAL_VALUE; 869 870 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 871 872 if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) 873 { 874 BTM_TRACE_ERROR("Controller does not support scan storage"); 875 return BTM_ERR_PROCESSING; 876 } 877 878 ble_advtrack_cb.p_track_cback = p_track_cback; 879 ble_advtrack_cb.ref_value = ref_value; 880 return BTM_SUCCESS; 881 } 882 883 /******************************************************************************* 884 ** 885 ** Function btm_ble_batchscan_init 886 ** 887 ** Description This function initialize the batch scan control block. 888 ** 889 ** Parameters None 890 ** 891 ** Returns status 892 ** 893 *******************************************************************************/ 894 void btm_ble_batchscan_init(void) 895 { 896 BTM_TRACE_EVENT (" btm_ble_batchscan_init"); 897 memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); 898 memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); 899 BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE); 900 } 901 902 /******************************************************************************* 903 ** 904 ** Function btm_ble_batchscan_cleanup 905 ** 906 ** Description This function cleans the batch scan control block. 907 ** 908 ** Parameters None 909 ** 910 ** Returns void 911 ** 912 *******************************************************************************/ 913 void btm_ble_batchscan_cleanup(void) 914 { 915 int index = 0; 916 BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup"); 917 918 for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) 919 { 920 if (NULL != ble_batchscan_cb.main_rep_q.p_data[index]) 921 GKI_freebuf(ble_batchscan_cb.main_rep_q.p_data[index]); 922 ble_batchscan_cb.main_rep_q.p_data[index] = NULL; 923 } 924 925 memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); 926 memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); 927 } 928 929 #endif 930