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