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