1 /****************************************************************************** 2 * 3 * Copyright 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 <base/logging.h> 26 #include <string.h> 27 #include <unordered_map> 28 29 #include "bt_types.h" 30 #include "bt_utils.h" 31 #include "btm_int.h" 32 #include "btu.h" 33 #include "device/include/controller.h" 34 #include "hcimsgs.h" 35 #include "l2c_int.h" 36 #include "osi/include/allocator.h" 37 #include "osi/include/osi.h" 38 39 #ifndef BTM_BLE_SCAN_PARAM_TOUT 40 #define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */ 41 #endif 42 43 static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state); 44 static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state); 45 46 // Unfortunately (for now?) we have to maintain a copy of the device whitelist 47 // on the host to determine if a device is pending to be connected or not. This 48 // controls whether the host should keep trying to scan for whitelisted 49 // peripherals or not. 50 // TODO: Move all of this to controller/le/background_list or similar? 51 typedef struct background_connection_t { 52 RawAddress address; 53 uint8_t addr_type; 54 55 bool in_controller_wl; 56 uint8_t addr_type_in_wl; 57 58 bool pending_removal; 59 } background_connection_t; 60 61 struct BgConnHash { 62 bool operator()(const RawAddress& x) const { 63 const uint8_t* a = x.address; 64 return a[0] ^ (a[1] << 8) ^ (a[2] << 16) ^ (a[3] << 24) ^ a[4] ^ 65 (a[5] << 8); 66 } 67 }; 68 69 static std::unordered_map<RawAddress, background_connection_t, BgConnHash> 70 background_connections; 71 72 static void background_connection_add(uint8_t addr_type, 73 const RawAddress& address) { 74 auto map_iter = background_connections.find(address); 75 if (map_iter == background_connections.end()) { 76 background_connections[address] = 77 background_connection_t{address, addr_type, false, 0, false}; 78 } else { 79 background_connection_t* connection = &map_iter->second; 80 connection->addr_type = addr_type; 81 connection->pending_removal = false; 82 } 83 } 84 85 static void background_connection_remove(const RawAddress& address) { 86 auto map_iter = background_connections.find(address); 87 if (map_iter != background_connections.end()) { 88 if (map_iter->second.in_controller_wl) { 89 map_iter->second.pending_removal = true; 90 } else { 91 background_connections.erase(map_iter); 92 } 93 } 94 } 95 96 static void background_connections_clear() { background_connections.clear(); } 97 98 static bool background_connections_pending() { 99 for (auto& map_el : background_connections) { 100 background_connection_t* connection = &map_el.second; 101 if (connection->pending_removal) continue; 102 const bool connected = 103 BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE); 104 if (!connected) { 105 return true; 106 } 107 } 108 return false; 109 } 110 111 static int background_connections_count() { 112 int count = 0; 113 for (auto& map_el : background_connections) { 114 if (!map_el.second.pending_removal) ++count; 115 } 116 return count; 117 } 118 119 /******************************************************************************* 120 * 121 * Function btm_update_scanner_filter_policy 122 * 123 * Description This function updates the filter policy of scanner 124 ******************************************************************************/ 125 void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) { 126 tBTM_BLE_INQ_CB* p_inq = &btm_cb.ble_ctr_cb.inq_var; 127 128 uint32_t scan_interval = 129 !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval; 130 uint32_t scan_window = 131 !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window; 132 133 BTM_TRACE_EVENT("%s", __func__); 134 135 p_inq->sfp = scan_policy; 136 p_inq->scan_type = p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE 137 ? BTM_BLE_SCAN_MODE_ACTI 138 : p_inq->scan_type; 139 140 btm_send_hci_set_scan_params( 141 p_inq->scan_type, (uint16_t)scan_interval, (uint16_t)scan_window, 142 btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, scan_policy); 143 } 144 145 /******************************************************************************* 146 * 147 * Function btm_ble_bgconn_cancel_if_disconnected 148 * 149 * Description If a device has been disconnected, it must be re-added to 150 * the white list. If needed, this function cancels a pending 151 * initiate command in order to trigger restart of the initiate 152 * command which in turn updates the white list. 153 * 154 * Parameters bd_addr: updated device 155 * 156 ******************************************************************************/ 157 void btm_ble_bgconn_cancel_if_disconnected(const RawAddress& bd_addr) { 158 if (btm_cb.ble_ctr_cb.conn_state != BLE_BG_CONN) return; 159 160 auto map_it = background_connections.find(bd_addr); 161 if (map_it != background_connections.end()) { 162 background_connection_t* connection = &map_it->second; 163 if (!connection->in_controller_wl && !connection->pending_removal && 164 !BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) { 165 btm_ble_start_auto_conn(false); 166 } 167 } 168 } 169 170 /******************************************************************************* 171 * 172 * Function btm_add_dev_to_controller 173 * 174 * Description This function load the device into controller white list 175 ******************************************************************************/ 176 bool btm_add_dev_to_controller(bool to_add, const RawAddress& bd_addr) { 177 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr); 178 bool started = false; 179 180 if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) { 181 if (to_add) { 182 if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || 183 !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) { 184 background_connection_add(p_dev_rec->ble.ble_addr_type, bd_addr); 185 started = true; 186 p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT; 187 } else if (p_dev_rec->ble.static_addr != bd_addr && 188 !p_dev_rec->ble.static_addr.IsEmpty()) { 189 background_connection_add(p_dev_rec->ble.static_addr_type, 190 p_dev_rec->ble.static_addr); 191 started = true; 192 p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT; 193 } 194 } else { 195 if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || 196 !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) { 197 background_connection_remove(bd_addr); 198 started = true; 199 } 200 201 if (!p_dev_rec->ble.static_addr.IsEmpty() && 202 p_dev_rec->ble.static_addr != bd_addr) { 203 background_connection_remove(p_dev_rec->ble.static_addr); 204 started = true; 205 } 206 207 p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT; 208 } 209 } else { 210 /* not a known device, i.e. attempt to connect to device never seen before 211 */ 212 started = true; 213 if (to_add) 214 background_connection_add(BLE_ADDR_PUBLIC, bd_addr); 215 else 216 background_connection_remove(bd_addr); 217 } 218 219 return started; 220 } 221 /******************************************************************************* 222 * 223 * Function btm_execute_wl_dev_operation 224 * 225 * Description execute the pending whitelist device operation (loading or 226 * removing) 227 ******************************************************************************/ 228 bool btm_execute_wl_dev_operation(void) { 229 // handle removals first to avoid filling up controller's white list 230 for (auto map_it = background_connections.begin(); 231 map_it != background_connections.end();) { 232 background_connection_t* connection = &map_it->second; 233 if (connection->pending_removal) { 234 btsnd_hcic_ble_remove_from_white_list(connection->addr_type_in_wl, 235 connection->address); 236 map_it = background_connections.erase(map_it); 237 } else 238 ++map_it; 239 } 240 for (auto& map_el : background_connections) { 241 background_connection_t* connection = &map_el.second; 242 const bool connected = 243 BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE); 244 if (!connection->in_controller_wl && !connected) { 245 btsnd_hcic_ble_add_white_list(connection->addr_type, connection->address); 246 connection->in_controller_wl = true; 247 connection->addr_type_in_wl = connection->addr_type; 248 } else if (connection->in_controller_wl && connected) { 249 /* Bluetooth Core 4.2 as well as ESR08 disallows more than one 250 connection between two LE addresses. Not all controllers handle this 251 correctly, therefore we must make sure connected devices are not in 252 the white list when bg connection attempt is active. */ 253 btsnd_hcic_ble_remove_from_white_list(connection->addr_type_in_wl, 254 connection->address); 255 connection->in_controller_wl = false; 256 } 257 } 258 return true; 259 } 260 261 /******************************************************************************* 262 * 263 * Function btm_update_dev_to_white_list 264 * 265 * Description This function adds or removes a device into/from 266 * the white list. 267 * 268 ******************************************************************************/ 269 bool btm_update_dev_to_white_list(bool to_add, const RawAddress& bd_addr) { 270 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb; 271 272 if (to_add && 273 background_connections_count() == 274 controller_get_interface()->get_ble_white_list_size()) { 275 BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__); 276 return false; 277 } 278 279 btm_suspend_wl_activity(p_cb->wl_state); 280 btm_add_dev_to_controller(to_add, bd_addr); 281 btm_resume_wl_activity(p_cb->wl_state); 282 return true; 283 } 284 285 /******************************************************************************* 286 * 287 * Function btm_ble_clear_white_list 288 * 289 * Description This function clears the white list. 290 * 291 ******************************************************************************/ 292 void btm_ble_clear_white_list(void) { 293 BTM_TRACE_EVENT("btm_ble_clear_white_list"); 294 btsnd_hcic_ble_clear_white_list(); 295 background_connections_clear(); 296 } 297 298 /******************************************************************************* 299 * 300 * Function btm_ble_clear_white_list_complete 301 * 302 * Description Indicates white list cleared. 303 * 304 ******************************************************************************/ 305 void btm_ble_clear_white_list_complete(uint8_t* p_data, 306 UNUSED_ATTR uint16_t evt_len) { 307 uint8_t status; 308 309 STREAM_TO_UINT8(status, p_data); 310 BTM_TRACE_EVENT("%s status=%d", __func__, status); 311 } 312 313 /******************************************************************************* 314 * 315 * Function btm_ble_white_list_init 316 * 317 * Description Initialize white list size 318 * 319 ******************************************************************************/ 320 void btm_ble_white_list_init(uint8_t white_list_size) { 321 BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, white_list_size); 322 } 323 324 /******************************************************************************* 325 * 326 * Function btm_ble_add_2_white_list_complete 327 * 328 * Description White list element added 329 * 330 ******************************************************************************/ 331 void btm_ble_add_2_white_list_complete(uint8_t status) { 332 BTM_TRACE_EVENT("%s status=%d", __func__, status); 333 } 334 335 /******************************************************************************* 336 * 337 * Function btm_ble_remove_from_white_list_complete 338 * 339 * Description White list element removal complete 340 * 341 ******************************************************************************/ 342 void btm_ble_remove_from_white_list_complete(uint8_t* p, 343 UNUSED_ATTR uint16_t evt_len) { 344 BTM_TRACE_EVENT("%s status=%d", __func__, *p); 345 } 346 347 void btm_ble_create_conn_cancel_complete(uint8_t* p) { 348 uint8_t status; 349 STREAM_TO_UINT8(status, p); 350 351 if (status == HCI_ERR_COMMAND_DISALLOWED) { 352 /* This is a sign that logic around keeping connection state is broken */ 353 LOG(ERROR) 354 << "Attempt to cancel LE connection, when no connection is pending."; 355 if (btm_ble_get_conn_st() == BLE_CONN_CANCEL) { 356 btm_ble_set_conn_st(BLE_CONN_IDLE); 357 btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, nullptr, status); 358 } 359 } 360 } 361 362 void btm_send_hci_create_connection( 363 uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, 364 uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own, 365 uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency, 366 uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, 367 uint8_t initiating_phys) { 368 if (controller_get_interface()->supports_ble_extended_advertising()) { 369 EXT_CONN_PHY_CFG phy_cfg[3]; // maximum three phys 370 371 int phy_cnt = 372 std::bitset<std::numeric_limits<uint8_t>::digits>(initiating_phys) 373 .count(); 374 375 LOG_ASSERT(phy_cnt < 3) << "More than three phys provided"; 376 // TODO(jpawlowski): tune parameters for different transports 377 for (int i = 0; i < phy_cnt; i++) { 378 phy_cfg[i].scan_int = scan_int; 379 phy_cfg[i].scan_win = scan_win; 380 phy_cfg[i].conn_int_min = conn_int_min; 381 phy_cfg[i].conn_int_max = conn_int_max; 382 phy_cfg[i].conn_latency = conn_latency; 383 phy_cfg[i].sup_timeout = conn_timeout; 384 phy_cfg[i].min_ce_len = min_ce_len; 385 phy_cfg[i].max_ce_len = max_ce_len; 386 } 387 388 addr_type_peer &= ~BLE_ADDR_TYPE_ID_BIT; 389 btsnd_hcic_ble_ext_create_conn(init_filter_policy, addr_type_own, 390 addr_type_peer, bda_peer, initiating_phys, 391 phy_cfg); 392 } else { 393 btsnd_hcic_ble_create_ll_conn(scan_int, scan_win, init_filter_policy, 394 addr_type_peer, bda_peer, addr_type_own, 395 conn_int_min, conn_int_max, conn_latency, 396 conn_timeout, min_ce_len, max_ce_len); 397 } 398 } 399 400 /******************************************************************************* 401 * 402 * Function btm_ble_start_auto_conn 403 * 404 * Description This function is to start/stop auto connection procedure. 405 * 406 * Parameters start: true to start; false to stop. 407 * 408 * Returns void 409 * 410 ******************************************************************************/ 411 bool btm_ble_start_auto_conn(bool start) { 412 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb; 413 bool exec = true; 414 uint16_t scan_int; 415 uint16_t scan_win; 416 uint8_t own_addr_type = p_cb->addr_mgnt_cb.own_addr_type; 417 uint8_t peer_addr_type = BLE_ADDR_PUBLIC; 418 419 uint8_t phy = PHY_LE_1M; 420 if (controller_get_interface()->supports_ble_2m_phy()) phy |= PHY_LE_2M; 421 if (controller_get_interface()->supports_ble_coded_phy()) phy |= PHY_LE_CODED; 422 423 BTM_TRACE_EVENT("%s start=%d", __func__, start); 424 425 if (start) { 426 if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending() && 427 btm_ble_topology_check(BTM_BLE_STATE_INIT) && l2cu_can_allocate_lcb()) { 428 p_cb->wl_state |= BTM_BLE_WL_INIT; 429 430 btm_execute_wl_dev_operation(); 431 432 #if (BLE_PRIVACY_SPT == TRUE) 433 btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT); 434 #endif 435 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) 436 ? BTM_BLE_SCAN_SLOW_INT_1 437 : p_cb->scan_int; 438 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) 439 ? BTM_BLE_SCAN_SLOW_WIN_1 440 : p_cb->scan_win; 441 442 #if (BLE_PRIVACY_SPT == TRUE) 443 if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE && 444 controller_get_interface()->supports_ble_privacy()) { 445 own_addr_type |= BLE_ADDR_TYPE_ID_BIT; 446 peer_addr_type |= BLE_ADDR_TYPE_ID_BIT; 447 } 448 #endif 449 450 btm_send_hci_create_connection( 451 scan_int, /* uint16_t scan_int */ 452 scan_win, /* uint16_t scan_win */ 453 0x01, /* uint8_t white_list */ 454 peer_addr_type, /* uint8_t addr_type_peer */ 455 RawAddress::kEmpty, /* BD_ADDR bda_peer */ 456 own_addr_type, /* uint8_t addr_type_own */ 457 BTM_BLE_CONN_INT_MIN_DEF, /* uint16_t conn_int_min */ 458 BTM_BLE_CONN_INT_MAX_DEF, /* uint16_t conn_int_max */ 459 BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* uint16_t conn_latency */ 460 BTM_BLE_CONN_TIMEOUT_DEF, /* uint16_t conn_timeout */ 461 0, /* uint16_t min_len */ 462 0, /* uint16_t max_len */ 463 phy); 464 btm_ble_set_conn_st(BLE_BG_CONN); 465 } else { 466 exec = false; 467 } 468 } else { 469 if (p_cb->conn_state == BLE_BG_CONN) { 470 btsnd_hcic_ble_create_conn_cancel(); 471 btm_ble_set_conn_st(BLE_CONN_CANCEL); 472 p_cb->wl_state &= ~BTM_BLE_WL_INIT; 473 } else { 474 BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop", 475 p_cb->conn_state); 476 exec = false; 477 } 478 } 479 return exec; 480 } 481 482 /******************************************************************************* 483 * 484 * Function btm_ble_suspend_bg_conn 485 * 486 * Description This function is to suspend an active background connection 487 * procedure. 488 * 489 * Parameters none. 490 * 491 * Returns none. 492 * 493 ******************************************************************************/ 494 bool btm_ble_suspend_bg_conn(void) { 495 BTM_TRACE_EVENT("%s", __func__); 496 497 if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_AUTO) 498 return btm_ble_start_auto_conn(false); 499 500 return false; 501 } 502 /******************************************************************************* 503 * 504 * Function btm_suspend_wl_activity 505 * 506 * Description This function is to suspend white list related activity 507 * 508 * Returns none. 509 * 510 ******************************************************************************/ 511 static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) { 512 if (wl_state & BTM_BLE_WL_INIT) { 513 btm_ble_start_auto_conn(false); 514 } 515 } 516 /******************************************************************************* 517 * 518 * Function btm_resume_wl_activity 519 * 520 * Description This function is to resume white list related activity 521 * 522 * Returns none. 523 * 524 ******************************************************************************/ 525 static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) { 526 btm_ble_resume_bg_conn(); 527 } 528 /******************************************************************************* 529 * 530 * Function btm_ble_resume_bg_conn 531 * 532 * Description This function is to resume a background auto connection 533 * procedure. 534 * 535 * Parameters none. 536 * 537 * Returns none. 538 * 539 ******************************************************************************/ 540 bool btm_ble_resume_bg_conn(void) { 541 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb; 542 if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) { 543 return btm_ble_start_auto_conn(true); 544 } 545 546 return false; 547 } 548 /******************************************************************************* 549 * 550 * Function btm_ble_get_conn_st 551 * 552 * Description This function get BLE connection state 553 * 554 * Returns connection state 555 * 556 ******************************************************************************/ 557 tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) { 558 return btm_cb.ble_ctr_cb.conn_state; 559 } 560 /******************************************************************************* 561 * 562 * Function btm_ble_set_conn_st 563 * 564 * Description This function set BLE connection state 565 * 566 * Returns None. 567 * 568 ******************************************************************************/ 569 void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) { 570 btm_cb.ble_ctr_cb.conn_state = new_st; 571 572 if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) 573 btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT); 574 else 575 btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT); 576 } 577 578 /******************************************************************************* 579 * 580 * Function btm_ble_enqueue_direct_conn_req 581 * 582 * Description This function enqueue the direct connection request 583 * 584 * Returns None. 585 * 586 ******************************************************************************/ 587 void btm_ble_enqueue_direct_conn_req(void* p_param) { 588 tBTM_BLE_CONN_REQ* p = 589 (tBTM_BLE_CONN_REQ*)osi_malloc(sizeof(tBTM_BLE_CONN_REQ)); 590 591 p->p_param = p_param; 592 593 fixed_queue_enqueue(btm_cb.ble_ctr_cb.conn_pending_q, p); 594 } 595 /******************************************************************************* 596 * 597 * Function btm_ble_dequeue_direct_conn_req 598 * 599 * Description This function dequeues the direct connection request 600 * 601 * Returns None. 602 * 603 ******************************************************************************/ 604 void btm_ble_dequeue_direct_conn_req(const RawAddress& rem_bda) { 605 if (fixed_queue_is_empty(btm_cb.ble_ctr_cb.conn_pending_q)) return; 606 607 list_t* list = fixed_queue_get_list(btm_cb.ble_ctr_cb.conn_pending_q); 608 for (const list_node_t* node = list_begin(list); node != list_end(list); 609 node = list_next(node)) { 610 tBTM_BLE_CONN_REQ* p_req = (tBTM_BLE_CONN_REQ*)list_node(node); 611 tL2C_LCB* p_lcb = (tL2C_LCB*)p_req->p_param; 612 if ((p_lcb == NULL) || (!p_lcb->in_use)) { 613 continue; 614 } 615 // If BD address matches 616 if (rem_bda == p_lcb->remote_bd_addr) { 617 fixed_queue_try_remove_from_queue(btm_cb.ble_ctr_cb.conn_pending_q, 618 p_req); 619 l2cu_release_lcb((tL2C_LCB*)p_req->p_param); 620 osi_free((void*)p_req); 621 break; 622 } 623 } 624 } 625 /******************************************************************************* 626 * 627 * Function btm_send_pending_direct_conn 628 * 629 * Description This function send the pending direct connection request in 630 * queue 631 * 632 * Returns true if started, false otherwise 633 * 634 ******************************************************************************/ 635 bool btm_send_pending_direct_conn(void) { 636 tBTM_BLE_CONN_REQ* p_req; 637 bool rt = false; 638 639 p_req = (tBTM_BLE_CONN_REQ*)fixed_queue_try_dequeue( 640 btm_cb.ble_ctr_cb.conn_pending_q); 641 if (p_req != NULL) { 642 tL2C_LCB* p_lcb = (tL2C_LCB*)(p_req->p_param); 643 /* Ignore entries that might have been released while queued. */ 644 if (p_lcb->in_use) rt = l2cble_init_direct_conn(p_lcb); 645 osi_free(p_req); 646 } 647 648 return rt; 649 } 650