vendor_ble.c revision b203d478f4835f5e35217874a1787e1914328f7c
1/****************************************************************************** 2 * 3 * Copyright (C) 2003-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/***************************************************************************** 20** 21** Name: vendor_ble.c 22** 23** Description: This file contains vendor specific feature for BLE 24** 25******************************************************************************/ 26#include <string.h> 27#include "bt_target.h" 28 29#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE) 30#include "bt_types.h" 31#include "hcimsgs.h" 32#include "btu.h" 33#include "vendor_ble.h" 34#include "vendor_hcidefs.h" 35#include "gatt_int.h" 36 37#define BTM_BLE_INVALID_COUNTER 0xff 38 39 40static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, 41 UINT8 cond_type, 42 tBLE_BD_ADDR *p_bd_addr, 43 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 49/* max number of filter available for different filter type, controller dependent number */ 50const static UINT8 btm_ble_cs_filter_max[BTM_BLE_PF_TYPE_MAX] = 51{ 52 BTM_BLE_MAX_ADDR_FILTER, /* address filter */ 53 1, /* no limit for service data change, always enable or disable */ 54 BTM_BLE_MAX_UUID_FILTER, /* service UUID filter */ 55 BTM_BLE_MAX_UUID_FILTER, /* solicitated UUID filter */ 56 BTM_BLE_PF_STR_COND_MAX, /* local name filter */ 57 BTM_BLE_PF_STR_COND_MAX /* manufacturer data filter */ 58}; 59 60/*** This needs to be moved to a VSC control block eventually per coding conventions ***/ 61#if VENDOR_DYNAMIC_MEMORY == FALSE 62tBTM_BLE_VENDOR_CB btm_ble_vendor_cb; 63#endif 64 65static const UINT8 op_code_to_cond_type[] = 66{ 67 BTM_BLE_PF_TYPE_ALL, 68 BTM_BLE_PF_ADDR_FILTER, 69 BTM_BLE_PF_SRVC_UUID, 70 BTM_BLE_PF_SRVC_SOL_UUID, 71 BTM_BLE_PF_LOCAL_NAME, 72 BTM_BLE_PF_MANU_DATA, 73 BTM_BLE_PF_SRVC_DATA_PATTERN 74}; 75 76static const BD_ADDR na_bda= {0}; 77 78/******************************************************************************* 79** 80** Function btm_ble_vendor_scan_pf_cmpl_cback 81** 82** Description the BTM BLE customer feature VSC complete callback for ADV PF 83** filtering 84** 85** Returns pointer to the counter if found; NULL otherwise. 86** 87*******************************************************************************/ 88void btm_ble_vendor_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params) 89{ 90 UINT8 status; 91 UINT8 *p = p_params->p_param_buf, op_subcode, action = 0xff; 92 UINT16 evt_len = p_params->param_len; 93 UINT8 num_avail = 0, cond_type = BTM_BLE_PF_TYPE_MAX; 94 tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback = btm_ble_vendor_cb.p_scan_pf_cback; 95 UINT8 op = BTM_BLE_GET_SCAN_PF_ACTION(btm_ble_vendor_cb.op_type); 96 UINT8 subcode = BTM_BLE_GET_SCAN_PF_SUBCODE(btm_ble_vendor_cb.op_type); 97 98 STREAM_TO_UINT8(status, p); 99 100 evt_len--; 101 102 if (evt_len < 1 ) 103 { 104 BTM_TRACE_ERROR1("can not interpret ADV PF filter setting callback. status = %d", status); 105 return; 106 } 107 op_subcode = *p ++; 108 109 switch (op_subcode) 110 { 111 case BTM_BLE_META_PF_LOCAL_NAME: 112 case BTM_BLE_META_PF_MANU_DATA: 113 case BTM_BLE_META_PF_ADDR: 114 case BTM_BLE_META_PF_UUID: 115 case BTM_BLE_META_PF_SOL_UUID: 116 case BTM_BLE_META_PF_FEAT_SEL: 117 case BTM_BLE_META_PF_SRVC_DATA: 118 cond_type = op_code_to_cond_type[op_subcode - BTM_BLE_META_PF_FEAT_SEL]; 119 if (status == HCI_SUCCESS) 120 { 121 action = *p ++; 122 if (op_subcode != BTM_BLE_META_PF_FEAT_SEL) 123 { 124 STREAM_TO_UINT8(num_avail, p); 125 } 126 127 if (memcmp(&btm_ble_vendor_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0) 128 btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail); 129 else 130 btm_ble_cs_update_pf_counter(action, cond_type, &btm_ble_vendor_cb.cur_filter_target, num_avail); 131 } 132 break; 133 134 case BTM_BLE_META_PF_ENABLE: 135 cond_type = BTM_BLE_META_PF_ENABLE; 136 BTM_TRACE_DEBUG0("CS feature Enabled"); 137 break; 138 139 default: 140 BTM_TRACE_ERROR1("unknow operation: %d", op_subcode); 141 break; 142 } 143 144 /* send ADV PF opeartion complete */ 145 if (p_cmpl_cback && subcode == cond_type) 146 { 147 btm_ble_vendor_cb.p_scan_pf_cback = NULL; 148 btm_ble_vendor_cb.op_type = 0; 149 (* p_cmpl_cback)(op, subcode, status); 150 } 151} 152/******************************************************************************* 153** adv payload filtering functions 154*******************************************************************************/ 155/******************************************************************************* 156** 157** Function btm_ble_find_addr_filter_counter 158** 159** Description find the per bd address ADV payload filter counter by BD_ADDR. 160** 161** Returns pointer to the counter if found; NULL otherwise. 162** 163*******************************************************************************/ 164tBTM_BLE_PF_COUNT * btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda) 165{ 166 UINT8 i; 167 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1]; 168 169 if (p_le_bda == NULL) 170 return &btm_ble_vendor_cb.addr_filter_count[0]; 171 172 for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++) 173 { 174 if (p_addr_filter->in_use && 175 memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) 176 { 177 return p_addr_filter; 178 } 179 } 180 return NULL; 181} 182 183/******************************************************************************* 184** 185** Function btm_ble_alloc_addr_filter_counter 186** 187** Description allocate the per device adv payload filter counter. 188** 189** Returns pointer to the counter if allocation succeed; NULL otherwise. 190** 191*******************************************************************************/ 192tBTM_BLE_PF_COUNT * btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr) 193{ 194 UINT8 i; 195 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1]; 196 197 for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++) 198 { 199 if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) 200 { 201 memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN); 202 p_addr_filter->in_use = TRUE; 203 return p_addr_filter; 204 } 205 } 206 return NULL; 207} 208/******************************************************************************* 209** 210** Function btm_ble_dealloc_addr_filter_counter 211** 212** Description de-allocate the per device adv payload filter counter. 213** 214** Returns TRUE if deallocation succeed; FALSE otherwise. 215** 216*******************************************************************************/ 217BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type) 218{ 219 UINT8 i; 220 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1]; 221 BOOLEAN found = FALSE; 222 223 if (filter_type == BTM_BLE_PF_TYPE_ALL && p_bd_addr == NULL) 224 memset(&btm_ble_vendor_cb.addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT)); 225 226 for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++) 227 { 228 if ((p_addr_filter->in_use) && 229 (p_bd_addr == NULL || 230 (p_bd_addr != NULL && memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0))) 231 { 232 found = TRUE; 233 memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT)); 234 235 if (p_bd_addr != NULL) break; 236 } 237 } 238 return found; 239} 240/******************************************************************************* 241** 242** Function btm_ble_cs_update_pf_counter 243** 244** Description this function is to update the adv data payload filter counter 245** 246** Returns current number of the counter; BTM_BLE_INVALID_COUNTER if 247** counter update failed. 248** 249*******************************************************************************/ 250UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, 251 UINT8 cond_type, 252 tBLE_BD_ADDR *p_bd_addr, 253 UINT8 num_available) 254{ 255 tBTM_BLE_PF_COUNT *p_addr_filter = NULL; 256 UINT8 *p_counter = NULL; 257 UINT32 *p_feat_mask = NULL; 258 259 260 if (cond_type > BTM_BLE_PF_TYPE_ALL) 261 { 262 BTM_TRACE_ERROR1("unknown PF filter condition type %d", cond_type); 263 return BTM_BLE_INVALID_COUNTER; 264 } 265 /* for these three types of filter, always generic */ 266 if (cond_type == BTM_BLE_PF_ADDR_FILTER || 267 cond_type == BTM_BLE_PF_MANU_DATA || 268 cond_type == BTM_BLE_PF_LOCAL_NAME || 269 cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN) 270 p_bd_addr = NULL; 271 272 if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL && 273 action == BTM_BLE_SCAN_COND_ADD) 274 { 275 p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda); 276 } 277 278 if (p_addr_filter != NULL) 279 { 280 /* all filter just cleared */ 281 if ((cond_type == BTM_BLE_PF_TYPE_ALL && action == BTM_BLE_SCAN_COND_CLEAR) || 282 /* or bd address filter been deleted */ 283 (cond_type == BTM_BLE_PF_ADDR_FILTER && 284 (action == BTM_BLE_SCAN_COND_DELETE || action == BTM_BLE_SCAN_COND_CLEAR))) 285 { 286 btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type); 287 } 288 /* if not feature selection, update new addition/reduction of the filter counter */ 289 else if (cond_type != BTM_BLE_PF_TYPE_ALL) 290 { 291 p_counter = p_addr_filter->pf_counter; 292 p_feat_mask = &p_addr_filter->feat_mask; 293 294 p_counter[cond_type] = btm_ble_cs_filter_max[cond_type] - num_available; 295 296 BTM_TRACE_DEBUG1("current filter counter number = %d", p_counter[cond_type]); 297 298 /* update corresponding feature mask */ 299 if (p_counter[cond_type] > 0) 300 *p_feat_mask |= (BTM_BLE_PF_BIT_TO_MASK(cond_type)); 301 else 302 *p_feat_mask &= ~(BTM_BLE_PF_BIT_TO_MASK(cond_type)); 303 304 return p_counter[cond_type]; 305 } 306 } 307 else 308 { 309 BTM_TRACE_ERROR0("no matching filter counter found"); 310 } 311 /* no matching filter located and updated */ 312 return BTM_BLE_INVALID_COUNTER; 313} 314/******************************************************************************* 315** 316** Function btm_ble_update_pf_manu_data 317** 318** Description this function update(add,delete or clear) the adv manufacturer 319** data filtering condition. 320** 321** 322** Returns BTM_SUCCESS if sucessful, 323** BTM_ILLEGAL_VALUE if paramter is not valid. 324** 325*******************************************************************************/ 326tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action, 327 tBTM_BLE_PF_COND_PARAM *p_data, 328 tBTM_BLE_PF_COND_TYPE cond_type) 329{ 330 tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data; 331 tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data; 332 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH], 333 *p = param, 334 len = BTM_BLE_META_HDR_LENGTH; 335 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 336 337 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH); 338 339 if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN) 340 { 341 UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA); 342 } 343 else 344 { 345 UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA); 346 } 347 UINT8_TO_STREAM(p, action); 348 349 if (action == BTM_BLE_SCAN_COND_ADD || 350 action == BTM_BLE_SCAN_COND_DELETE) 351 { 352 if (p_manu_data == NULL) 353 return st; 354 if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN) 355 { 356 if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) 357 p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); 358 359 UINT16_TO_STREAM(p, p_srvc_data->uuid); 360 ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len); 361 len += (p_srvc_data->data_len + 2); 362 } 363 else 364 { 365 if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) 366 p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); 367 368 UINT16_TO_STREAM(p, p_manu_data->company_id); 369 ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len); 370 len += (p_manu_data->data_len + 2); 371 372 if (p_manu_data->company_id_mask != 0) 373 { 374 UINT16_TO_STREAM (p, p_manu_data->company_id_mask); 375 } 376 else 377 { 378 memset(p, 0xff, 2); 379 p += 2; 380 } 381 if (p_manu_data->p_pattern_mask != NULL) 382 { 383 ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len); 384 } 385 else 386 memset(p, 0xff, p_manu_data->data_len); 387 len += (p_manu_data->data_len + 2); 388 } 389 } 390 391 /* send manufacturer*/ 392 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 393 len, 394 param, 395 btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 396 { 397 memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 398 } 399 else 400 { 401 BTM_TRACE_ERROR0("manufacturer data PF filter update failed"); 402 } 403 404 return st; 405} 406/******************************************************************************* 407** 408** Function btm_ble_update_pf_local_name 409** 410** Description this function update(add,delete or clear) the adv lcoal name 411** filtering condition. 412** 413** 414** Returns BTM_SUCCESS if sucessful, 415** BTM_ILLEGAL_VALUE if paramter is not valid. 416** 417*******************************************************************************/ 418tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action, 419 tBTM_BLE_PF_COND_PARAM *p_cond) 420{ 421 tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name; 422 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH], 423 *p = param, 424 len = BTM_BLE_META_HDR_LENGTH; 425 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 426 427 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH); 428 429 UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME); 430 UINT8_TO_STREAM(p, action); 431 432 if (action == BTM_BLE_SCAN_COND_ADD || 433 action == BTM_BLE_SCAN_COND_DELETE) 434 { 435 if (p_local_name == NULL) 436 return st; 437 438 if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX) 439 p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX; 440 441 ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len); 442 len += p_local_name->data_len; 443 } 444 /* send local name filter */ 445 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 446 len, 447 param, 448 btm_ble_vendor_scan_pf_cmpl_cback)) 449 != BTM_NO_RESOURCES) 450 { 451 memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 452 } 453 else 454 { 455 BTM_TRACE_ERROR0("Local Name PF filter update failed"); 456 } 457 458 return st; 459} 460/******************************************************************************* 461** 462** Function btm_ble_update_addr_filter 463** 464** Description this function update(add,delete or clear) the address filter of adv. 465** 466** 467** Returns BTM_SUCCESS if sucessful, 468** BTM_ILLEGAL_VALUE if paramter is not valid. 469** 470*******************************************************************************/ 471tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action, 472 tBTM_BLE_PF_COND_PARAM *p_cond) 473{ 474 UINT8 param[BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH], 475 * p= param; 476 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 477 tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr; 478 479 memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH); 480 481 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); 482 UINT8_TO_STREAM(p, action); 483 484 if (action == BTM_BLE_SCAN_COND_ADD || 485 action == BTM_BLE_SCAN_COND_DELETE) 486 { 487 if (p_addr == NULL) 488 return st; 489 490 BDADDR_TO_STREAM(p, p_addr->bda); 491 UINT8_TO_STREAM(p, p_addr->type); 492 } 493 /* send address filter */ 494 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 495 (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), 496 param, 497 btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 498 { 499 memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 500 } 501 else 502 { 503 BTM_TRACE_ERROR0("Broadcaster Address Filter Update failed"); 504 } 505 return st; 506} 507/******************************************************************************* 508** 509** Function btm_ble_update_uuid_filter 510** 511** Description this function update(add,delete or clear) service UUID filter. 512** 513** 514** Returns BTM_SUCCESS if sucessful, 515** BTM_ILLEGAL_VALUE if paramter is not valid. 516** 517*******************************************************************************/ 518tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, 519 tBTM_BLE_PF_COND_TYPE filter_type, 520 tBTM_BLE_PF_COND_PARAM *p_cond) 521{ 522 UINT8 param[BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH], 523 * p= param, 524 len = BTM_BLE_META_HDR_LENGTH + 7; 525 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 526 tBTM_BLE_PF_UUID_COND *p_uuid_cond; 527 UINT8 evt_type; 528 529 memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH); 530 531 if (filter_type == BTM_BLE_PF_SRVC_UUID) 532 { 533 evt_type = BTM_BLE_META_PF_UUID; 534 p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL; 535 } 536 else 537 { 538 evt_type = BTM_BLE_META_PF_SOL_UUID; 539 p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL; 540 } 541 542 if (p_uuid_cond == NULL && action != BTM_BLE_SCAN_COND_CLEAR) 543 { 544 BTM_TRACE_ERROR0("Illegal param for add/delete UUID filter"); 545 return st; 546 } 547 548 /* need to add address fitler first, if adding per bda UUID filter without address filter */ 549 if (action == BTM_BLE_SCAN_COND_ADD && 550 p_uuid_cond->p_target_addr && 551 btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL) 552 { 553 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); 554 UINT8_TO_STREAM(p, action); 555 556 BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda); 557 UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type); 558 559 /* send address filter */ 560 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 561 (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), 562 param, 563 btm_ble_vendor_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES) 564 { 565 BTM_TRACE_ERROR0("Update Address filter into controller failed."); 566 return st; 567 } 568 } 569 570 p= param; 571 UINT8_TO_STREAM(p, evt_type); 572 UINT8_TO_STREAM(p, action); 573 574 /* per BD ADDR UUID filter */ 575 if (p_uuid_cond && p_uuid_cond->p_target_addr) 576 { 577 BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda); 578 UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type); 579 } 580 else /* generic UUID filter */ 581 { 582 BDADDR_TO_STREAM(p, na_bda); 583 UINT8_TO_STREAM(p, 0x02); 584 } 585 586 if (action == BTM_BLE_SCAN_COND_ADD || 587 action == BTM_BLE_SCAN_COND_DELETE) 588 { 589 UINT8_TO_STREAM(p, p_uuid_cond->cond_logic); 590 len ++; 591 592 if (p_uuid_cond->uuid.len == LEN_UUID_16) 593 { 594 UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16); 595 len += LEN_UUID_16; 596 } 597 else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */ 598 { 599 UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32); 600 len += LEN_UUID_32; 601 } 602 else if (p_uuid_cond->uuid.len == LEN_UUID_128) 603 { 604 ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128); 605 len += LEN_UUID_128; 606 } 607 else 608 { 609 BTM_TRACE_ERROR1("illegal UUID length: %d", p_uuid_cond->uuid.len); 610 return BTM_ILLEGAL_VALUE; 611 } 612#if !(defined VENDOR_ADV_PCF_LEGACY && VENDOR_ADV_PCF_LEGACY == TRUE) 613 if (p_uuid_cond->p_uuid_mask != NULL) 614 { 615 if (p_uuid_cond->uuid.len == LEN_UUID_16) 616 { 617 UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask); 618 len += LEN_UUID_16; 619 } 620 else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */ 621 { 622 UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask); 623 len += LEN_UUID_32; 624 } 625 else if (p_uuid_cond->uuid.len == LEN_UUID_128) 626 { 627 ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128); 628 len += LEN_UUID_128; 629 } 630 } 631 else 632 { 633 memset(p, 0xff, p_uuid_cond->uuid.len); 634 len += p_uuid_cond->uuid.len; 635 } 636#endif 637 } 638 639 /* send UUID filter update */ 640 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 641 len, 642 param, 643 btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) 644 { 645 if (p_uuid_cond && p_uuid_cond->p_target_addr) 646 memcpy(&btm_ble_vendor_cb.cur_filter_target, p_uuid_cond->p_target_addr, sizeof(tBLE_BD_ADDR)); 647 else 648 memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 649 } 650 else 651 { 652 BTM_TRACE_ERROR0("UUID filter udpating failed"); 653 } 654 655 return st; 656} 657/******************************************************************************* 658** 659** Function btm_ble_update_srvc_data_change 660** 661** Description this function update(add/remove) service data change filter. 662** 663** 664** Returns BTM_SUCCESS if sucessful, 665** BTM_ILLEGAL_VALUE if paramter is not valid. 666** 667*******************************************************************************/ 668tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action, 669 tBTM_BLE_PF_COND_PARAM *p_cond) 670{ 671 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 672 tBLE_BD_ADDR *p_bd_addr = p_cond ? &p_cond->target_addr : NULL; 673 UINT8 num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1; 674 675 if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail) 676 != BTM_BLE_INVALID_COUNTER) 677 st = BTM_SUCCESS; 678 679 return st; 680} 681 682/******************************************************************************* 683** 684** Function btm_ble_clear_scan_pf_filter 685** 686** Description clear all adv payload filter by de-select all the adv pf feature bits 687** 688** 689** Returns BTM_SUCCESS if sucessful, 690** BTM_ILLEGAL_VALUE if paramter is not valid. 691** 692*******************************************************************************/ 693tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action, 694 tBTM_BLE_PF_COND_PARAM *p_cond) 695{ 696 tBLE_BD_ADDR *p_target = (p_cond == NULL)? NULL : &p_cond->target_addr; 697 tBTM_BLE_PF_COUNT *p_bda_filter; 698 tBTM_STATUS st = BTM_WRONG_MODE; 699 UINT8 param[20], *p; 700 701 if (action != BTM_BLE_SCAN_COND_CLEAR) 702 { 703 BTM_TRACE_ERROR1("unable to perform action:%d for generic adv filter type", action); 704 return BTM_ILLEGAL_VALUE; 705 } 706 707 p = param; 708 memset(param, 0, 20); 709 710 p_bda_filter = btm_ble_find_addr_filter_counter(p_target); 711 712 if (p_bda_filter == NULL || 713 /* not a generic filter, and feature selection is empty */ 714 (p_target != NULL && p_bda_filter && p_bda_filter->feat_mask == 0)) 715 { 716 BTM_TRACE_ERROR0("Error: Can not clear filter, No PF filter has been configured!"); 717 return st; 718 } 719 720 /* clear the general filter entry */ 721 if (p_target == NULL) 722 { 723 /* clear manufactuer data filter */ 724 btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA); 725 /* clear local name filter */ 726 btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, NULL); 727 /* update the counter for service data */ 728 btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, NULL); 729 /* clear UUID filter */ 730 btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_PF_SRVC_UUID, NULL); 731 btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_META_PF_SOL_UUID, NULL); 732 /* clear service data filter */ 733 btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA); 734 } 735 736 /* select feature based on control block settings */ 737 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 738 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR); 739 740 if (p_target != NULL) 741 { 742 BDADDR_TO_STREAM(p, p_target->bda); 743 UINT8_TO_STREAM(p, p_target->type); 744 } 745 else 746 { 747 BDADDR_TO_STREAM(p, na_bda); 748 UINT8_TO_STREAM(p, 0x02); 749 } 750 751 /* set PCF selection */ 752 UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE); 753 /* set logic condition as OR as default */ 754 UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR); 755 756 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 757 (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN), 758 param, 759 btm_ble_vendor_scan_pf_cmpl_cback)) 760 != BTM_NO_RESOURCES) 761 { 762 if (p_bda_filter) 763 p_bda_filter->feat_mask = BTM_BLE_PF_SELECT_NONE; 764 765 if (p_target) 766 memcpy(&btm_ble_vendor_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR)); 767 else 768 memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); 769 } 770 771 return st; 772} 773/******************************************************************************* 774** 775** Function BTM_BleEnableFilterCondition 776** 777** Description This function is called to enable the adv data payload filter 778** condition. 779** 780** Parameters p_target: enabble the filter condition on a target device; if NULL 781** enable the generic scan condition. 782** enable: enable or disable the filter condition 783** 784** Returns void 785** 786*******************************************************************************/ 787tBTM_STATUS BTM_BleEnableFilterCondition(BOOLEAN enable, tBLE_BD_ADDR *p_target, 788 tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback) 789{ 790 UINT8 param[20], *p; 791 tBTM_STATUS st = BTM_WRONG_MODE; 792 tBTM_BLE_PF_COUNT *p_bda_filter; 793 794 p = param; 795 memset(param, 0, 20); 796 797 if (btm_ble_vendor_cb.p_scan_pf_cback) 798 { 799 BTM_TRACE_ERROR0("ADV PF Filter activity busy"); 800 return BTM_BUSY; 801 } 802 803 if (enable) 804 { 805 p_bda_filter = btm_ble_find_addr_filter_counter(p_target); 806 807 if (p_bda_filter == NULL || 808 (p_bda_filter && p_bda_filter->feat_mask == BTM_BLE_PF_SELECT_NONE)) 809 { 810 BTM_TRACE_ERROR0("No PF filter has been configured!"); 811 return st; 812 } 813 814 /* select feature based on control block settings */ 815 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); 816 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD); 817 818 if (p_target != NULL) 819 { 820 BDADDR_TO_STREAM(p, p_target->bda); 821 UINT8_TO_STREAM(p, p_target->type); 822 } 823 else 824 { 825 BDADDR_TO_STREAM(p, na_bda); 826 UINT8_TO_STREAM(p, 0x02); 827 } 828 829 /* set PCF selection */ 830 UINT32_TO_STREAM(p, p_bda_filter->feat_mask); 831 /* set logic condition as OR as default */ 832 UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR); 833 834 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 835 (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN), 836 param, 837 btm_ble_vendor_scan_pf_cmpl_cback)) 838 == BTM_NO_RESOURCES) 839 { 840 return st; 841 } 842 843 /* enable the content filter in controller */ 844 p = param; 845 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE); 846 /* enable adv data payload filtering */ 847 UINT8_TO_STREAM(p, enable); 848 } 849 else 850 { 851 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE); 852 /* disable adv data payload filtering */ 853 UINT8_TO_STREAM(p, enable); 854 } 855 856 if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC, 857 BTM_BLE_PCF_ENABLE_LEN, 858 param, 859 btm_ble_vendor_scan_pf_cmpl_cback)) 860 == BTM_CMD_STARTED) 861 { 862 btm_ble_vendor_cb.op_type = BTM_BLE_SET_SCAN_PF_OPCODE(BTM_BLE_META_PF_ENABLE, BTM_BLE_PF_ENABLE); 863 btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback; 864 } 865 866 return st; 867} 868/******************************************************************************* 869** 870** Function BTM_BleCfgFilterCondition 871** 872** Description This function is called to configure the adv data payload filter 873** condition. 874** 875** Parameters action: to read/write/clear 876** cond_type: filter condition type. 877** p_cond: filter condition paramter 878** 879** Returns void 880** 881*******************************************************************************/ 882tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action, 883 tBTM_BLE_PF_COND_TYPE cond_type, 884 tBTM_BLE_PF_COND_PARAM *p_cond, 885 tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback) 886{ 887 tBTM_STATUS st = BTM_ILLEGAL_VALUE; 888 889 if (btm_ble_vendor_cb.p_scan_pf_cback != NULL) 890 return BTM_BUSY; 891 892 switch (cond_type) 893 { 894 case BTM_BLE_PF_SRVC_DATA_PATTERN: 895 /* write manufacture data filter */ 896 case BTM_BLE_PF_MANU_DATA: 897 st = btm_ble_update_pf_manu_data(action, p_cond, cond_type); 898 break; 899 900 /* write local name filter */ 901 case BTM_BLE_PF_LOCAL_NAME: 902 st = btm_ble_update_pf_local_name(action, p_cond); 903 break; 904 905 /* filter on advertiser address */ 906 case BTM_BLE_PF_ADDR_FILTER: 907 st = btm_ble_update_addr_filter(action, p_cond); 908 break; 909 910 /* filter on service/solicitated UUID */ 911 case BTM_BLE_PF_SRVC_UUID: 912 case BTM_BLE_PF_SRVC_SOL_UUID: 913 st = btm_ble_update_uuid_filter(action, cond_type, p_cond); 914 break; 915 916 case BTM_BLE_PF_SRVC_DATA: 917 st = btm_ble_update_srvc_data_change(action, p_cond); 918 break; 919 920 case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */ 921 st = btm_ble_clear_scan_pf_filter(action, p_cond); 922 break; 923 924 default: 925 BTM_TRACE_WARNING1("condition type [%d] not supported currently.", cond_type); 926 break; 927 } 928 if (st == BTM_CMD_STARTED 929 /* no vsc needed for service data change */ 930 && cond_type != BTM_BLE_PF_SRVC_DATA) 931 { 932 btm_ble_vendor_cb.op_type = BTM_BLE_SET_SCAN_PF_OPCODE(cond_type, BTM_BLE_PF_CONFIG); 933 btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback; 934 } 935 936 return st; 937} 938 939 940/******************************************************************************* 941** 942** Function btm_ble_vendor_init 943** 944** Description Initialize customer specific feature information in host stack 945** 946** Parameters 947** 948** Returns status 949** 950*******************************************************************************/ 951void btm_ble_vendor_init(void) 952{ 953 memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB)); 954 955 if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) 956 return; 957} 958 959#endif 960 961 962