1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-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 relating to BLE management. 22 * 23 ******************************************************************************/ 24 25 #include <base/logging.h> 26 #include <base/strings/stringprintf.h> 27 #include <string.h> 28 #include "bt_target.h" 29 #include "bt_utils.h" 30 #include "btm_int.h" 31 #include "btu.h" 32 #include "device/include/controller.h" 33 #include "hcimsgs.h" 34 #include "l2c_int.h" 35 #include "l2cdefs.h" 36 #include "osi/include/osi.h" 37 #include "stack_config.h" 38 39 using base::StringPrintf; 40 41 static void l2cble_start_conn_update(tL2C_LCB* p_lcb); 42 43 /******************************************************************************* 44 * 45 * Function L2CA_CancelBleConnectReq 46 * 47 * Description Cancel a pending connection attempt to a BLE device. 48 * 49 * Parameters: BD Address of remote 50 * 51 * Return value: true if connection was cancelled 52 * 53 ******************************************************************************/ 54 bool L2CA_CancelBleConnectReq(const RawAddress& rem_bda) { 55 tL2C_LCB* p_lcb; 56 57 /* There can be only one BLE connection request outstanding at a time */ 58 if (btm_ble_get_conn_st() == BLE_CONN_IDLE) { 59 L2CAP_TRACE_WARNING("%s - no connection pending", __func__); 60 return (false); 61 } 62 63 if (rem_bda != l2cb.ble_connecting_bda) { 64 LOG(WARNING) << __func__ 65 << " different BDA Connecting: " << l2cb.ble_connecting_bda 66 << " Cancel: " << rem_bda; 67 68 btm_ble_dequeue_direct_conn_req(rem_bda); 69 return (false); 70 } 71 72 btsnd_hcic_ble_create_conn_cancel(); 73 74 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE); 75 /* Do not remove lcb if an LE link is already up as a peripheral */ 76 if (p_lcb != NULL && 77 !(p_lcb->link_role == HCI_ROLE_SLAVE && 78 btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE) != NULL)) { 79 p_lcb->disc_reason = L2CAP_CONN_CANCEL; 80 l2cu_release_lcb(p_lcb); 81 } 82 /* update state to be cancel, wait for connection cancel complete */ 83 btm_ble_set_conn_st(BLE_CONN_CANCEL); 84 85 return (true); 86 } 87 88 /******************************************************************************* 89 * 90 * Function L2CA_UpdateBleConnParams 91 * 92 * Description Update BLE connection parameters. 93 * 94 * Parameters: BD Address of remote 95 * 96 * Return value: true if update started 97 * 98 ******************************************************************************/ 99 bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int, 100 uint16_t max_int, uint16_t latency, 101 uint16_t timeout) { 102 tL2C_LCB* p_lcb; 103 tACL_CONN* p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE); 104 105 /* See if we have a link control block for the remote device */ 106 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE); 107 108 /* If we don't have one, create one and accept the connection. */ 109 if (!p_lcb || !p_acl_cb) { 110 LOG(WARNING) << __func__ << " - unknown BD_ADDR " << rem_bda; 111 return (false); 112 } 113 114 if (p_lcb->transport != BT_TRANSPORT_LE) { 115 LOG(WARNING) << __func__ << " - BD_ADDR " << rem_bda << " not LE"; 116 return (false); 117 } 118 119 p_lcb->min_interval = min_int; 120 p_lcb->max_interval = max_int; 121 p_lcb->latency = latency; 122 p_lcb->timeout = timeout; 123 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; 124 125 l2cble_start_conn_update(p_lcb); 126 127 return (true); 128 } 129 130 /******************************************************************************* 131 * 132 * Function L2CA_EnableUpdateBleConnParams 133 * 134 * Description Enable or disable update based on the request from the peer 135 * 136 * Parameters: BD Address of remote 137 * 138 * Return value: true if update started 139 * 140 ******************************************************************************/ 141 bool L2CA_EnableUpdateBleConnParams(const RawAddress& rem_bda, bool enable) { 142 if (stack_config_get_interface()->get_pts_conn_updates_disabled()) 143 return false; 144 145 tL2C_LCB* p_lcb; 146 147 /* See if we have a link control block for the remote device */ 148 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE); 149 150 if (!p_lcb) { 151 LOG(WARNING) << __func__ << " - unknown BD_ADDR " << rem_bda; 152 return false; 153 } 154 155 VLOG(2) << __func__ << " - BD_ADDR " << rem_bda 156 << StringPrintf(" enable %d current upd state 0x%02x", enable, 157 p_lcb->conn_update_mask); 158 159 if (p_lcb->transport != BT_TRANSPORT_LE) { 160 LOG(WARNING) << __func__ << " - BD_ADDR " << rem_bda 161 << " not LE, link role " << p_lcb->link_role; 162 return false; 163 } 164 165 if (enable) 166 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE; 167 else 168 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE; 169 170 l2cble_start_conn_update(p_lcb); 171 172 return (true); 173 } 174 175 /******************************************************************************* 176 * 177 * Function L2CA_GetBleConnRole 178 * 179 * Description This function returns the connection role. 180 * 181 * Returns link role. 182 * 183 ******************************************************************************/ 184 uint8_t L2CA_GetBleConnRole(const RawAddress& bd_addr) { 185 uint8_t role = HCI_ROLE_UNKNOWN; 186 187 tL2C_LCB* p_lcb; 188 189 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE); 190 if (p_lcb != NULL) role = p_lcb->link_role; 191 192 return role; 193 } 194 /******************************************************************************* 195 * 196 * Function L2CA_GetDisconnectReason 197 * 198 * Description This function returns the disconnect reason code. 199 * 200 * Returns disconnect reason 201 * 202 ******************************************************************************/ 203 uint16_t L2CA_GetDisconnectReason(const RawAddress& remote_bda, 204 tBT_TRANSPORT transport) { 205 tL2C_LCB* p_lcb; 206 uint16_t reason = 0; 207 208 p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, transport); 209 if (p_lcb != NULL) reason = p_lcb->disc_reason; 210 211 L2CAP_TRACE_DEBUG("L2CA_GetDisconnectReason=%d ", reason); 212 213 return reason; 214 } 215 216 /******************************************************************************* 217 * 218 * Function l2cble_notify_le_connection 219 * 220 * Description This function notifiy the l2cap connection to the app layer 221 * 222 * Returns none 223 * 224 ******************************************************************************/ 225 void l2cble_notify_le_connection(const RawAddress& bda) { 226 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE); 227 tACL_CONN* p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE); 228 tL2C_CCB* p_ccb; 229 230 if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) { 231 /* update link status */ 232 btm_establish_continue(p_acl); 233 /* update l2cap link status and send callback */ 234 p_lcb->link_state = LST_CONNECTED; 235 l2cu_process_fixed_chnl_resp(p_lcb); 236 } 237 238 if (p_lcb != NULL) { 239 /* For all channels, send the event through their FSMs */ 240 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; 241 p_ccb = p_ccb->p_next_ccb) { 242 if (p_ccb->chnl_state == CST_CLOSED) 243 l2c_csm_execute(p_ccb, L2CEVT_LP_CONNECT_CFM, NULL); 244 } 245 } 246 } 247 248 /******************************************************************************* 249 * 250 * Function l2cble_scanner_conn_comp 251 * 252 * Description This function is called when an HCI Connection Complete 253 * event is received while we are a scanner (so we are master). 254 * 255 * Returns void 256 * 257 ******************************************************************************/ 258 void l2cble_scanner_conn_comp(uint16_t handle, const RawAddress& bda, 259 tBLE_ADDR_TYPE type, uint16_t conn_interval, 260 uint16_t conn_latency, uint16_t conn_timeout) { 261 tL2C_LCB* p_lcb; 262 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda); 263 264 L2CAP_TRACE_DEBUG( 265 "l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d " 266 "slave_latency=%d supervision_tout=%d", 267 handle, type, conn_interval, conn_latency, conn_timeout); 268 269 l2cb.is_ble_connecting = false; 270 271 /* See if we have a link control block for the remote device */ 272 p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE); 273 274 /* If we don't have one, create one. this is auto connection complete. */ 275 if (!p_lcb) { 276 p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE); 277 if (!p_lcb) { 278 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION); 279 L2CAP_TRACE_ERROR("l2cble_scanner_conn_comp - failed to allocate LCB"); 280 btm_ble_set_conn_st(BLE_CONN_IDLE); 281 return; 282 } else { 283 if (!l2cu_initialize_fixed_ccb( 284 p_lcb, L2CAP_ATT_CID, 285 &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL] 286 .fixed_chnl_opts)) { 287 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION); 288 L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB"); 289 btm_ble_set_conn_st(BLE_CONN_IDLE); 290 return; 291 } 292 } 293 } else if (p_lcb->link_state != LST_CONNECTING) { 294 L2CAP_TRACE_ERROR("L2CAP got BLE scanner conn_comp in bad state: %d", 295 p_lcb->link_state); 296 btm_ble_set_conn_st(BLE_CONN_IDLE); 297 return; 298 } 299 alarm_cancel(p_lcb->l2c_lcb_timer); 300 301 /* Save the handle */ 302 p_lcb->handle = handle; 303 304 /* Connected OK. Change state to connected, we were scanning so we are master 305 */ 306 p_lcb->link_role = HCI_ROLE_MASTER; 307 p_lcb->transport = BT_TRANSPORT_LE; 308 309 /* update link parameter, set slave link as non-spec default upon link up */ 310 p_lcb->min_interval = p_lcb->max_interval = conn_interval; 311 p_lcb->timeout = conn_timeout; 312 p_lcb->latency = conn_latency; 313 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; 314 315 /* Tell BTM Acl management about the link */ 316 btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, 317 BT_TRANSPORT_LE); 318 319 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | 320 L2CAP_FIXED_CHNL_BLE_SIG_BIT | 321 L2CAP_FIXED_CHNL_SMP_BIT; 322 323 btm_ble_set_conn_st(BLE_CONN_IDLE); 324 325 #if (BLE_PRIVACY_SPT == TRUE) 326 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true); 327 #endif 328 } 329 330 /******************************************************************************* 331 * 332 * Function l2cble_advertiser_conn_comp 333 * 334 * Description This function is called when an HCI Connection Complete 335 * event is received while we are an advertiser (so we are 336 * slave). 337 * 338 * Returns void 339 * 340 ******************************************************************************/ 341 void l2cble_advertiser_conn_comp(uint16_t handle, const RawAddress& bda, 342 UNUSED_ATTR tBLE_ADDR_TYPE type, 343 UNUSED_ATTR uint16_t conn_interval, 344 UNUSED_ATTR uint16_t conn_latency, 345 UNUSED_ATTR uint16_t conn_timeout) { 346 tL2C_LCB* p_lcb; 347 tBTM_SEC_DEV_REC* p_dev_rec; 348 349 /* See if we have a link control block for the remote device */ 350 p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE); 351 352 /* If we don't have one, create one and accept the connection. */ 353 if (!p_lcb) { 354 p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE); 355 if (!p_lcb) { 356 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION); 357 L2CAP_TRACE_ERROR("l2cble_advertiser_conn_comp - failed to allocate LCB"); 358 return; 359 } else { 360 if (!l2cu_initialize_fixed_ccb( 361 p_lcb, L2CAP_ATT_CID, 362 &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL] 363 .fixed_chnl_opts)) { 364 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION); 365 L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB"); 366 return; 367 } 368 } 369 } 370 371 /* Save the handle */ 372 p_lcb->handle = handle; 373 374 /* Connected OK. Change state to connected, we were advertising, so we are 375 * slave */ 376 p_lcb->link_role = HCI_ROLE_SLAVE; 377 p_lcb->transport = BT_TRANSPORT_LE; 378 379 /* update link parameter, set slave link as non-spec default upon link up */ 380 p_lcb->min_interval = p_lcb->max_interval = conn_interval; 381 p_lcb->timeout = conn_timeout; 382 p_lcb->latency = conn_latency; 383 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; 384 385 /* Tell BTM Acl management about the link */ 386 p_dev_rec = btm_find_or_alloc_dev(bda); 387 388 btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, 389 BT_TRANSPORT_LE); 390 391 #if (BLE_PRIVACY_SPT == TRUE) 392 btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true); 393 #endif 394 395 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | 396 L2CAP_FIXED_CHNL_BLE_SIG_BIT | 397 L2CAP_FIXED_CHNL_SMP_BIT; 398 399 if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED( 400 controller_get_interface()->get_features_ble()->as_array)) { 401 p_lcb->link_state = LST_CONNECTED; 402 l2cu_process_fixed_chnl_resp(p_lcb); 403 } 404 405 /* when adv and initiating are both active, cancel the direct connection */ 406 if (l2cb.is_ble_connecting && bda == l2cb.ble_connecting_bda) { 407 L2CA_CancelBleConnectReq(bda); 408 } 409 } 410 411 /******************************************************************************* 412 * 413 * Function l2cble_conn_comp 414 * 415 * Description This function is called when an HCI Connection Complete 416 * event is received. 417 * 418 * Returns void 419 * 420 ******************************************************************************/ 421 void l2cble_conn_comp(uint16_t handle, uint8_t role, const RawAddress& bda, 422 tBLE_ADDR_TYPE type, uint16_t conn_interval, 423 uint16_t conn_latency, uint16_t conn_timeout) { 424 btm_ble_update_link_topology_mask(role, true); 425 426 if (role == HCI_ROLE_MASTER) { 427 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, 428 conn_timeout); 429 } else { 430 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, 431 conn_timeout); 432 } 433 } 434 435 /******************************************************************************* 436 * 437 * Function l2cble_start_conn_update 438 * 439 * Description Start the BLE connection parameter update process based on 440 * status. 441 * 442 * Parameters: lcb : l2cap link control block 443 * 444 * Return value: none 445 * 446 ******************************************************************************/ 447 static void l2cble_start_conn_update(tL2C_LCB* p_lcb) { 448 uint16_t min_conn_int, max_conn_int, slave_latency, supervision_tout; 449 tACL_CONN* p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE); 450 if (!p_acl_cb) { 451 LOG(ERROR) << "No known connection ACL for " << p_lcb->remote_bd_addr; 452 return; 453 } 454 455 // TODO(armansito): The return value of this call wasn't being used but the 456 // logic of this function might be depending on its side effects. We should 457 // verify if this call is needed at all and remove it otherwise. 458 btm_find_or_alloc_dev(p_lcb->remote_bd_addr); 459 460 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return; 461 462 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) { 463 /* application requests to disable parameters update. 464 If parameters are already updated, lets set them 465 up to what has been requested during connection establishement */ 466 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM && 467 /* current connection interval is greater than default min */ 468 p_lcb->min_interval > BTM_BLE_CONN_INT_MIN) { 469 /* use 7.5 ms as fast connection parameter, 0 slave latency */ 470 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN; 471 slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF; 472 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF; 473 474 /* if both side 4.1, or we are master device, send HCI command */ 475 if (p_lcb->link_role == HCI_ROLE_MASTER 476 #if (BLE_LLT_INCLUDED == TRUE) 477 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED( 478 controller_get_interface()->get_features_ble()->as_array) && 479 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)) 480 #endif 481 ) { 482 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, 483 max_conn_int, slave_latency, 484 supervision_tout, 0, 0); 485 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING; 486 } else { 487 l2cu_send_peer_ble_par_req(p_lcb, min_conn_int, max_conn_int, 488 slave_latency, supervision_tout); 489 } 490 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM; 491 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; 492 } 493 } else { 494 /* application allows to do update, if we were delaying one do it now */ 495 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) { 496 /* if both side 4.1, or we are master device, send HCI command */ 497 if (p_lcb->link_role == HCI_ROLE_MASTER 498 #if (BLE_LLT_INCLUDED == TRUE) 499 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED( 500 controller_get_interface()->get_features_ble()->as_array) && 501 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)) 502 #endif 503 ) { 504 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval, 505 p_lcb->max_interval, p_lcb->latency, 506 p_lcb->timeout, 0, 0); 507 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING; 508 } else { 509 l2cu_send_peer_ble_par_req(p_lcb, p_lcb->min_interval, 510 p_lcb->max_interval, p_lcb->latency, 511 p_lcb->timeout); 512 } 513 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM; 514 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM; 515 } 516 } 517 } 518 519 /******************************************************************************* 520 * 521 * Function l2cble_process_conn_update_evt 522 * 523 * Description This function enables the connection update request from 524 * remote after a successful connection update response is 525 * received. 526 * 527 * Returns void 528 * 529 ******************************************************************************/ 530 void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status, 531 uint16_t interval, uint16_t latency, 532 uint16_t timeout) { 533 L2CAP_TRACE_DEBUG("%s", __func__); 534 535 /* See if we have a link control block for the remote device */ 536 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle); 537 if (!p_lcb) { 538 L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle); 539 return; 540 } 541 542 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; 543 544 if (status != HCI_SUCCESS) { 545 L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status); 546 } 547 548 l2cble_start_conn_update(p_lcb); 549 550 L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, 551 p_lcb->conn_update_mask); 552 } 553 554 /******************************************************************************* 555 * 556 * Function l2cble_process_sig_cmd 557 * 558 * Description This function is called when a signalling packet is received 559 * on the BLE signalling CID 560 * 561 * Returns void 562 * 563 ******************************************************************************/ 564 void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { 565 uint8_t* p_pkt_end; 566 uint8_t cmd_code, id; 567 uint16_t cmd_len; 568 uint16_t min_interval, max_interval, latency, timeout; 569 tL2C_CONN_INFO con_info; 570 uint16_t lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0; 571 tL2C_CCB *p_ccb = NULL, *temp_p_ccb = NULL; 572 tL2C_RCB* p_rcb; 573 uint16_t credit; 574 p_pkt_end = p + pkt_len; 575 576 STREAM_TO_UINT8(cmd_code, p); 577 STREAM_TO_UINT8(id, p); 578 STREAM_TO_UINT16(cmd_len, p); 579 580 /* Check command length does not exceed packet length */ 581 if ((p + cmd_len) > p_pkt_end) { 582 L2CAP_TRACE_WARNING( 583 "L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d", 584 pkt_len, cmd_len, cmd_code); 585 return; 586 } 587 588 switch (cmd_code) { 589 case L2CAP_CMD_REJECT: 590 p += 2; 591 break; 592 593 case L2CAP_CMD_ECHO_REQ: 594 case L2CAP_CMD_ECHO_RSP: 595 case L2CAP_CMD_INFO_RSP: 596 case L2CAP_CMD_INFO_REQ: 597 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 598 break; 599 600 case L2CAP_CMD_BLE_UPDATE_REQ: 601 STREAM_TO_UINT16(min_interval, p); /* 0x0006 - 0x0C80 */ 602 STREAM_TO_UINT16(max_interval, p); /* 0x0006 - 0x0C80 */ 603 STREAM_TO_UINT16(latency, p); /* 0x0000 - 0x03E8 */ 604 STREAM_TO_UINT16(timeout, p); /* 0x000A - 0x0C80 */ 605 /* If we are a master, the slave wants to update the parameters */ 606 if (p_lcb->link_role == HCI_ROLE_MASTER) { 607 if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT) 608 min_interval = BTM_BLE_CONN_INT_MIN_LIMIT; 609 610 // While this could result in connection parameters that fall 611 // outside fo the range requested, this will allow the connection 612 // to remain established. 613 // In other words, this is a workaround for certain peripherals. 614 if (max_interval < BTM_BLE_CONN_INT_MIN_LIMIT) 615 max_interval = BTM_BLE_CONN_INT_MIN_LIMIT; 616 617 if (min_interval < BTM_BLE_CONN_INT_MIN || 618 min_interval > BTM_BLE_CONN_INT_MAX || 619 max_interval < BTM_BLE_CONN_INT_MIN || 620 max_interval > BTM_BLE_CONN_INT_MAX || 621 latency > BTM_BLE_CONN_LATENCY_MAX || 622 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval 623 * 1.25) - 1)) ||*/ 624 timeout < BTM_BLE_CONN_SUP_TOUT_MIN || 625 timeout > BTM_BLE_CONN_SUP_TOUT_MAX || 626 max_interval < min_interval) { 627 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id); 628 } else { 629 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_OK, id); 630 631 p_lcb->min_interval = min_interval; 632 p_lcb->max_interval = max_interval; 633 p_lcb->latency = latency; 634 p_lcb->timeout = timeout; 635 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; 636 637 l2cble_start_conn_update(p_lcb); 638 } 639 } else 640 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 641 0); 642 break; 643 644 case L2CAP_CMD_BLE_UPDATE_RSP: 645 p += 2; 646 break; 647 648 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: 649 STREAM_TO_UINT16(con_info.psm, p); 650 STREAM_TO_UINT16(rcid, p); 651 STREAM_TO_UINT16(mtu, p); 652 STREAM_TO_UINT16(mps, p); 653 STREAM_TO_UINT16(initial_credit, p); 654 655 L2CAP_TRACE_DEBUG( 656 "Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ with " 657 "mtu = %d, " 658 "mps = %d, " 659 "initial credit = %d", 660 mtu, mps, initial_credit); 661 662 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid); 663 if (p_ccb) { 664 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for duplicated cid: 0x%04x", 665 rcid); 666 l2cu_reject_ble_connection(p_lcb, id, 667 L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED); 668 break; 669 } 670 671 p_rcb = l2cu_find_ble_rcb_by_psm(con_info.psm); 672 if (p_rcb == NULL) { 673 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: 0x%04x", 674 con_info.psm); 675 l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_NO_PSM); 676 break; 677 } else { 678 if (!p_rcb->api.pL2CA_ConnectInd_Cb) { 679 L2CAP_TRACE_WARNING( 680 "L2CAP - rcvd conn req for outgoing-only connection PSM: %d", 681 con_info.psm); 682 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_PSM); 683 break; 684 } 685 } 686 687 /* Allocate a ccb for this.*/ 688 p_ccb = l2cu_allocate_ccb(p_lcb, 0); 689 if (p_ccb == NULL) { 690 L2CAP_TRACE_ERROR("L2CAP - unable to allocate CCB"); 691 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_RESOURCES); 692 break; 693 } 694 695 /* validate the parameters */ 696 if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS || 697 mps > L2CAP_LE_MAX_MPS) { 698 L2CAP_TRACE_ERROR("L2CAP don't like the params"); 699 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_RESOURCES); 700 break; 701 } 702 703 p_ccb->remote_id = id; 704 p_ccb->p_rcb = p_rcb; 705 p_ccb->remote_cid = rcid; 706 707 p_ccb->peer_conn_cfg.mtu = mtu; 708 p_ccb->peer_conn_cfg.mps = mps; 709 p_ccb->peer_conn_cfg.credits = initial_credit; 710 711 p_ccb->tx_mps = mps; 712 p_ccb->ble_sdu = NULL; 713 p_ccb->ble_sdu_length = 0; 714 p_ccb->is_first_seg = true; 715 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE; 716 717 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info); 718 break; 719 720 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES: 721 L2CAP_TRACE_DEBUG("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES"); 722 /* For all channels, see whose identifier matches this id */ 723 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb; 724 temp_p_ccb = temp_p_ccb->p_next_ccb) { 725 if (temp_p_ccb->local_id == id) { 726 p_ccb = temp_p_ccb; 727 break; 728 } 729 } 730 if (p_ccb) { 731 L2CAP_TRACE_DEBUG("I remember the connection req"); 732 STREAM_TO_UINT16(p_ccb->remote_cid, p); 733 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mtu, p); 734 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mps, p); 735 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.credits, p); 736 STREAM_TO_UINT16(con_info.l2cap_result, p); 737 con_info.remote_cid = p_ccb->remote_cid; 738 739 L2CAP_TRACE_DEBUG( 740 "remote_cid = %d, " 741 "mtu = %d, " 742 "mps = %d, " 743 "initial_credit = %d, " 744 "con_info.l2cap_result = %d", 745 p_ccb->remote_cid, p_ccb->peer_conn_cfg.mtu, 746 p_ccb->peer_conn_cfg.mps, p_ccb->peer_conn_cfg.credits, 747 con_info.l2cap_result); 748 749 /* validate the parameters */ 750 if (p_ccb->peer_conn_cfg.mtu < L2CAP_LE_MIN_MTU || 751 p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS || 752 p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS) { 753 L2CAP_TRACE_ERROR("L2CAP don't like the params"); 754 con_info.l2cap_result = L2CAP_LE_NO_RESOURCES; 755 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info); 756 break; 757 } 758 759 p_ccb->tx_mps = p_ccb->peer_conn_cfg.mps; 760 p_ccb->ble_sdu = NULL; 761 p_ccb->ble_sdu_length = 0; 762 p_ccb->is_first_seg = true; 763 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE; 764 765 if (con_info.l2cap_result == L2CAP_LE_CONN_OK) 766 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info); 767 else 768 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info); 769 } else { 770 L2CAP_TRACE_DEBUG("I DO NOT remember the connection req"); 771 con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID; 772 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info); 773 } 774 break; 775 776 case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT: 777 STREAM_TO_UINT16(lcid, p); 778 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, lcid); 779 if (p_ccb == NULL) { 780 L2CAP_TRACE_DEBUG("%s Credit received for unknown channel id %d", 781 __func__, lcid); 782 break; 783 } 784 785 STREAM_TO_UINT16(credit, p); 786 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT, &credit); 787 L2CAP_TRACE_DEBUG("%s Credit received", __func__); 788 break; 789 790 case L2CAP_CMD_DISC_REQ: 791 STREAM_TO_UINT16(lcid, p); 792 STREAM_TO_UINT16(rcid, p); 793 794 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid); 795 if (p_ccb != NULL) { 796 if (p_ccb->remote_cid == rcid) { 797 p_ccb->remote_id = id; 798 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL); 799 } 800 } else 801 l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid); 802 803 break; 804 805 case L2CAP_CMD_DISC_RSP: 806 STREAM_TO_UINT16(rcid, p); 807 STREAM_TO_UINT16(lcid, p); 808 809 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid); 810 if (p_ccb != NULL) { 811 if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id)) 812 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, NULL); 813 } 814 break; 815 816 default: 817 L2CAP_TRACE_WARNING("L2CAP - LE - unknown cmd code: %d", cmd_code); 818 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 819 break; 820 } 821 } 822 823 /******************************************************************************* 824 * 825 * Function l2cble_init_direct_conn 826 * 827 * Description This function is to initate a direct connection 828 * 829 * Returns true connection initiated, false otherwise. 830 * 831 ******************************************************************************/ 832 bool l2cble_init_direct_conn(tL2C_LCB* p_lcb) { 833 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr); 834 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb; 835 uint16_t scan_int; 836 uint16_t scan_win; 837 RawAddress peer_addr; 838 uint8_t peer_addr_type = BLE_ADDR_PUBLIC; 839 uint8_t own_addr_type = BLE_ADDR_PUBLIC; 840 841 /* There can be only one BLE connection request outstanding at a time */ 842 if (p_dev_rec == NULL) { 843 L2CAP_TRACE_WARNING("unknown device, can not initate connection"); 844 return (false); 845 } 846 847 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) 848 ? BTM_BLE_SCAN_FAST_INT 849 : p_cb->scan_int; 850 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) 851 ? BTM_BLE_SCAN_FAST_WIN 852 : p_cb->scan_win; 853 854 peer_addr_type = p_lcb->ble_addr_type; 855 peer_addr = p_lcb->remote_bd_addr; 856 857 #if (BLE_PRIVACY_SPT == TRUE) 858 own_addr_type = 859 btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC; 860 if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) { 861 if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2) 862 own_addr_type |= BLE_ADDR_TYPE_ID_BIT; 863 864 btm_ble_enable_resolving_list(BTM_BLE_RL_INIT); 865 btm_random_pseudo_to_identity_addr(&peer_addr, &peer_addr_type); 866 } else { 867 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true); 868 869 // If we have a current RPA, use that instead. 870 if (!p_dev_rec->ble.cur_rand_addr.IsEmpty()) { 871 peer_addr = p_dev_rec->ble.cur_rand_addr; 872 } 873 } 874 #endif 875 876 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) { 877 l2cu_release_lcb(p_lcb); 878 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation"); 879 return false; 880 } 881 882 btm_send_hci_create_connection( 883 scan_int, /* uint16_t scan_int */ 884 scan_win, /* uint16_t scan_win */ 885 false, /* uint8_t white_list */ 886 peer_addr_type, /* uint8_t addr_type_peer */ 887 peer_addr, /* BD_ADDR bda_peer */ 888 own_addr_type, /* uint8_t addr_type_own */ 889 (uint16_t)( 890 (p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) 891 ? p_dev_rec->conn_params.min_conn_int 892 : BTM_BLE_CONN_INT_MIN_DEF), /* uint16_t conn_int_min */ 893 (uint16_t)( 894 (p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) 895 ? p_dev_rec->conn_params.max_conn_int 896 : BTM_BLE_CONN_INT_MAX_DEF), /* uint16_t conn_int_max */ 897 (uint16_t)( 898 (p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) 899 ? p_dev_rec->conn_params.slave_latency 900 : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* uint16_t conn_latency */ 901 (uint16_t)( 902 (p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) 903 ? p_dev_rec->conn_params.supervision_tout 904 : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */ 905 0, /* uint16_t min_len */ 906 0, /* uint16_t max_len */ 907 p_lcb->initiating_phys); 908 909 p_lcb->link_state = LST_CONNECTING; 910 l2cb.is_ble_connecting = true; 911 l2cb.ble_connecting_bda = p_lcb->remote_bd_addr; 912 alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS, 913 l2c_lcb_timer_timeout, p_lcb); 914 btm_ble_set_conn_st(BLE_DIR_CONN); 915 916 return (true); 917 } 918 919 /******************************************************************************* 920 * 921 * Function l2cble_create_conn 922 * 923 * Description This function initiates an acl connection via HCI 924 * 925 * Returns true if successful, false if connection not started. 926 * 927 ******************************************************************************/ 928 bool l2cble_create_conn(tL2C_LCB* p_lcb) { 929 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st(); 930 bool rt = false; 931 932 /* There can be only one BLE connection request outstanding at a time */ 933 if (conn_st == BLE_CONN_IDLE) { 934 rt = l2cble_init_direct_conn(p_lcb); 935 } else { 936 L2CAP_TRACE_WARNING( 937 "L2CAP - LE - cannot start new connection at conn st: %d", conn_st); 938 939 btm_ble_enqueue_direct_conn_req(p_lcb); 940 941 if (conn_st == BLE_BG_CONN) btm_ble_suspend_bg_conn(); 942 943 rt = true; 944 } 945 return rt; 946 } 947 948 /******************************************************************************* 949 * 950 * Function l2c_link_processs_ble_num_bufs 951 * 952 * Description This function is called when a "controller buffer size" 953 * event is first received from the controller. It updates 954 * the L2CAP values. 955 * 956 * Returns void 957 * 958 ******************************************************************************/ 959 void l2c_link_processs_ble_num_bufs(uint16_t num_lm_ble_bufs) { 960 if (num_lm_ble_bufs == 0) { 961 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED; 962 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED; 963 } 964 965 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs; 966 } 967 968 /******************************************************************************* 969 * 970 * Function l2c_ble_link_adjust_allocation 971 * 972 * Description This function is called when a link is created or removed 973 * to calculate the amount of packets each link may send to 974 * the HCI without an ack coming back. 975 * 976 * Currently, this is a simple allocation, dividing the 977 * number of Controller Packets by the number of links. In 978 * the future, QOS configuration should be examined. 979 * 980 * Returns void 981 * 982 ******************************************************************************/ 983 void l2c_ble_link_adjust_allocation(void) { 984 uint16_t qq, yy, qq_remainder; 985 tL2C_LCB* p_lcb; 986 uint16_t hi_quota, low_quota; 987 uint16_t num_lowpri_links = 0; 988 uint16_t num_hipri_links = 0; 989 uint16_t controller_xmit_quota = l2cb.num_lm_ble_bufs; 990 uint16_t high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A; 991 992 /* If no links active, reset buffer quotas and controller buffers */ 993 if (l2cb.num_ble_links_active == 0) { 994 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs; 995 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0; 996 return; 997 } 998 999 /* First, count the links */ 1000 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { 1001 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) { 1002 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) 1003 num_hipri_links++; 1004 else 1005 num_lowpri_links++; 1006 } 1007 } 1008 1009 /* now adjust high priority link quota */ 1010 low_quota = num_lowpri_links ? 1 : 0; 1011 while ((num_hipri_links * high_pri_link_quota + low_quota) > 1012 controller_xmit_quota) 1013 high_pri_link_quota--; 1014 1015 /* Work out the xmit quota and buffer quota high and low priorities */ 1016 hi_quota = num_hipri_links * high_pri_link_quota; 1017 low_quota = 1018 (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1; 1019 1020 /* Work out and save the HCI xmit quota for each low priority link */ 1021 1022 /* If each low priority link cannot have at least one buffer */ 1023 if (num_lowpri_links > low_quota) { 1024 l2cb.ble_round_robin_quota = low_quota; 1025 qq = qq_remainder = 0; 1026 } 1027 /* If each low priority link can have at least one buffer */ 1028 else if (num_lowpri_links > 0) { 1029 l2cb.ble_round_robin_quota = 0; 1030 l2cb.ble_round_robin_unacked = 0; 1031 qq = low_quota / num_lowpri_links; 1032 qq_remainder = low_quota % num_lowpri_links; 1033 } 1034 /* If no low priority link */ 1035 else { 1036 l2cb.ble_round_robin_quota = 0; 1037 l2cb.ble_round_robin_unacked = 0; 1038 qq = qq_remainder = 0; 1039 } 1040 L2CAP_TRACE_EVENT( 1041 "l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u " 1042 "low_quota: %u round_robin_quota: %u qq: %u", 1043 num_hipri_links, num_lowpri_links, low_quota, l2cb.ble_round_robin_quota, 1044 qq); 1045 1046 /* Now, assign the quotas to each link */ 1047 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) { 1048 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) { 1049 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) { 1050 p_lcb->link_xmit_quota = high_pri_link_quota; 1051 } else { 1052 /* Safety check in case we switched to round-robin with something 1053 * outstanding */ 1054 /* if sent_not_acked is added into round_robin_unacked then don't add it 1055 * again */ 1056 /* l2cap keeps updating sent_not_acked for exiting from round robin */ 1057 if ((p_lcb->link_xmit_quota > 0) && (qq == 0)) 1058 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked; 1059 1060 p_lcb->link_xmit_quota = qq; 1061 if (qq_remainder > 0) { 1062 p_lcb->link_xmit_quota++; 1063 qq_remainder--; 1064 } 1065 } 1066 1067 L2CAP_TRACE_EVENT( 1068 "l2c_ble_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d", 1069 yy, p_lcb->acl_priority, p_lcb->link_xmit_quota); 1070 1071 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d", 1072 p_lcb->sent_not_acked, l2cb.round_robin_unacked); 1073 1074 /* There is a special case where we have readjusted the link quotas and */ 1075 /* this link may have sent anything but some other link sent packets so */ 1076 /* so we may need a timer to kick off this link's transmissions. */ 1077 if ((p_lcb->link_state == LST_CONNECTED) && 1078 (!list_is_empty(p_lcb->link_xmit_data_q)) && 1079 (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) { 1080 alarm_set_on_mloop(p_lcb->l2c_lcb_timer, 1081 L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS, 1082 l2c_lcb_timer_timeout, p_lcb); 1083 } 1084 } 1085 } 1086 } 1087 1088 #if (BLE_LLT_INCLUDED == TRUE) 1089 /******************************************************************************* 1090 * 1091 * Function l2cble_process_rc_param_request_evt 1092 * 1093 * Description process LE Remote Connection Parameter Request Event. 1094 * 1095 * Returns void 1096 * 1097 ******************************************************************************/ 1098 void l2cble_process_rc_param_request_evt(uint16_t handle, uint16_t int_min, 1099 uint16_t int_max, uint16_t latency, 1100 uint16_t timeout) { 1101 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle); 1102 1103 if (p_lcb != NULL) { 1104 p_lcb->min_interval = int_min; 1105 p_lcb->max_interval = int_max; 1106 p_lcb->latency = latency; 1107 p_lcb->timeout = timeout; 1108 1109 /* if update is enabled, always accept connection parameter update */ 1110 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) { 1111 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, 1112 timeout, 0, 0); 1113 } else { 1114 L2CAP_TRACE_EVENT("L2CAP - LE - update currently disabled"); 1115 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; 1116 btsnd_hcic_ble_rc_param_req_neg_reply(handle, 1117 HCI_ERR_UNACCEPT_CONN_INTERVAL); 1118 } 1119 1120 } else { 1121 L2CAP_TRACE_WARNING("No link to update connection parameter") 1122 } 1123 } 1124 #endif 1125 1126 /******************************************************************************* 1127 * 1128 * Function l2cble_update_data_length 1129 * 1130 * Description This function update link tx data length if applicable 1131 * 1132 * Returns void 1133 * 1134 ******************************************************************************/ 1135 void l2cble_update_data_length(tL2C_LCB* p_lcb) { 1136 uint16_t tx_mtu = 0; 1137 uint16_t i = 0; 1138 1139 L2CAP_TRACE_DEBUG("%s", __func__); 1140 1141 /* See if we have a link control block for the connection */ 1142 if (p_lcb == NULL) return; 1143 1144 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++) { 1145 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID) { 1146 if ((p_lcb->p_fixed_ccbs[i] != NULL) && 1147 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD))) 1148 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD; 1149 } 1150 } 1151 1152 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) tx_mtu = BTM_BLE_DATA_SIZE_MAX; 1153 1154 /* update TX data length if changed */ 1155 if (p_lcb->tx_data_len != tx_mtu) 1156 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu); 1157 } 1158 1159 /******************************************************************************* 1160 * 1161 * Function l2cble_process_data_length_change_evt 1162 * 1163 * Description This function process the data length change event 1164 * 1165 * Returns void 1166 * 1167 ******************************************************************************/ 1168 void l2cble_process_data_length_change_event(uint16_t handle, 1169 uint16_t tx_data_len, 1170 uint16_t rx_data_len) { 1171 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle); 1172 1173 L2CAP_TRACE_DEBUG("%s TX data len = %d", __func__, tx_data_len); 1174 if (p_lcb == NULL) return; 1175 1176 if (tx_data_len > 0) p_lcb->tx_data_len = tx_data_len; 1177 1178 /* ignore rx_data len for now */ 1179 } 1180 1181 /******************************************************************************* 1182 * 1183 * Function l2cble_set_fixed_channel_tx_data_length 1184 * 1185 * Description This function update max fixed channel tx data length if 1186 * applicable 1187 * 1188 * Returns void 1189 * 1190 ******************************************************************************/ 1191 void l2cble_set_fixed_channel_tx_data_length(const RawAddress& remote_bda, 1192 uint16_t fix_cid, 1193 uint16_t tx_mtu) { 1194 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE); 1195 uint16_t cid = fix_cid - L2CAP_FIRST_FIXED_CHNL; 1196 1197 L2CAP_TRACE_DEBUG("%s TX MTU = %d", __func__, tx_mtu); 1198 1199 if (!controller_get_interface()->supports_ble_packet_extension()) { 1200 L2CAP_TRACE_WARNING("%s, request not supported", __func__); 1201 return; 1202 } 1203 1204 /* See if we have a link control block for the connection */ 1205 if (p_lcb == NULL) return; 1206 1207 if (p_lcb->p_fixed_ccbs[cid] != NULL) { 1208 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) tx_mtu = BTM_BLE_DATA_SIZE_MAX; 1209 1210 p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu; 1211 } 1212 1213 l2cble_update_data_length(p_lcb); 1214 } 1215 1216 /******************************************************************************* 1217 * 1218 * Function l2cble_credit_based_conn_req 1219 * 1220 * Description This function sends LE Credit Based Connection Request for 1221 * LE connection oriented channels. 1222 * 1223 * Returns void 1224 * 1225 ******************************************************************************/ 1226 void l2cble_credit_based_conn_req(tL2C_CCB* p_ccb) { 1227 if (!p_ccb) return; 1228 1229 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1230 L2CAP_TRACE_WARNING("LE link doesn't exist"); 1231 return; 1232 } 1233 1234 l2cu_send_peer_ble_credit_based_conn_req(p_ccb); 1235 return; 1236 } 1237 1238 /******************************************************************************* 1239 * 1240 * Function l2cble_credit_based_conn_res 1241 * 1242 * Description This function sends LE Credit Based Connection Response for 1243 * LE connection oriented channels. 1244 * 1245 * Returns void 1246 * 1247 ******************************************************************************/ 1248 void l2cble_credit_based_conn_res(tL2C_CCB* p_ccb, uint16_t result) { 1249 if (!p_ccb) return; 1250 1251 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1252 L2CAP_TRACE_WARNING("LE link doesn't exist"); 1253 return; 1254 } 1255 1256 l2cu_send_peer_ble_credit_based_conn_res(p_ccb, result); 1257 return; 1258 } 1259 1260 /******************************************************************************* 1261 * 1262 * Function l2cble_send_flow_control_credit 1263 * 1264 * Description This function sends flow control credits for 1265 * LE connection oriented channels. 1266 * 1267 * Returns void 1268 * 1269 ******************************************************************************/ 1270 void l2cble_send_flow_control_credit(tL2C_CCB* p_ccb, uint16_t credit_value) { 1271 if (!p_ccb) return; 1272 1273 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1274 L2CAP_TRACE_WARNING("LE link doesn't exist"); 1275 return; 1276 } 1277 1278 l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value); 1279 return; 1280 } 1281 1282 /******************************************************************************* 1283 * 1284 * Function l2cble_send_peer_disc_req 1285 * 1286 * Description This function sends disconnect request 1287 * to the peer LE device 1288 * 1289 * Returns void 1290 * 1291 ******************************************************************************/ 1292 void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb) { 1293 L2CAP_TRACE_DEBUG("%s", __func__); 1294 if (!p_ccb) return; 1295 1296 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1297 L2CAP_TRACE_WARNING("LE link doesn't exist"); 1298 return; 1299 } 1300 1301 l2cu_send_peer_ble_credit_based_disconn_req(p_ccb); 1302 return; 1303 } 1304 1305 /******************************************************************************* 1306 * 1307 * Function l2cble_sec_comp 1308 * 1309 * Description This function is called when security procedure for an LE 1310 * COC link is done 1311 * 1312 * Returns void 1313 * 1314 ******************************************************************************/ 1315 void l2cble_sec_comp(const RawAddress* bda, tBT_TRANSPORT transport, 1316 void* p_ref_data, uint8_t status) { 1317 const RawAddress& p_bda = *bda; 1318 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE); 1319 tL2CAP_SEC_DATA* p_buf = NULL; 1320 uint8_t sec_flag; 1321 uint8_t sec_act; 1322 1323 if (!p_lcb) { 1324 L2CAP_TRACE_WARNING("%s security complete for unknown device", __func__); 1325 return; 1326 } 1327 1328 sec_act = p_lcb->sec_act; 1329 p_lcb->sec_act = 0; 1330 1331 if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) { 1332 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q); 1333 if (!p_buf) { 1334 L2CAP_TRACE_WARNING( 1335 "%s Security complete for request not initiated from L2CAP", 1336 __func__); 1337 return; 1338 } 1339 1340 if (status != BTM_SUCCESS) { 1341 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status); 1342 } else { 1343 if (sec_act == BTM_SEC_ENCRYPT_MITM) { 1344 BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport); 1345 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) 1346 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, 1347 status); 1348 else { 1349 L2CAP_TRACE_DEBUG("%s MITM Protection Not present", __func__); 1350 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, 1351 BTM_FAILED_ON_SECURITY); 1352 } 1353 } else { 1354 L2CAP_TRACE_DEBUG("%s MITM Protection not required sec_act = %d", 1355 __func__, p_lcb->sec_act); 1356 1357 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, 1358 status); 1359 } 1360 } 1361 } else { 1362 L2CAP_TRACE_WARNING( 1363 "%s Security complete for request not initiated from L2CAP", __func__); 1364 return; 1365 } 1366 osi_free(p_buf); 1367 1368 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) { 1369 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q); 1370 1371 if (status != BTM_SUCCESS) 1372 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status); 1373 else 1374 l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator, 1375 p_buf->p_callback, p_buf->p_ref_data); 1376 1377 osi_free(p_buf); 1378 } 1379 } 1380 1381 /******************************************************************************* 1382 * 1383 * Function l2ble_sec_access_req 1384 * 1385 * Description This function is called by LE COC link to meet the 1386 * security requirement for the link 1387 * 1388 * Returns true - security procedures are started 1389 * false - failure 1390 * 1391 ******************************************************************************/ 1392 bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm, 1393 bool is_originator, tL2CAP_SEC_CBACK* p_callback, 1394 void* p_ref_data) { 1395 L2CAP_TRACE_DEBUG("%s", __func__); 1396 bool status; 1397 tL2C_LCB* p_lcb = NULL; 1398 1399 if (!p_callback) { 1400 L2CAP_TRACE_ERROR("%s No callback function", __func__); 1401 return false; 1402 } 1403 1404 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE); 1405 1406 if (!p_lcb) { 1407 L2CAP_TRACE_ERROR("%s Security check for unknown device", __func__); 1408 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR); 1409 return false; 1410 } 1411 1412 tL2CAP_SEC_DATA* p_buf = 1413 (tL2CAP_SEC_DATA*)osi_malloc((uint16_t)sizeof(tL2CAP_SEC_DATA)); 1414 if (!p_buf) { 1415 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES); 1416 return false; 1417 } 1418 1419 p_buf->psm = psm; 1420 p_buf->is_originator = is_originator; 1421 p_buf->p_callback = p_callback; 1422 p_buf->p_ref_data = p_ref_data; 1423 fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf); 1424 status = btm_ble_start_sec_check(bd_addr, psm, is_originator, 1425 &l2cble_sec_comp, p_ref_data); 1426 1427 return status; 1428 } 1429