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