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 19 #include <string.h> 20 #include "bt_target.h" 21 22 #if (BLE_INCLUDED == TRUE) 23 #include "bt_types.h" 24 #include "hcimsgs.h" 25 #include "btu.h" 26 #include "btm_int.h" 27 #include "bt_utils.h" 28 #include "hcidefs.h" 29 #include "btm_ble_api.h" 30 #include "vendor_ble.h" 31 32 #define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3 33 #define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13 34 35 #define BTM_BLE_PF_BIT_TO_MASK(x) (UINT16)(1 << (x)) 36 37 38 tBTM_BLE_ADV_FILTER_CB btm_ble_adv_filt_cb; 39 tBTM_BLE_VSC_CB cmn_ble_vsc_cb; 40 static const BD_ADDR na_bda= {0}; 41 42 static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, 43 UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, UINT8 num_available); 44 45 #define BTM_BLE_SET_SCAN_PF_OPCODE(x, y) (((x)<<4)|y) 46 #define BTM_BLE_GET_SCAN_PF_SUBCODE(x) ((x) >> 4) 47 #define BTM_BLE_GET_SCAN_PF_ACTION(x) ((x) & 0x0f) 48 #define BTM_BLE_INVALID_COUNTER 0xff 49 50 51 /* length of each multi adv sub command */ 52 #define BTM_BLE_ADV_FILTER_ENB_LEN 3 53 54 /* length of each batch scan command */ 55 #define BTM_BLE_ADV_FILTER_CLEAR_LEN 3 56 #define BTM_BLE_ADV_FILTER_LEN 2 57 58 #define BTM_BLE_ADV_FILT_CB_EVT_MASK 0xF0 59 #define BTM_BLE_ADV_FILT_SUBCODE_MASK 0x0F 60 61 /******************************************************************************* 62 ** 63 ** Function btm_ble_obtain_vsc_details 64 ** 65 ** Description This function obtains the VSC details 66 ** 67 ** Parameters 68 ** 69 ** Returns status 70 ** 71 *******************************************************************************/ 72 tBTM_STATUS btm_ble_obtain_vsc_details() 73 { 74 tBTM_STATUS st = BTM_SUCCESS; 75 76 #if BLE_VND_INCLUDED == TRUE 77 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); 78 if (0 == cmn_ble_vsc_cb.max_filter) 79 { 80 st = BTM_MODE_UNSUPPORTED; 81 return st; 82 } 83 #else 84 cmn_ble_vsc_cb.max_filter = BTM_BLE_MAX_FILTER_COUNTER; 85 #endif 86 return st; 87 } 88 89 /******************************************************************************* 90 ** 91 ** Function btm_ble_advfilt_enq_op_q 92 ** 93 ** Description enqueue an adv filter operation in q to check command complete 94 ** status 95 ** 96 ** Returns void 97 ** 98 *******************************************************************************/ 99 void btm_ble_advfilt_enq_op_q(UINT8 action, UINT8 ocf, tBTM_BLE_FILT_CB_EVT cb_evt, 100 tBTM_BLE_REF_VALUE ref, tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, 101 tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback) 102 { 103 btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx] = (action |(ocf << 4)); 104 btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.next_idx] = ref; 105 btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.next_idx] = cb_evt; 106 btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_cmpl_cback; 107 btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.next_idx] 108 = p_filt_param_cback; 109 BTM_TRACE_DEBUG("btm_ble_advfilt_enq_op_q: act_ocf:%d, action:%d, ocf:%d,cb_evt;%d, cback:%x", 110 btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx], action, 111 ocf, cb_evt, p_cmpl_cback); 112 btm_ble_adv_filt_cb.op_q.next_idx = (btm_ble_adv_filt_cb.op_q.next_idx + 1) 113 % BTM_BLE_PF_TYPE_MAX; 114 } 115 116 /******************************************************************************* 117 ** 118 ** Function btm_ble_advfilt_deq_op_q 119 ** 120 ** Description dequeue an adv filter operation from q when command complete 121 ** is received 122 ** 123 ** Returns void 124 ** 125 *******************************************************************************/ 126 void btm_ble_advfilt_deq_op_q(UINT8 *p_action,UINT8 *p_ocf, tBTM_BLE_FILT_CB_EVT *p_cb_evt, 127 tBTM_BLE_REF_VALUE *p_ref, tBTM_BLE_PF_CFG_CBACK ** p_cmpl_cback, 128 tBTM_BLE_PF_PARAM_CBACK **p_filt_param_cback) 129 { 130 *p_ocf = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] >> 4); 131 *p_action = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] 132 & BTM_BLE_ADV_FILT_SUBCODE_MASK); 133 *p_ref = btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.pending_idx]; 134 *p_cb_evt = btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.pending_idx]; 135 *p_cmpl_cback = btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.pending_idx]; 136 *p_filt_param_cback = 137 btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.pending_idx]; 138 139 btm_ble_adv_filt_cb.op_q.pending_idx = (btm_ble_adv_filt_cb.op_q.pending_idx + 1) 140 % BTM_BLE_PF_TYPE_MAX; 141 BTM_TRACE_DEBUG("btm_ble_advfilt_deq_op_q: ocf:%d, action:%d, ref_value:%d, cb_evt:%x", 142 *p_ocf,*p_action, *p_ref, *p_cb_evt); 143 } 144 145 /******************************************************************************* 146 ** 147 ** Function btm_ble_condtype_to_ocf 148 ** 149 ** Description Convert cond_type to OCF 150 ** 151 ** Returns Returns ocf value 152 ** 153 *******************************************************************************/ 154 UINT8 btm_ble_condtype_to_ocf(UINT8 cond_type) 155 { 156 UINT8 ocf = 0; 157 158 switch(cond_type) 159 { 160 case BTM_BLE_PF_ADDR_FILTER: 161 ocf = BTM_BLE_META_PF_ADDR; 162 break; 163 case BTM_BLE_PF_SRVC_UUID: 164 ocf = BTM_BLE_META_PF_UUID; 165 break; 166 case BTM_BLE_PF_SRVC_SOL_UUID: 167 ocf = BTM_BLE_META_PF_SOL_UUID; 168 break; 169 case BTM_BLE_PF_LOCAL_NAME: 170 ocf = BTM_BLE_META_PF_LOCAL_NAME; 171 break; 172 case BTM_BLE_PF_MANU_DATA: 173 ocf = BTM_BLE_META_PF_MANU_DATA; 174 break; 175 case BTM_BLE_PF_SRVC_DATA_PATTERN: 176 ocf = BTM_BLE_META_PF_SRVC_DATA; 177 break; 178 case BTM_BLE_PF_TYPE_ALL: 179 ocf = BTM_BLE_META_PF_ALL; 180 break; 181 default: 182 ocf = BTM_BLE_PF_TYPE_MAX; 183 break; 184 } 185 return ocf; 186 } 187 188 /******************************************************************************* 189 ** 190 ** Function btm_ble_ocf_to_condtype 191 ** 192 ** Description Convert OCF to cond type 193 ** 194 ** Returns Returns condtype value 195 ** 196 *******************************************************************************/ 197 UINT8 btm_ble_ocf_to_condtype(UINT8 ocf) 198 { 199 UINT8 cond_type = 0; 200 201 switch(ocf) 202 { 203 case BTM_BLE_META_PF_FEAT_SEL: 204 cond_type = BTM_BLE_META_PF_FEAT_SEL; 205 break; 206 case BTM_BLE_META_PF_ADDR: 207 cond_type = BTM_BLE_PF_ADDR_FILTER; 208 break; 209 case BTM_BLE_META_PF_UUID: 210 cond_type = BTM_BLE_PF_SRVC_UUID; 211 break; 212 case BTM_BLE_META_PF_SOL_UUID: 213 cond_type = BTM_BLE_PF_SRVC_SOL_UUID; 214 break; 215 case BTM_BLE_META_PF_LOCAL_NAME: 216 cond_type = BTM_BLE_PF_LOCAL_NAME; 217 break; 218 case BTM_BLE_META_PF_MANU_DATA: 219 cond_type = BTM_BLE_PF_MANU_DATA; 220 break; 221 case BTM_BLE_META_PF_SRVC_DATA: 222 cond_type = BTM_BLE_PF_SRVC_DATA_PATTERN; 223 break; 224 case BTM_BLE_META_PF_ALL: 225 cond_type = BTM_BLE_PF_TYPE_ALL; 226 break; 227 default: 228 cond_type = BTM_BLE_PF_TYPE_MAX; 229 break; 230 } 231 return cond_type; 232 } 233 234 /******************************************************************************* 235 ** 236 ** Function btm_ble_scan_pf_cmpl_cback 237 ** 238 ** Description the BTM BLE customer feature VSC complete callback for ADV PF filtering 239 ** 240 ** Returns pointer to the counter if found; NULL otherwise. 241 ** 242 *******************************************************************************/ 243 void btm_ble_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params) 244 { 245 UINT8 status = 0; 246 UINT8 *p = p_params->p_param_buf, op_subcode = 0, action = 0xff; 247 UINT16 evt_len = p_params->param_len; 248 UINT8 ocf = BTM_BLE_META_PF_ALL, cond_type = 0; 249 UINT8 num_avail = 0, cb_evt = 0; 250 tBTM_BLE_REF_VALUE ref_value = 0; 251 tBTM_BLE_PF_CFG_CBACK *p_scan_cfg_cback = NULL; 252 tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback = NULL; 253 254 if (evt_len < 3 || evt_len > 4) 255 { 256 BTM_TRACE_ERROR("cannot interpret APCF callback status = %d, length = %d", status, evt_len); 257 btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback, 258 &p_filt_param_cback); 259 return; 260 } 261 262 btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback, 263 &p_filt_param_cback); 264 265 STREAM_TO_UINT8(status, p); 266 STREAM_TO_UINT8(op_subcode, p); 267 STREAM_TO_UINT8(action, p); 268 269 /* Ignore the event, if it is not the same one expected */ 270 if (3 == evt_len) 271 { 272 if(ocf != op_subcode) 273 { 274 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:3-Incorrect opcode :%d, %d, %d, %d, %d, %d", 275 ocf, op_subcode, action, evt_len, ref_value, status); 276 return; 277 } 278 else 279 { 280 if(NULL != btm_ble_adv_filt_cb.p_filt_stat_cback) 281 btm_ble_adv_filt_cb.p_filt_stat_cback(action, status, ref_value); 282 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback enabled/disabled, %d, %d, %d, %d", 283 ocf, action, status, ref_value); 284 return; 285 } 286 } 287 288 if (4 == evt_len && ocf != op_subcode) 289 { 290 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:4-Incorrect opcode: %d, %d, %d, %d, %d", 291 ocf, op_subcode, action, status, ref_value); 292 return; 293 } 294 295 STREAM_TO_UINT8(num_avail, p); 296 switch (op_subcode) 297 { 298 case BTM_BLE_META_PF_ADDR: 299 case BTM_BLE_META_PF_UUID: 300 case BTM_BLE_META_PF_SOL_UUID: 301 case BTM_BLE_META_PF_LOCAL_NAME: 302 case BTM_BLE_META_PF_MANU_DATA: 303 case BTM_BLE_META_PF_SRVC_DATA: 304 cond_type = btm_ble_ocf_to_condtype(ocf); 305 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback Recd: %d, %d, %d, %d, %d, %d", op_subcode, 306 ocf, action, status, ref_value, num_avail); 307 if (HCI_SUCCESS == status) 308 { 309 if (memcmp(&btm_ble_adv_filt_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0) 310 btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail); 311 else 312 btm_ble_cs_update_pf_counter(action, cond_type, 313 &btm_ble_adv_filt_cb.cur_filter_target, num_avail); 314 } 315 316 /* send ADV PF operation complete */ 317 btm_ble_adv_filt_cb.op_type = 0; 318 break; 319 320 case BTM_BLE_META_PF_FEAT_SEL: 321 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback-Feat sel event: %d, %d, %d, %d", 322 action, status, ref_value, num_avail); 323 break; 324 325 default: 326 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback: unknown operation: %d", op_subcode); 327 break; 328 } 329 330 switch(cb_evt) 331 { 332 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback: calling the cback: %d", cb_evt); 333 case BTM_BLE_FILT_CFG: 334 if(NULL != p_scan_cfg_cback) 335 p_scan_cfg_cback(action, cond_type, num_avail, status, ref_value); 336 break; 337 case BTM_BLE_FILT_ADV_PARAM: 338 if(NULL != p_filt_param_cback) 339 p_filt_param_cback(action, num_avail, ref_value, status); 340 break; 341 default: 342 break; 343 } 344 } 345 346 /******************************************************************************* 347 ** 348 ** Function btm_ble_find_addr_filter_counter 349 ** 350 ** Description find the per bd address ADV payload filter counter by BD_ADDR. 351 ** 352 ** Returns pointer to the counter if found; NULL otherwise. 353 ** 354 *******************************************************************************/ 355 tBTM_BLE_PF_COUNT* btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda) 356 { 357 UINT8 i; 358 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; 359 360 if (p_le_bda == NULL) 361 return &btm_ble_adv_filt_cb.p_addr_filter_count[0]; 362 363 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) 364 { 365 if (p_addr_filter->in_use && 366 memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) 367 { 368 return p_addr_filter; 369 } 370 } 371 return NULL; 372 } 373 374 /******************************************************************************* 375 ** 376 ** Function btm_ble_alloc_addr_filter_counter 377 ** 378 ** Description allocate the per device adv payload filter counter. 379 ** 380 ** Returns pointer to the counter if allocation succeed; NULL otherwise. 381 ** 382 *******************************************************************************/ 383 tBTM_BLE_PF_COUNT * btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr) 384 { 385 UINT8 i; 386 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; 387 388 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) 389 { 390 if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) 391 { 392 memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN); 393 p_addr_filter->in_use = TRUE; 394 return p_addr_filter; 395 } 396 } 397 return NULL; 398 } 399 /******************************************************************************* 400 ** 401 ** Function btm_ble_dealloc_addr_filter_counter 402 ** 403 ** Description de-allocate the per device adv payload filter counter. 404 ** 405 ** Returns TRUE if deallocation succeed; FALSE otherwise. 406 ** 407 *******************************************************************************/ 408 BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type) 409 { 410 UINT8 i; 411 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; 412 BOOLEAN found = FALSE; 413 414 if (BTM_BLE_PF_TYPE_ALL == filter_type && NULL == p_bd_addr) 415 memset(&btm_ble_adv_filt_cb.p_addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT)); 416 417 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) 418 { 419 if ((p_addr_filter->in_use) && (NULL == p_bd_addr || 420 (NULL != p_bd_addr && 421 memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0))) 422 { 423 found = TRUE; 424 memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT)); 425 426 if (NULL != p_bd_addr) break; 427 } 428 } 429 return found; 430 } 431 432 /******************************************************************************* 433 ** 434 ** Function btm_ble_update_pf_local_name 435 ** 436 ** Description this function update(add,delete or clear) the adv lcoal name filtering condition. 437 ** 438 ** 439 ** Returns BTM_SUCCESS if sucessful, 440 ** BTM_ILLEGAL_VALUE if paramter is not valid. 441 ** 442 *******************************************************************************/ 443 tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action, 444 tBTM_BLE_PF_FILT_INDEX filt_index, 445 tBTM_BLE_PF_COND_PARAM *p_cond) 446 { 447 tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name; 448 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH], 449 *p = param, 450 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; 451 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 452 453 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH); 454 455 UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME); 456 UINT8_TO_STREAM(p, action); 457 458 /* Filter index */ 459 UINT8_TO_STREAM(p, filt_index); 460 461 if (BTM_BLE_SCAN_COND_ADD == action || 462 BTM_BLE_SCAN_COND_DELETE == action) 463 { 464 if (NULL == p_local_name) 465 return st; 466 467 if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX) 468 p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX; 469 470 ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len); 471 len += p_local_name->data_len; 472 } 473 474 /* send local name filter */ 475 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 476 len, 477 param, 478 btm_ble_scan_pf_cmpl_cback)) 479 != BTM_NO_RESOURCES) 480 { 481 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 482 } 483 else 484 { 485 BTM_TRACE_ERROR("Local Name PF filter update failed"); 486 } 487 488 return st; 489 } 490 491 492 /******************************************************************************* 493 ** 494 ** Function btm_ble_update_srvc_data_change 495 ** 496 ** Description this function update(add/remove) service data change filter. 497 ** 498 ** 499 ** Returns BTM_SUCCESS if sucessful, 500 ** BTM_ILLEGAL_VALUE if paramter is not valid. 501 ** 502 *******************************************************************************/ 503 tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action, 504 tBTM_BLE_PF_FILT_INDEX filt_index, 505 tBTM_BLE_PF_COND_PARAM *p_cond) 506 { 507 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 508 tBLE_BD_ADDR *p_bd_addr = p_cond ? &p_cond->target_addr : NULL; 509 UINT8 num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1; 510 511 if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail) 512 != BTM_BLE_INVALID_COUNTER) 513 st = BTM_SUCCESS; 514 515 return st; 516 } 517 518 /******************************************************************************* 519 ** 520 ** Function btm_ble_update_pf_manu_data 521 ** 522 ** Description this function update(add,delete or clear) the adv manufacturer 523 ** data filtering condition. 524 ** 525 ** 526 ** Returns BTM_SUCCESS if sucessful, 527 ** BTM_ILLEGAL_VALUE if paramter is not valid. 528 ** 529 *******************************************************************************/ 530 tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action, 531 tBTM_BLE_PF_FILT_INDEX filt_index, 532 tBTM_BLE_PF_COND_PARAM *p_data, 533 tBTM_BLE_PF_COND_TYPE cond_type, 534 tBTM_BLE_FILT_CB_EVT cb_evt, 535 tBTM_BLE_REF_VALUE ref_value) 536 { 537 tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data; 538 tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data; 539 540 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH], 541 *p = param, 542 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; 543 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 544 545 if (NULL == p_data) 546 return st; 547 548 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX 549 + BTM_BLE_ADV_FILT_META_HDR_LENGTH); 550 551 if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) 552 { 553 UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA); 554 } 555 else 556 { 557 UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA); 558 } 559 560 UINT8_TO_STREAM(p, action); 561 562 /* Filter index */ 563 UINT8_TO_STREAM(p, filt_index); 564 565 if (BTM_BLE_SCAN_COND_ADD == action || BTM_BLE_SCAN_COND_DELETE == action) 566 { 567 if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) 568 { 569 if (NULL == p_srvc_data) 570 return st; 571 if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) 572 p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); 573 574 if (p_srvc_data->data_len > 0) 575 { 576 ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len); 577 len += (p_srvc_data->data_len); 578 ARRAY_TO_STREAM(p, p_srvc_data->p_pattern_mask, p_srvc_data->data_len); 579 } 580 581 len += (p_srvc_data->data_len); 582 BTM_TRACE_DEBUG("Service data length: %d", len); 583 } 584 else 585 { 586 if (NULL == p_manu_data) 587 { 588 BTM_TRACE_ERROR("btm_ble_update_pf_manu_data - No manuf data"); 589 return st; 590 } 591 BTM_TRACE_EVENT("btm_ble_update_pf_manu_data length: %d", 592 p_manu_data->data_len); 593 if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) 594 p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); 595 596 UINT16_TO_STREAM(p, p_manu_data->company_id); 597 if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) 598 { 599 ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len); 600 len += (p_manu_data->data_len + 2); 601 } 602 else 603 len += 2; 604 605 if (p_manu_data->company_id_mask != 0) 606 { 607 UINT16_TO_STREAM (p, p_manu_data->company_id_mask); 608 } 609 else 610 { 611 memset(p, 0xff, 2); 612 p += 2; 613 } 614 len += 2; 615 616 if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) 617 { 618 ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len); 619 len += (p_manu_data->data_len); 620 } 621 622 BTM_TRACE_DEBUG("Manuf data length: %d", len); 623 } 624 } 625 626 /* send manufacturer*/ 627 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 628 len, 629 param, 630 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 631 { 632 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 633 } 634 else 635 { 636 BTM_TRACE_ERROR("manufacturer data PF filter update failed"); 637 } 638 639 return st; 640 } 641 642 /******************************************************************************* 643 ** 644 ** Function btm_ble_cs_update_pf_counter 645 ** 646 ** Description this function is to update the adv data payload filter counter 647 ** 648 ** Returns current number of the counter; BTM_BLE_INVALID_COUNTER if 649 ** counter update failed. 650 ** 651 *******************************************************************************/ 652 UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, 653 UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, 654 UINT8 num_available) 655 { 656 tBTM_BLE_PF_COUNT *p_addr_filter = NULL; 657 UINT8 *p_counter = NULL; 658 659 btm_ble_obtain_vsc_details(); 660 661 if (cond_type > BTM_BLE_PF_TYPE_ALL) 662 { 663 BTM_TRACE_ERROR("unknown PF filter condition type %d", cond_type); 664 return BTM_BLE_INVALID_COUNTER; 665 } 666 667 /* for these three types of filter, always generic */ 668 if (BTM_BLE_PF_ADDR_FILTER == cond_type || 669 BTM_BLE_PF_MANU_DATA == cond_type || 670 BTM_BLE_PF_LOCAL_NAME == cond_type || 671 BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) 672 p_bd_addr = NULL; 673 674 if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL && 675 BTM_BLE_SCAN_COND_ADD == action) 676 { 677 p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda); 678 } 679 680 if (NULL != p_addr_filter) 681 { 682 /* all filter just cleared */ 683 if ((BTM_BLE_PF_TYPE_ALL == cond_type && BTM_BLE_SCAN_COND_CLEAR == action) || 684 /* or bd address filter been deleted */ 685 (BTM_BLE_PF_ADDR_FILTER == cond_type && 686 (BTM_BLE_SCAN_COND_DELETE == action || BTM_BLE_SCAN_COND_CLEAR == action))) 687 { 688 btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type); 689 } 690 /* if not feature selection, update new addition/reduction of the filter counter */ 691 else if (cond_type != BTM_BLE_PF_TYPE_ALL) 692 { 693 p_counter = p_addr_filter->pf_counter; 694 if (num_available > 0) 695 p_counter[cond_type] += 1; 696 697 BTM_TRACE_DEBUG("counter = %d, maxfilt = %d, num_avbl=%d", 698 p_counter[cond_type], cmn_ble_vsc_cb.max_filter, num_available); 699 return p_counter[cond_type]; 700 } 701 } 702 else 703 { 704 BTM_TRACE_ERROR("no matching filter counter found"); 705 } 706 /* no matching filter located and updated */ 707 return BTM_BLE_INVALID_COUNTER; 708 } 709 710 711 /******************************************************************************* 712 ** 713 ** Function btm_ble_update_addr_filter 714 ** 715 ** Description this function update(add,delete or clear) the address filter of adv. 716 ** 717 ** 718 ** Returns BTM_SUCCESS if sucessful, 719 ** BTM_ILLEGAL_VALUE if paramter is not valid. 720 ** 721 *******************************************************************************/ 722 tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action, 723 tBTM_BLE_PF_FILT_INDEX filt_index, 724 tBTM_BLE_PF_COND_PARAM *p_cond) 725 { 726 UINT8 param[BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH], 727 * p= param; 728 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 729 tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr; 730 731 memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH); 732 733 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); 734 UINT8_TO_STREAM(p, action); 735 736 /* Filter index */ 737 UINT8_TO_STREAM(p, filt_index); 738 739 if (BTM_BLE_SCAN_COND_ADD == action || 740 BTM_BLE_SCAN_COND_DELETE == action) 741 { 742 if (NULL == p_addr) 743 return st; 744 745 BDADDR_TO_STREAM(p, p_addr->bda); 746 UINT8_TO_STREAM(p, p_addr->type); 747 } 748 /* send address filter */ 749 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 750 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), 751 param, 752 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 753 { 754 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 755 } 756 else 757 { 758 BTM_TRACE_ERROR("Broadcaster Address Filter Update failed"); 759 } 760 return st; 761 } 762 763 /******************************************************************************* 764 ** 765 ** Function btm_ble_update_uuid_filter 766 ** 767 ** Description this function update(add,delete or clear) service UUID filter. 768 ** 769 ** 770 ** Returns BTM_SUCCESS if sucessful, 771 ** BTM_ILLEGAL_VALUE if paramter is not valid. 772 ** 773 *******************************************************************************/ 774 tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, 775 tBTM_BLE_PF_FILT_INDEX filt_index, 776 tBTM_BLE_PF_COND_TYPE filter_type, 777 tBTM_BLE_PF_COND_PARAM *p_cond, 778 tBTM_BLE_FILT_CB_EVT cb_evt, 779 tBTM_BLE_REF_VALUE ref_value) 780 { 781 UINT8 param[BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH], 782 * p= param, 783 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; 784 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 785 tBTM_BLE_PF_UUID_COND *p_uuid_cond; 786 UINT8 evt_type; 787 788 memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH); 789 790 if (BTM_BLE_PF_SRVC_UUID == filter_type) 791 { 792 evt_type = BTM_BLE_META_PF_UUID; 793 p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL; 794 } 795 else 796 { 797 evt_type = BTM_BLE_META_PF_SOL_UUID; 798 p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL; 799 } 800 801 if (NULL == p_uuid_cond && action != BTM_BLE_SCAN_COND_CLEAR) 802 { 803 BTM_TRACE_ERROR("Illegal param for add/delete UUID filter"); 804 return st; 805 } 806 807 /* need to add address filter first, if adding per bda UUID filter without address filter */ 808 if (BTM_BLE_SCAN_COND_ADD == action && NULL != p_uuid_cond && 809 p_uuid_cond->p_target_addr && 810 btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL) 811 { 812 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); 813 UINT8_TO_STREAM(p, action); 814 815 /* Filter index */ 816 UINT8_TO_STREAM(p, filt_index); 817 818 BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda); 819 UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type); 820 821 /* send address filter */ 822 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 823 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), 824 param, 825 btm_ble_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES) 826 { 827 BTM_TRACE_ERROR("Update Address filter into controller failed."); 828 return st; 829 } 830 831 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_ADDR, cb_evt, ref_value, NULL, NULL); 832 BTM_TRACE_DEBUG("Updated Address filter"); 833 } 834 835 p = param; 836 UINT8_TO_STREAM(p, evt_type); 837 UINT8_TO_STREAM(p, action); 838 839 /* Filter index */ 840 UINT8_TO_STREAM(p, filt_index); 841 842 if ((BTM_BLE_SCAN_COND_ADD == action || 843 BTM_BLE_SCAN_COND_DELETE == action) && 844 NULL != p_uuid_cond) 845 { 846 if (p_uuid_cond->uuid.len == LEN_UUID_16) 847 { 848 UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16); 849 len += LEN_UUID_16; 850 } 851 else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */ 852 { 853 UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32); 854 len += LEN_UUID_32; 855 } 856 else if (p_uuid_cond->uuid.len == LEN_UUID_128) 857 { 858 ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128); 859 len += LEN_UUID_128; 860 } 861 else 862 { 863 BTM_TRACE_ERROR("illegal UUID length: %d", p_uuid_cond->uuid.len); 864 return BTM_ILLEGAL_VALUE; 865 } 866 867 if (NULL != p_uuid_cond->p_uuid_mask) 868 { 869 if (p_uuid_cond->uuid.len == LEN_UUID_16) 870 { 871 UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask); 872 len += LEN_UUID_16; 873 } 874 else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */ 875 { 876 UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask); 877 len += LEN_UUID_32; 878 } 879 else if (p_uuid_cond->uuid.len == LEN_UUID_128) 880 { 881 ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128); 882 len += LEN_UUID_128; 883 } 884 } 885 else 886 { 887 memset(p, 0xff, p_uuid_cond->uuid.len); 888 len += p_uuid_cond->uuid.len; 889 } 890 BTM_TRACE_DEBUG("btm_ble_update_uuid_filter : %d, %d, %d, %d", filter_type, evt_type, 891 p_uuid_cond->uuid.len, len); 892 } 893 894 /* send UUID filter update */ 895 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 896 len, 897 param, 898 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 899 { 900 if (p_uuid_cond && p_uuid_cond->p_target_addr) 901 memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_uuid_cond->p_target_addr, 902 sizeof(tBLE_BD_ADDR)); 903 else 904 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 905 } 906 else 907 { 908 BTM_TRACE_ERROR("UUID filter udpating failed"); 909 } 910 911 return st; 912 } 913 914 915 /******************************************************************************* 916 ** 917 ** Function btm_ble_clear_scan_pf_filter 918 ** 919 ** Description clear all adv payload filter by de-select all the adv pf feature bits 920 ** 921 ** 922 ** Returns BTM_SUCCESS if sucessful, 923 ** BTM_ILLEGAL_VALUE if paramter is not valid. 924 ** 925 *******************************************************************************/ 926 tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action, 927 tBTM_BLE_PF_FILT_INDEX filt_index, 928 tBTM_BLE_PF_COND_PARAM *p_cond, 929 tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, 930 tBTM_BLE_FILT_CB_EVT cb_evt, 931 tBTM_BLE_REF_VALUE ref_value) 932 { 933 tBLE_BD_ADDR *p_target = (p_cond == NULL)? NULL : &p_cond->target_addr; 934 tBTM_BLE_PF_COUNT *p_bda_filter; 935 tBTM_STATUS st = BTM_WRONG_MODE; 936 UINT8 param[20], *p; 937 938 if (BTM_BLE_SCAN_COND_CLEAR != action) 939 { 940 BTM_TRACE_ERROR("unable to perform action:%d for generic adv filter type", action); 941 return BTM_ILLEGAL_VALUE; 942 } 943 944 p = param; 945 memset(param, 0, 20); 946 947 p_bda_filter = btm_ble_find_addr_filter_counter(p_target); 948 949 if (NULL == p_bda_filter || 950 /* not a generic filter */ 951 (p_target != NULL && p_bda_filter)) 952 { 953 BTM_TRACE_ERROR("Error: Can not clear filter, No PF filter has been configured!"); 954 return st; 955 } 956 957 /* clear the general filter entry */ 958 if (NULL == p_target) 959 { 960 /* clear manufactuer data filter */ 961 st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL, 962 BTM_BLE_PF_MANU_DATA, cb_evt, ref_value); 963 if(BTM_CMD_STARTED == st) 964 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_MANU_DATA, cb_evt, 965 ref_value, NULL, NULL); 966 967 /* clear local name filter */ 968 st = btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL); 969 if(BTM_CMD_STARTED == st) 970 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_LOCAL_NAME, cb_evt, 971 ref_value, NULL, NULL); 972 973 /* update the counter for service data */ 974 st = btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL); 975 976 /* clear UUID filter */ 977 st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index, 978 BTM_BLE_PF_SRVC_UUID, NULL, cb_evt, ref_value); 979 if(BTM_CMD_STARTED == st) 980 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_UUID, cb_evt, ref_value, NULL, NULL); 981 982 st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index, 983 BTM_BLE_PF_SRVC_SOL_UUID, NULL, cb_evt, ref_value); 984 if(BTM_CMD_STARTED == st) 985 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SOL_UUID, cb_evt, 986 ref_value, NULL, NULL); 987 988 /* clear service data filter */ 989 st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL, 990 BTM_BLE_PF_SRVC_DATA_PATTERN, cb_evt, ref_value); 991 if(BTM_CMD_STARTED == st) 992 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SRVC_DATA, cb_evt, 993 ref_value, NULL, NULL); 994 } 995 996 /* select feature based on control block settings */ 997 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 998 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR); 999 1000 /* Filter index */ 1001 UINT8_TO_STREAM(p, filt_index); 1002 1003 /* set PCF selection */ 1004 UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE); 1005 /* set logic condition as OR as default */ 1006 UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR); 1007 1008 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 1009 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN), 1010 param, 1011 btm_ble_scan_pf_cmpl_cback)) 1012 != BTM_NO_RESOURCES) 1013 { 1014 if (p_target) 1015 memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR)); 1016 else 1017 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 1018 } 1019 return st; 1020 } 1021 1022 /******************************************************************************* 1023 ** 1024 ** Function BTM_BleAdvFilterParamSetup 1025 ** 1026 ** Description This function is called to setup the adv data payload filter 1027 ** condition. 1028 ** 1029 ** Parameters action - Type of action to be performed 1030 ** filt_index - Filter index 1031 ** p_filt_params - Filter parameters 1032 ** p_target - Target device 1033 ** p_cmpl_back - Callback pointer 1034 ** ref_value - reference value 1035 ** 1036 ** Returns void 1037 ** 1038 *******************************************************************************/ 1039 tBTM_STATUS BTM_BleAdvFilterParamSetup(int action, tBTM_BLE_PF_FILT_INDEX filt_index, 1040 tBTM_BLE_PF_FILT_PARAMS *p_filt_params, 1041 tBLE_BD_ADDR *p_target, tBTM_BLE_PF_PARAM_CBACK *p_cmpl_cback, 1042 tBTM_BLE_REF_VALUE ref_value) 1043 { 1044 UINT8 param[20], *p; 1045 tBTM_STATUS st = BTM_WRONG_MODE; 1046 tBTM_BLE_PF_COUNT *p_bda_filter = NULL; 1047 UINT8 len =0; 1048 1049 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) 1050 return st; 1051 1052 p = param; 1053 memset(param, 0, 20); 1054 BTM_TRACE_EVENT (" BTM_BleAdvFilterParamSetup"); 1055 1056 if (BTM_BLE_SCAN_COND_ADD == action) 1057 { 1058 p_bda_filter = btm_ble_find_addr_filter_counter(p_target); 1059 if (NULL == p_bda_filter) 1060 { 1061 BTM_TRACE_ERROR("BD Address not found!"); 1062 return st; 1063 } 1064 1065 BTM_TRACE_DEBUG("BTM_BleAdvFilterParamSetup : Feat mask:%d", p_filt_params->feat_seln); 1066 /* select feature based on control block settings */ 1067 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 1068 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD); 1069 1070 /* Filter index */ 1071 UINT8_TO_STREAM(p, filt_index); 1072 1073 /* set PCF selection */ 1074 UINT16_TO_STREAM(p, p_filt_params->feat_seln); 1075 /* set logic type */ 1076 UINT16_TO_STREAM(p, p_filt_params->logic_type); 1077 /* set logic condition */ 1078 UINT8_TO_STREAM(p, p_filt_params->filt_logic_type); 1079 /* set RSSI high threshold */ 1080 UINT8_TO_STREAM(p, p_filt_params->rssi_high_thres); 1081 /* set delivery mode */ 1082 UINT8_TO_STREAM(p, p_filt_params->dely_mode); 1083 1084 if (0x01 == p_filt_params->dely_mode) 1085 { 1086 /* set onfound timeout */ 1087 UINT16_TO_STREAM(p, p_filt_params->found_timeout); 1088 /* set onfound timeout count*/ 1089 UINT8_TO_STREAM(p, p_filt_params->found_timeout_cnt); 1090 /* set RSSI low threshold */ 1091 UINT8_TO_STREAM(p, p_filt_params->rssi_low_thres); 1092 /* set onlost timeout */ 1093 UINT16_TO_STREAM(p, p_filt_params->lost_timeout); 1094 } 1095 1096 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN; 1097 1098 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 1099 (UINT8)len, 1100 param, 1101 btm_ble_scan_pf_cmpl_cback)) 1102 == BTM_NO_RESOURCES) 1103 { 1104 return st; 1105 } 1106 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, 1107 ref_value, NULL, p_cmpl_cback); 1108 } 1109 else 1110 if (BTM_BLE_SCAN_COND_DELETE == action) 1111 { 1112 /* select feature based on control block settings */ 1113 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 1114 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_DELETE); 1115 /* Filter index */ 1116 UINT8_TO_STREAM(p, filt_index); 1117 1118 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 1119 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH), 1120 param, 1121 btm_ble_scan_pf_cmpl_cback)) 1122 == BTM_NO_RESOURCES) 1123 { 1124 return st; 1125 } 1126 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, 1127 ref_value, NULL, p_cmpl_cback); 1128 } 1129 else 1130 if (BTM_BLE_SCAN_COND_CLEAR == action) 1131 { 1132 /* Deallocate all filters here */ 1133 btm_ble_dealloc_addr_filter_counter(NULL, BTM_BLE_PF_TYPE_ALL); 1134 1135 /* select feature based on control block settings */ 1136 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 1137 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR); 1138 1139 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 1140 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH-1), 1141 param, 1142 btm_ble_scan_pf_cmpl_cback)) 1143 == BTM_NO_RESOURCES) 1144 { 1145 return st; 1146 } 1147 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, 1148 ref_value, NULL, p_cmpl_cback); 1149 } 1150 1151 return st; 1152 } 1153 1154 /******************************************************************************* 1155 ** 1156 ** Function BTM_BleEnableDisableFilterFeature 1157 ** 1158 ** Description This function is called to enable / disable the APCF feature 1159 ** 1160 ** Parameters enable the generic scan condition. 1161 ** enable: enable or disable the filter condition 1162 ** p_stat_cback - Status callback pointer 1163 ** ref_value - Ref value 1164 ** Returns void 1165 ** 1166 *******************************************************************************/ 1167 tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable, 1168 tBTM_BLE_PF_STATUS_CBACK *p_stat_cback, 1169 tBTM_BLE_REF_VALUE ref_value) 1170 { 1171 UINT8 param[20], *p; 1172 tBTM_STATUS st = BTM_WRONG_MODE; 1173 1174 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) 1175 return st; 1176 1177 p = param; 1178 memset(param, 0, 20); 1179 1180 /* enable the content filter in controller */ 1181 p = param; 1182 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE); 1183 /* enable adv data payload filtering */ 1184 UINT8_TO_STREAM(p, enable); 1185 1186 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, 1187 BTM_BLE_PCF_ENABLE_LEN, param, 1188 btm_ble_scan_pf_cmpl_cback)) == BTM_CMD_STARTED) 1189 { 1190 btm_ble_adv_filt_cb.p_filt_stat_cback = p_stat_cback; 1191 btm_ble_advfilt_enq_op_q(enable, BTM_BLE_META_PF_ENABLE, BTM_BLE_FILT_ENABLE_DISABLE, 1192 ref_value, NULL, NULL); 1193 } 1194 return st; 1195 } 1196 1197 /******************************************************************************* 1198 ** 1199 ** Function BTM_BleCfgFilterCondition 1200 ** 1201 ** Description This function is called to configure the adv data payload filter 1202 ** condition. 1203 ** 1204 ** Parameters action: to read/write/clear 1205 ** cond_type: filter condition type. 1206 ** filt_index - Filter index 1207 ** p_cond: filter condition parameter 1208 ** p_cmpl_cback - Config callback pointer 1209 ** ref_value - Reference value 1210 ** 1211 ** Returns void 1212 ** 1213 *******************************************************************************/ 1214 tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action, 1215 tBTM_BLE_PF_COND_TYPE cond_type, 1216 tBTM_BLE_PF_FILT_INDEX filt_index, 1217 tBTM_BLE_PF_COND_PARAM *p_cond, 1218 tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, 1219 tBTM_BLE_REF_VALUE ref_value) 1220 { 1221 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 1222 UINT8 ocf = 0; 1223 BTM_TRACE_EVENT (" BTM_BleCfgFilterCondition action:%d, cond_type:%d, index:%d", action, 1224 cond_type, filt_index); 1225 1226 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) 1227 return st; 1228 1229 switch (cond_type) 1230 { 1231 /* write service data filter */ 1232 case BTM_BLE_PF_SRVC_DATA_PATTERN: 1233 /* write manufacturer data filter */ 1234 case BTM_BLE_PF_MANU_DATA: 1235 st = btm_ble_update_pf_manu_data(action, filt_index, p_cond, cond_type, 0, ref_value); 1236 break; 1237 1238 /* write local name filter */ 1239 case BTM_BLE_PF_LOCAL_NAME: 1240 st = btm_ble_update_pf_local_name(action, filt_index, p_cond); 1241 break; 1242 1243 /* filter on advertiser address */ 1244 case BTM_BLE_PF_ADDR_FILTER: 1245 st = btm_ble_update_addr_filter(action, filt_index, p_cond); 1246 break; 1247 1248 /* filter on service/solicitated UUID */ 1249 case BTM_BLE_PF_SRVC_UUID: 1250 case BTM_BLE_PF_SRVC_SOL_UUID: 1251 st = btm_ble_update_uuid_filter(action, filt_index, cond_type, p_cond, 0, ref_value); 1252 break; 1253 1254 case BTM_BLE_PF_SRVC_DATA: 1255 st = btm_ble_update_srvc_data_change(action, filt_index, p_cond); 1256 break; 1257 1258 case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */ 1259 st = btm_ble_clear_scan_pf_filter(action, filt_index, p_cond, p_cmpl_cback, 1260 0, ref_value); 1261 break; 1262 1263 default: 1264 BTM_TRACE_WARNING("condition type [%d] not supported currently.", cond_type); 1265 break; 1266 } 1267 1268 if(BTM_CMD_STARTED == st && cond_type != BTM_BLE_PF_TYPE_ALL) 1269 { 1270 ocf = btm_ble_condtype_to_ocf(cond_type); 1271 btm_ble_advfilt_enq_op_q(action, ocf, BTM_BLE_FILT_CFG, ref_value, p_cmpl_cback, NULL); 1272 } 1273 else 1274 if(BTM_CMD_STARTED == st && BTM_BLE_PF_TYPE_ALL == cond_type) 1275 { 1276 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_CFG, 1277 ref_value, p_cmpl_cback, NULL); 1278 } 1279 return st; 1280 } 1281 1282 /******************************************************************************* 1283 ** 1284 ** Function btm_ble_adv_filter_init 1285 ** 1286 ** Description This function initializes the adv filter control block 1287 ** 1288 ** Parameters 1289 ** 1290 ** Returns status 1291 ** 1292 *******************************************************************************/ 1293 void btm_ble_adv_filter_init(void) 1294 { 1295 memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB)); 1296 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) 1297 return; 1298 1299 if (cmn_ble_vsc_cb.max_filter > 0) 1300 { 1301 btm_ble_adv_filt_cb.p_addr_filter_count = 1302 (tBTM_BLE_PF_COUNT*) GKI_getbuf( sizeof(tBTM_BLE_PF_COUNT) * cmn_ble_vsc_cb.max_filter); 1303 } 1304 1305 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 1306 return; 1307 } 1308 1309 /******************************************************************************* 1310 ** 1311 ** Function btm_ble_adv_filter_cleanup 1312 ** 1313 ** Description This function de-initializes the adv filter control block 1314 ** 1315 ** Parameters 1316 ** 1317 ** Returns status 1318 ** 1319 *******************************************************************************/ 1320 void btm_ble_adv_filter_cleanup(void) 1321 { 1322 if (btm_ble_adv_filt_cb.p_addr_filter_count) 1323 GKI_freebuf (btm_ble_adv_filt_cb.p_addr_filter_count); 1324 } 1325 1326 #endif 1327