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