l2c_ble.c revision f37456d5a14773e25386629803f7dcaecb37fb99
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 34#if (BLE_INCLUDED == TRUE) 35#define L2CA_GET_UPD_ST(x) ((x) & UPD_ST_MASK) 36#define L2CA_SET_UPD_ST(x, y) x = (((x) & ~UPD_ST_MASK) | (y)) 37 38#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE) 39#include "vendor_ble.h" 40#else 41#if BLE_PRIVACY_SPT == TRUE 42extern BOOLEAN btm_ble_get_acl_remote_addr(tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR conn_addr, 43 tBLE_ADDR_TYPE *p_addr_type); 44#endif 45#endif 46 47/******************************************************************************* 48** 49** Function L2CA_CancelBleConnectReq 50** 51** Description Cancel a pending connection attempt to a BLE device. 52** 53** Parameters: BD Address of remote 54** 55** Return value: TRUE if connection was cancelled 56** 57*******************************************************************************/ 58BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) 59{ 60 tL2C_LCB *p_lcb; 61 62 /* There can be only one BLE connection request outstanding at a time */ 63 if (btm_ble_get_conn_st() == BLE_CONN_IDLE) 64 { 65 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending"); 66 return(FALSE); 67 } 68 69 if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) 70 { 71 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x", 72 (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3], 73 (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5], 74 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]); 75 76 return(FALSE); 77 } 78 79 if (btsnd_hcic_ble_create_conn_cancel()) 80 { 81 82 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE)) != NULL) 83 { 84 p_lcb->disc_reason = L2CAP_CONN_CANCEL; 85 l2cu_release_lcb (p_lcb); 86 } 87 /* update state to be cancel, wait for connection cancel complete */ 88 btm_ble_set_conn_st (BLE_CONN_CANCEL); 89 90 return(TRUE); 91 } 92 else 93 return(FALSE); 94} 95 96/******************************************************************************* 97** 98** Function L2CA_UpdateBleConnParams 99** 100** Description Update BLE connection parameters. 101** 102** Parameters: BD Address of remote 103** 104** Return value: TRUE if update started 105** 106*******************************************************************************/ 107BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int, 108 UINT16 latency, UINT16 timeout) 109{ 110 tL2C_LCB *p_lcb; 111 tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE); 112 113 /* See if we have a link control block for the remote device */ 114 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE); 115 116 /* If we don't have one, create one and accept the connection. */ 117 if (!p_lcb || !p_acl_cb) 118 { 119 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x", 120 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 121 (rem_bda[4]<<8)+rem_bda[5]); 122 return(FALSE); 123 } 124 125 if (p_lcb->transport != BT_TRANSPORT_LE) 126 { 127 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE", 128 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 129 (rem_bda[4]<<8)+rem_bda[5]); 130 return(FALSE); 131 } 132#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) 133 /* if both 4.1 compliant */ 134 if ((HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) && 135 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))) 136 { 137 /* TODO: CE length selection ?? */ 138 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int, 139 latency, timeout, 0, 0); 140 } 141 else 142 /* if either side does not support Connection Parameters Request 143 Link Layer Control Procedure, 144 use Link Layer Connection Update procedure */ 145#endif 146 { 147 if (p_lcb->link_role == HCI_ROLE_MASTER) 148 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int, 149 latency, timeout, 0, 0); 150 else 151 l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout); 152 } 153 return(TRUE); 154 155} 156 157 158/******************************************************************************* 159** 160** Function L2CA_EnableUpdateBleConnParams 161** 162** Description Enable or disable update based on the request from the peer 163** 164** Parameters: BD Address of remote 165** 166** Return value: TRUE if update started 167** 168*******************************************************************************/ 169BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) 170{ 171 tL2C_LCB *p_lcb; 172 173 /* See if we have a link control block for the remote device */ 174 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE); 175 176 if (!p_lcb) 177 { 178 L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x", 179 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 180 (rem_bda[4]<<8)+rem_bda[5]); 181 return (FALSE); 182 } 183 184 L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__, 185 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 186 (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask); 187 188 if (p_lcb->transport != BT_TRANSPORT_LE || (p_lcb->link_role != HCI_ROLE_MASTER)) 189 { 190 L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE or not master %d", __FUNCTION__, 191 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], 192 (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role); 193 return (FALSE); 194 } 195 196 if (enable) 197 { 198 if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) == UPD_DISABLED) 199 { 200 p_lcb->conn_param_enb.param = (TIMER_PARAM_TYPE)p_lcb; 201 btu_start_timer (&p_lcb->conn_param_enb, BTU_TTYPE_L2CAP_END_CONN_UPD, 202 L2CAP_BLE_ENB_CONN_PARAM_TOUT); 203 L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENB_TOUT); 204 } 205 } 206 else if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) != UPD_DISABLED) 207 { 208 btu_stop_timer(&p_lcb->conn_param_enb); 209 210 if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED) 211 { 212 213 /* 214 application requests to disable parameters update.If parameters are already updated, 215 lets set them up to what has been requested during connection establishement 216 */ 217 if ((p_lcb->conn_update_mask & UPD_REQUEST) != 0) 218 { 219 /* revert back to default */ 220 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, 221 BTM_BLE_CONN_INT_MIN_DEF, 222 BTM_BLE_CONN_INT_MAX_DEF, 223 BTM_BLE_CONN_SLAVE_LATENCY_DEF, 224 BTM_BLE_CONN_TIMEOUT_DEF, 225 0, 0); 226 } 227 } 228 L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_DISABLED); 229 230 } 231 232 return (TRUE); 233 234} 235 236 237/******************************************************************************* 238** 239** Function L2CA_GetBleConnRole 240** 241** Description This function returns the connection role. 242** 243** Returns link role. 244** 245*******************************************************************************/ 246UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr) 247{ 248 UINT8 role = HCI_ROLE_UNKNOWN; 249 250 tL2C_LCB *p_lcb; 251 252 if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL) 253 role = p_lcb->link_role; 254 255 return role; 256} 257/******************************************************************************* 258** 259** Function L2CA_GetDisconnectReason 260** 261** Description This function returns the disconnect reason code. 262** 263** Returns disconnect reason 264** 265*******************************************************************************/ 266UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport) 267{ 268 tL2C_LCB *p_lcb; 269 UINT16 reason = 0; 270 271 if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL) 272 reason = p_lcb->disc_reason; 273 274 L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ",reason); 275 276 return reason; 277} 278 279/******************************************************************************* 280** 281** Function l2cble_scanner_conn_comp 282** 283** Description This function is called when an HCI Connection Complete 284** event is received while we are a scanner (so we are master). 285** 286** Returns void 287** 288*******************************************************************************/ 289void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, 290 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) 291{ 292 tL2C_LCB *p_lcb; 293 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda); 294 295 L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d", 296 handle, type, conn_interval, conn_latency, conn_timeout); 297 298 l2cb.is_ble_connecting = FALSE; 299 300 /* See if we have a link control block for the remote device */ 301 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE); 302 303 /* If we don't have one, create one. this is auto connection complete. */ 304 if (!p_lcb) 305 { 306 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE); 307 if (!p_lcb) 308 { 309 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); 310 L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB"); 311 return; 312 } 313 else 314 { 315 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) 316 { 317 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); 318 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB"); 319 return ; 320 } 321 } 322 } 323 else if (p_lcb->link_state != LST_CONNECTING) 324 { 325 L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state); 326 return; 327 } 328 btu_stop_timer(&p_lcb->timer_entry); 329 330 /* Save the handle */ 331 p_lcb->handle = handle; 332 333 /* Connected OK. Change state to connected, we were scanning so we are master */ 334 p_lcb->link_state = LST_CONNECTED; 335 p_lcb->link_role = HCI_ROLE_MASTER; 336 p_lcb->transport = BT_TRANSPORT_LE; 337 338 /* If there are any preferred connection parameters, set them now */ 339 if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && 340 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) && 341 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) && 342 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) && 343 (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) && 344 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) && 345 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) && 346 ((conn_interval < p_dev_rec->conn_params.min_conn_int && 347 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) || 348 (conn_interval > p_dev_rec->conn_params.max_conn_int) || 349 (conn_latency > p_dev_rec->conn_params.slave_latency) || 350 (conn_timeout > p_dev_rec->conn_params.supervision_tout))) 351 { 352 L2CAP_TRACE_ERROR ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", 353 handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, 354 p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout); 355 356 btsnd_hcic_ble_upd_ll_conn_params (handle, 357 p_dev_rec->conn_params.min_conn_int, 358 p_dev_rec->conn_params.max_conn_int, 359 p_dev_rec->conn_params.slave_latency, 360 p_dev_rec->conn_params.supervision_tout, 361 0, 0); 362 } 363 364 /* Tell BTM Acl management about the link */ 365 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE); 366 367 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT; 368 369 l2cu_process_fixed_chnl_resp (p_lcb); 370 371 btm_ble_set_conn_st(BLE_CONN_IDLE); 372} 373 374 375/******************************************************************************* 376** 377** Function l2cble_advertiser_conn_comp 378** 379** Description This function is called when an HCI Connection Complete 380** event is received while we are an advertiser (so we are slave). 381** 382** Returns void 383** 384*******************************************************************************/ 385void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, 386 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) 387{ 388 tL2C_LCB *p_lcb; 389 tBTM_SEC_DEV_REC *p_dev_rec; 390 UNUSED(type); 391 UNUSED(conn_interval); 392 UNUSED(conn_latency); 393 UNUSED(conn_timeout); 394 395 /* See if we have a link control block for the remote device */ 396 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE); 397 398 /* If we don't have one, create one and accept the connection. */ 399 if (!p_lcb) 400 { 401 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE); 402 if (!p_lcb) 403 { 404 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); 405 L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB"); 406 return; 407 } 408 else 409 { 410 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) 411 { 412 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); 413 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB"); 414 return ; 415 } 416 } 417 } 418 419 /* Save the handle */ 420 p_lcb->handle = handle; 421 422 /* Connected OK. Change state to connected, we were advertising, so we are slave */ 423 p_lcb->link_state = LST_CONNECTED; 424 p_lcb->link_role = HCI_ROLE_SLAVE; 425 p_lcb->transport = BT_TRANSPORT_LE; 426 427 /* Tell BTM Acl management about the link */ 428 p_dev_rec = btm_find_or_alloc_dev (bda); 429 430 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE); 431 432 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT; 433 434 l2cu_process_fixed_chnl_resp (p_lcb); 435 436 /* when adv and initiating are both active, cancel the direct connection */ 437 if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0) 438 { 439 L2CA_CancelBleConnectReq(bda); 440 } 441} 442 443/******************************************************************************* 444** 445** Function l2cble_conn_comp 446** 447** Description This function is called when an HCI Connection Complete 448** event is received. 449** 450** Returns void 451** 452*******************************************************************************/ 453void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type, 454 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) 455{ 456 if (role == HCI_ROLE_MASTER) 457 { 458 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout); 459 } 460 else 461 { 462 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout); 463 } 464} 465/******************************************************************************* 466** 467** Function l2cble_process_sig_cmd 468** 469** Description This function is called when a signalling packet is received 470** on the BLE signalling CID 471** 472** Returns void 473** 474*******************************************************************************/ 475void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) 476{ 477 UINT8 *p_pkt_end; 478 UINT8 cmd_code, id; 479 UINT16 cmd_len, rej_reason; 480 UINT16 result; 481 UINT16 min_interval, max_interval, latency, timeout; 482 483 p_pkt_end = p + pkt_len; 484 485 STREAM_TO_UINT8 (cmd_code, p); 486 STREAM_TO_UINT8 (id, p); 487 STREAM_TO_UINT16 (cmd_len, p); 488 489 /* Check command length does not exceed packet length */ 490 if ((p + cmd_len) > p_pkt_end) 491 { 492 L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d", pkt_len, cmd_len, cmd_code); 493 return; 494 } 495 496 switch (cmd_code) 497 { 498 case L2CAP_CMD_REJECT: 499 case L2CAP_CMD_ECHO_RSP: 500 case L2CAP_CMD_INFO_RSP: 501 STREAM_TO_UINT16 (rej_reason, p); 502 break; 503 case L2CAP_CMD_ECHO_REQ: 504 case L2CAP_CMD_INFO_REQ: 505 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 506 break; 507 508 case L2CAP_CMD_BLE_UPDATE_REQ: 509 STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */ 510 STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */ 511 STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */ 512 STREAM_TO_UINT16 (timeout, p); /* 0x000A - 0x0C80 */ 513 /* If we are a master, the slave wants to update the parameters */ 514 if (p_lcb->link_role == HCI_ROLE_MASTER) 515 { 516 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX || 517 max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX || 518 latency > BTM_BLE_CONN_LATENCY_MAX || 519 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/ 520 timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX || 521 max_interval < min_interval) 522 { 523 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id); 524 } 525 else 526 { 527 528 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id); 529 530 p_lcb->min_interval = min_interval; 531 p_lcb->max_interval = max_interval; 532 p_lcb->latency = latency; 533 p_lcb->timeout = timeout; 534 p_lcb->conn_update_mask |= UPD_REQUEST; 535 536 if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED) 537 { 538 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_interval, max_interval, 539 latency, timeout, 0, 0); 540 } 541 else 542 { 543 L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled"); 544 } 545 546 } 547 } 548 else 549 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 550 break; 551 552 case L2CAP_CMD_BLE_UPDATE_RSP: 553 STREAM_TO_UINT16 (result, p); 554 break; 555 556 default: 557 L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code); 558 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 559 return; 560 } 561} 562/******************************************************************************* 563** 564** Function l2c_enable_conn_param_timeout 565** 566** Description This function process the connection parameter enabling timeout 567** 568** Returns None. 569** 570*******************************************************************************/ 571void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb) 572{ 573 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr); 574 575 576 /* application allows to do update, if we were delaying one do it now, otherwise 577 just mark lcb that updates are enabled */ 578 if (p_lcb->conn_update_mask & UPD_REQUEST) 579 { 580 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, p_lcb->min_interval, p_lcb->max_interval, 581 p_lcb->latency, p_lcb->timeout, 0, 0); 582 } 583 else 584 { 585 /* if preferred number has been set, set to preferred conn parameter */ 586 if (p_dev_rec && p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) 587 { 588 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, 589 (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? 590 p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), 591 (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? 592 p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), 593 (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? 594 p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), 595 (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? 596 p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), 597 0, 0); 598 } 599 } 600 L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENABLED); 601 602} 603/******************************************************************************* 604** 605** Function l2cble_init_direct_conn 606** 607** Description This function is to initate a direct connection 608** 609** Returns TRUE connection initiated, FALSE otherwise. 610** 611*******************************************************************************/ 612BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) 613{ 614 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr); 615 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; 616 UINT16 scan_int, scan_win; 617 BD_ADDR init_addr; 618 UINT8 init_addr_type = BLE_ADDR_PUBLIC, 619 own_addr_type = BLE_ADDR_PUBLIC; 620 621 /* There can be only one BLE connection request outstanding at a time */ 622 if (p_dev_rec == NULL) 623 { 624 L2CAP_TRACE_WARNING ("unknown device, can not initate connection"); 625 return(FALSE); 626 } 627 628 scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int; 629 scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win; 630 631 init_addr_type = p_lcb->ble_addr_type; 632 memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN); 633 634#if BLE_PRIVACY_SPT == TRUE 635 if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA) 636 { 637 init_addr_type = BLE_ADDR_RANDOM; 638 } 639 /* if privacy is on and current do not consider using reconnection address */ 640 if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */ 641 own_addr_type = BLE_ADDR_RANDOM; 642#endif 643 644 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) 645 { 646 l2cu_release_lcb (p_lcb); 647 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation"); 648 return FALSE; 649 } 650#if BLE_PRIVACY_SPT == TRUE 651#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE) 652 extern tBTM_STATUS BTM_BleEnableIRKFeature(BOOLEAN enable); 653 if (btm_ble_vendor_irk_list_load_dev(p_dev_rec)) 654 BTM_BleEnableIRKFeature(TRUE); 655 656 btm_random_pseudo_to_public(init_addr, &init_addr_type); 657#else 658 btm_ble_get_acl_remote_addr(p_dev_rec, init_addr, &init_addr_type); 659#endif 660#endif 661 if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */ 662 scan_win, /* UINT16 scan_win */ 663 FALSE, /* UINT8 white_list */ 664 init_addr_type, /* UINT8 addr_type_peer */ 665 init_addr, /* BD_ADDR bda_peer */ 666 own_addr_type, /* UINT8 addr_type_own */ 667 (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? 668 p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* conn_int_min */ 669 (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? 670 p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* conn_int_max */ 671 (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? 672 p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */ 673 (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? 674 p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */ 675 0, /* UINT16 min_len */ 676 0)) /* UINT16 max_len */ 677 { 678 l2cu_release_lcb (p_lcb); 679 L2CAP_TRACE_ERROR("initate direct connection fail, no resources"); 680 return (FALSE); 681 } 682 else 683 { 684 p_lcb->link_state = LST_CONNECTING; 685 l2cb.is_ble_connecting = TRUE; 686 memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN); 687 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT); 688 btm_ble_set_conn_st (BLE_DIR_CONN); 689 690 return (TRUE); 691 } 692} 693 694/******************************************************************************* 695** 696** Function l2cble_create_conn 697** 698** Description This function initiates an acl connection via HCI 699** 700** Returns TRUE if successful, FALSE if connection not started. 701** 702*******************************************************************************/ 703BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb) 704{ 705 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st(); 706 BOOLEAN rt = FALSE; 707 708 /* There can be only one BLE connection request outstanding at a time */ 709 if (conn_st == BLE_CONN_IDLE) 710 { 711 rt = l2cble_init_direct_conn(p_lcb); 712 } 713 else 714 { 715 L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st); 716 717 btm_ble_enqueue_direct_conn_req(p_lcb); 718 719 if (conn_st == BLE_BG_CONN) 720 btm_ble_suspend_bg_conn(); 721 722 rt = TRUE; 723 } 724 return rt; 725} 726 727/******************************************************************************* 728** 729** Function l2c_link_processs_ble_num_bufs 730** 731** Description This function is called when a "controller buffer size" 732** event is first received from the controller. It updates 733** the L2CAP values. 734** 735** Returns void 736** 737*******************************************************************************/ 738void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs) 739{ 740 if (num_lm_ble_bufs == 0) 741 { 742 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED; 743 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED; 744 } 745 746 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs; 747} 748 749#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) 750/******************************************************************************* 751** 752** Function l2cble_process_rc_param_request_evt 753** 754** Description process LE Remote Connection Parameter Request Event. 755** 756** Returns void 757** 758*******************************************************************************/ 759void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max, 760 UINT16 latency, UINT16 timeout) 761{ 762 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle); 763 764 if (p_lcb != NULL) 765 { 766 p_lcb->min_interval = int_min; 767 p_lcb->max_interval = int_max; 768 p_lcb->latency = latency; 769 p_lcb->timeout = timeout; 770 p_lcb->conn_update_mask |= UPD_REQUEST; 771 772 /* TODO: revisit: if update is enabled, always accept connection parameter update */ 773 if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED) 774 { 775 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0); 776 } 777 else 778 { 779 L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled"); 780 btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL); 781 } 782 783 } 784 else 785 { 786 L2CAP_TRACE_WARNING("No link to update connection parameter") 787 } 788} 789#endif 790 791 792#endif /* (BLE_INCLUDED == TRUE) */ 793