1 /****************************************************************************** 2 * 3 * Copyright (C) 1999-2012 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 * This file contains functions for BLE whitelist operation. 22 * 23 ******************************************************************************/ 24 25 #include <string.h> 26 27 #include "bt_types.h" 28 #include "btu.h" 29 #include "btm_int.h" 30 #include "l2c_int.h" 31 #include "hcimsgs.h" 32 33 34 #ifndef BTM_BLE_SCAN_PARAM_TOUT 35 #define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */ 36 #endif 37 38 #if (BLE_INCLUDED == TRUE) 39 40 static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state); 41 static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state); 42 43 /******************************************************************************* 44 ** 45 ** Function btm_update_scanner_filter_policy 46 ** 47 ** Description This function update the filter policy of scnner or advertiser. 48 *******************************************************************************/ 49 void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) 50 { 51 tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; 52 BTM_TRACE_EVENT0 ("btm_update_scanner_filter_policy"); 53 54 p_inq->sfp = scan_policy; 55 p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type; 56 57 btsnd_hcic_ble_set_scan_params (p_inq->scan_type, 58 (UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval), 59 (UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window), 60 BLE_ADDR_PUBLIC, 61 scan_policy); 62 } 63 /******************************************************************************* 64 ** 65 ** Function btm_update_dev_to_white_list 66 ** 67 ** Description This function adds a device into white list. 68 *******************************************************************************/ 69 BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr) 70 { 71 /* look up the sec device record, and find the address */ 72 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 73 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr); 74 BD_ADDR dummy_bda = {0}; 75 BOOLEAN started = FALSE; 76 UINT8 wl_state = p_cb->wl_state; 77 tBT_DEVICE_TYPE dev_type; 78 tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC; 79 80 if ((to_add && p_cb->num_empty_filter == 0) || 81 (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries)) 82 { 83 BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d", p_cb->num_empty_filter); 84 return started; 85 } 86 87 btm_suspend_wl_activity(wl_state); 88 89 if (p_dev_rec != NULL && 90 p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) 91 { 92 93 if (to_add) 94 { 95 if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr)) 96 { 97 started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr); 98 } 99 if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 && 100 memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0) 101 { 102 started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr); 103 } 104 } 105 else 106 { 107 if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr)) 108 { 109 started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr); 110 } 111 if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0) 112 { 113 started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr); 114 } 115 } 116 } /* if not a known device, shall we add it? */ 117 else 118 { 119 BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type); 120 if (to_add) 121 started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr); 122 else 123 started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr); 124 } 125 126 btm_resume_wl_activity(wl_state); 127 128 return started; 129 } 130 /******************************************************************************* 131 ** 132 ** Function btm_ble_clear_white_list 133 ** 134 ** Description This function clears the white list. 135 *******************************************************************************/ 136 void btm_ble_clear_white_list (void) 137 { 138 BTM_TRACE_EVENT0 ("btm_ble_clear_white_list"); 139 btsnd_hcic_ble_clear_white_list(); 140 } 141 142 /******************************************************************************* 143 ** 144 ** Function btm_ble_clear_white_list_complete 145 ** 146 ** Description This function clears the white list complete. 147 *******************************************************************************/ 148 void btm_ble_clear_white_list_complete(UINT8 *p_data, UINT16 evt_len) 149 { 150 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 151 UINT8 status; 152 BTM_TRACE_EVENT0 ("btm_ble_clear_white_list_complete"); 153 STREAM_TO_UINT8 (status, p_data); 154 155 if (status == HCI_SUCCESS) 156 p_cb->num_empty_filter = p_cb->max_filter_entries; 157 158 } 159 /******************************************************************************* 160 ** 161 ** Function btm_ble_add_2_white_list_complete 162 ** 163 ** Description This function read the current white list size. 164 *******************************************************************************/ 165 void btm_ble_add_2_white_list_complete(UINT8 status) 166 { 167 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 168 BTM_TRACE_EVENT0 ("btm_ble_add_2_white_list_complete"); 169 170 if (status == HCI_SUCCESS) 171 { 172 p_cb->num_empty_filter --; 173 } 174 } 175 /******************************************************************************* 176 ** 177 ** Function btm_ble_add_2_white_list_complete 178 ** 179 ** Description This function read the current white list size. 180 *******************************************************************************/ 181 void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len) 182 { 183 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 184 BTM_TRACE_EVENT0 ("btm_ble_remove_from_white_list_complete"); 185 if (*p == HCI_SUCCESS) 186 { 187 p_cb->num_empty_filter ++; 188 } 189 } 190 /******************************************************************************* 191 ** 192 ** Function btm_ble_count_unconn_dev_in_whitelist 193 ** 194 ** Description This function find the number of un-connected background device 195 *******************************************************************************/ 196 UINT8 btm_ble_count_unconn_dev_in_whitelist(void) 197 { 198 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 199 UINT8 i, count = 0; 200 201 for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++) 202 { 203 if (p_cb->bg_dev_list[i].in_use && 204 !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr)) 205 { 206 count ++; 207 } 208 } 209 return count; 210 211 } 212 /******************************************************************************* 213 ** 214 ** Function btm_update_bg_conn_list 215 ** 216 ** Description This function update the local background connection device list. 217 *******************************************************************************/ 218 BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag) 219 { 220 UINT8 white_list_type = *p_attr_tag; 221 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 222 tBTM_LE_BG_CONN_DEV *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur; 223 UINT8 i, j; 224 BOOLEAN ret = FALSE; 225 226 BTM_TRACE_EVENT0 ("btm_update_bg_conn_list"); 227 228 if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0))) 229 { 230 BTM_TRACE_DEBUG1("num_empty_filter = %d", p_cb->num_empty_filter); 231 return ret; 232 } 233 234 for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++) 235 { 236 if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) 237 { 238 if (to_add) 239 p_bg_dev->attr |= white_list_type; 240 else 241 p_bg_dev->attr &= ~white_list_type; 242 243 if (p_bg_dev->attr == 0) 244 { 245 memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV)); 246 p_cb->bg_dev_num --; 247 p_cur = p_bg_dev; 248 p_next = p_bg_dev + 1; 249 for (j = i + 1 ;j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use ; j ++, p_cur ++, p_next ++ ) 250 memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV)); 251 } 252 ret = TRUE; 253 break; 254 } 255 else if (!p_bg_dev->in_use && to_add) 256 { 257 BTM_TRACE_DEBUG0("add new WL entry in bg_dev_list"); 258 259 memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN); 260 p_bg_dev->in_use = TRUE; 261 p_bg_dev->attr |= white_list_type; 262 p_cb->bg_dev_num ++; 263 264 ret = TRUE; 265 break; 266 } 267 } 268 269 if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM) 270 *p_attr_tag = p_bg_dev->attr; 271 272 return ret; 273 } 274 275 /******************************************************************************* 276 ** 277 ** Function btm_ble_start_auto_conn 278 ** 279 ** Description This function is to start/stop auto connection procedure. 280 ** 281 ** Parameters start: TRUE to start; FALSE to stop. 282 ** 283 ** Returns void 284 ** 285 *******************************************************************************/ 286 BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) 287 { 288 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 289 BD_ADDR dummy_bda = {0}; 290 BOOLEAN exec = TRUE; 291 UINT8 own_addr_type = BLE_ADDR_PUBLIC; 292 UINT16 scan_int, scan_win; 293 294 if (start) 295 { 296 if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0) 297 { 298 299 scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int; 300 scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win; 301 302 if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */ 303 scan_win, /* UINT16 scan_win */ 304 0x01, /* UINT8 white_list */ 305 BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */ 306 dummy_bda, /* BD_ADDR bda_peer */ 307 own_addr_type, /* UINT8 addr_type_own, not allow random address for central */ 308 BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */ 309 BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */ 310 BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */ 311 BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */ 312 0, /* UINT16 min_len */ 313 0)) /* UINT16 max_len */ 314 { 315 /* start auto connection failed */ 316 exec = FALSE; 317 } 318 else 319 { 320 p_cb->conn_state = BLE_BG_CONN; 321 322 } 323 } 324 else 325 { 326 exec = FALSE; 327 } 328 } 329 else 330 { 331 if (p_cb->conn_state == BLE_BG_CONN) 332 { 333 btsnd_hcic_ble_create_conn_cancel(); 334 p_cb->conn_state = BLE_CONN_IDLE; 335 336 } 337 else 338 { 339 #if 0 340 BTM_TRACE_ERROR1("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state); 341 exec = FALSE; 342 #endif 343 } 344 } 345 return exec; 346 } 347 348 /******************************************************************************* 349 ** 350 ** Function btm_ble_start_select_conn 351 ** 352 ** Description This function is to start/stop selective connection procedure. 353 ** 354 ** Parameters start: TRUE to start; FALSE to stop. 355 ** p_select_cback: callback function to return application 356 ** selection. 357 ** 358 ** Returns BOOLEAN: selective connectino procedure is started. 359 ** 360 *******************************************************************************/ 361 BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_cback) 362 { 363 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 364 UINT16 scan_int, scan_win; 365 366 BTM_TRACE_EVENT0 ("btm_ble_start_select_conn"); 367 368 scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int; 369 scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win; 370 371 if (start) 372 { 373 if (btm_cb.btm_inq_vars.inq_active == BTM_INQUIRY_INACTIVE) 374 { 375 if (p_select_cback != NULL) 376 btm_cb.ble_ctr_cb.p_select_cback = p_select_cback; 377 378 btm_update_scanner_filter_policy(SP_ADV_WL); 379 btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS; 380 381 if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS, /* use passive scan by default */ 382 scan_int, /* scan interval */ 383 scan_win, /* scan window */ 384 BLE_ADDR_PUBLIC, /* own device, DUMO always use public */ 385 SP_ADV_WL) /* process advertising packets only from devices in the White List */ 386 ) 387 return FALSE; 388 389 if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE 390 ) 391 { 392 BTM_TRACE_ERROR0("peripheral device cannot initiate a selective connection"); 393 return FALSE; 394 } 395 else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 ) 396 { 397 398 if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */ 399 return FALSE; 400 401 /* mark up inquiry status flag */ 402 btm_cb.btm_inq_vars.inq_active |= BTM_LE_SELECT_CONN_ACTIVE; 403 p_cb->inq_var.proc_mode = BTM_BLE_SELECT_SCAN; 404 p_cb->conn_state = BLE_BG_CONN; 405 } 406 } 407 else 408 { 409 BTM_TRACE_ERROR0("scan active, can not start selective connection procedure"); 410 return FALSE; 411 } 412 } 413 else /* disable selective connection mode */ 414 { 415 btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_SELECT_CONN_ACTIVE; 416 btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE; 417 418 btm_update_scanner_filter_policy(SP_ADV_ALL); 419 /* stop scanning */ 420 if (p_cb->bg_dev_num > 0) 421 { 422 if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */ 423 return FALSE; 424 } 425 } 426 return TRUE; 427 } 428 /******************************************************************************* 429 ** 430 ** Function btm_ble_initiate_select_conn 431 ** 432 ** Description This function is to start/stop selective connection procedure. 433 ** 434 ** Parameters start: TRUE to start; FALSE to stop. 435 ** p_select_cback: callback function to return application 436 ** selection. 437 ** 438 ** Returns BOOLEAN: selective connectino procedure is started. 439 ** 440 *******************************************************************************/ 441 void btm_ble_initiate_select_conn(BD_ADDR bda) 442 { 443 BTM_TRACE_EVENT0 ("btm_ble_initiate_select_conn"); 444 445 /* use direct connection procedure to initiate connection */ 446 if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda)) 447 { 448 BTM_TRACE_ERROR0("btm_ble_initiate_select_conn failed"); 449 } 450 } 451 /******************************************************************************* 452 ** 453 ** Function btm_ble_suspend_bg_conn 454 ** 455 ** Description This function is to suspend an active background connection 456 ** procedure. 457 ** 458 ** Parameters none. 459 ** 460 ** Returns none. 461 ** 462 *******************************************************************************/ 463 void btm_ble_suspend_bg_conn(void) 464 { 465 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 466 BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_conn"); 467 468 if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) 469 { 470 btm_ble_start_auto_conn(FALSE); 471 } 472 else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE) 473 { 474 btm_ble_start_select_conn(FALSE, NULL); 475 } 476 } 477 /******************************************************************************* 478 ** 479 ** Function btm_suspend_wl_activity 480 ** 481 ** Description This function is to suspend white list related activity 482 ** 483 ** Returns none. 484 ** 485 *******************************************************************************/ 486 static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) 487 { 488 if (wl_state & BTM_BLE_WL_INIT) 489 { 490 btm_ble_start_auto_conn(FALSE); 491 } 492 if (wl_state & BTM_BLE_WL_SCAN) 493 { 494 btm_ble_start_select_conn(FALSE, NULL); 495 } 496 if (wl_state & BTM_BLE_WL_ADV) 497 { 498 btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE); 499 } 500 501 } 502 /******************************************************************************* 503 ** 504 ** Function btm_resume_wl_activity 505 ** 506 ** Description This function is to resume white list related activity 507 ** 508 ** Returns none. 509 ** 510 *******************************************************************************/ 511 static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) 512 { 513 btm_ble_resume_bg_conn(); 514 515 if (wl_state & BTM_BLE_WL_ADV) 516 { 517 btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE); 518 } 519 520 } 521 /******************************************************************************* 522 ** 523 ** Function btm_ble_resume_bg_conn 524 ** 525 ** Description This function is to resume a background auto connection 526 ** procedure. 527 ** 528 ** Parameters none. 529 ** 530 ** Returns none. 531 ** 532 *******************************************************************************/ 533 BOOLEAN btm_ble_resume_bg_conn(void) 534 { 535 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 536 BOOLEAN ret = FALSE; 537 538 if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE) 539 { 540 if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) 541 ret = btm_ble_start_auto_conn(TRUE); 542 543 if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE) 544 ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback); 545 } 546 547 return ret; 548 } 549 /******************************************************************************* 550 ** 551 ** Function btm_ble_get_conn_st 552 ** 553 ** Description This function get BLE connection state 554 ** 555 ** Returns connection state 556 ** 557 *******************************************************************************/ 558 tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) 559 { 560 return btm_cb.ble_ctr_cb.conn_state; 561 } 562 /******************************************************************************* 563 ** 564 ** Function btm_ble_set_conn_st 565 ** 566 ** Description This function set BLE connection state 567 ** 568 ** Returns None. 569 ** 570 *******************************************************************************/ 571 void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) 572 { 573 btm_cb.ble_ctr_cb.conn_state = new_st; 574 } 575 576 /******************************************************************************* 577 ** 578 ** Function btm_ble_enqueue_direct_conn_req 579 ** 580 ** Description This function enqueue the direct connection request 581 ** 582 ** Returns None. 583 ** 584 *******************************************************************************/ 585 void btm_ble_enqueue_direct_conn_req(void *p_param) 586 { 587 tBTM_BLE_CONN_REQ *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ)); 588 589 p->p_param = p_param; 590 591 GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p); 592 } 593 /******************************************************************************* 594 ** 595 ** Function btm_send_pending_direct_conn 596 ** 597 ** Description This function send the pending direct connection request in queue 598 ** 599 ** Returns TRUE if started, FALSE otherwise 600 ** 601 *******************************************************************************/ 602 BOOLEAN btm_send_pending_direct_conn(void ) 603 { 604 tBTM_BLE_CONN_REQ *p_req; 605 BOOLEAN rt = FALSE; 606 607 if ( btm_cb.ble_ctr_cb.conn_pending_q.count ) 608 { 609 p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q); 610 611 rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param)); 612 613 GKI_freebuf((void *)p_req); 614 } 615 616 return rt; 617 } 618 #endif 619 620 621