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