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