1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-2013 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 #include "bt_target.h" 21 #include "bt_utils.h" 22 #include "btu.h" 23 #include "gap_int.h" 24 #include "l2cdefs.h" 25 #include "l2c_int.h" 26 #include <string.h> 27 #include "osi/include/mutex.h" 28 #if GAP_CONN_INCLUDED == TRUE 29 #include "btm_int.h" 30 31 /********************************************************************************/ 32 /* L O C A L F U N C T I O N P R O T O T Y P E S */ 33 /********************************************************************************/ 34 static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id); 35 static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result); 36 static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 37 static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 38 static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed); 39 static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg); 40 static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested); 41 static void gap_tx_complete_ind (UINT16 l2cap_cid, UINT16 sdu_sent); 42 43 static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid); 44 static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle); 45 static tGAP_CCB *gap_allocate_ccb (void); 46 static void gap_release_ccb (tGAP_CCB *p_ccb); 47 static void gap_checks_con_flags (tGAP_CCB *p_ccb); 48 49 /******************************************************************************* 50 ** 51 ** Function gap_conn_init 52 ** 53 ** Description This function is called to initialize GAP connection management 54 ** 55 ** Returns void 56 ** 57 *******************************************************************************/ 58 void gap_conn_init (void) 59 { 60 #if AMP_INCLUDED == TRUE 61 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind; 62 gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb = gap_connect_cfm; 63 gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb = NULL; 64 gap_cb.conn.reg_info.pAMP_ConfigInd_Cb = gap_config_ind; 65 gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb = gap_config_cfm; 66 gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb = gap_disconnect_ind; 67 gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb = NULL; 68 gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb = NULL; 69 gap_cb.conn.reg_info.pAMP_DataInd_Cb = gap_data_ind; 70 gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb = gap_congestion_ind; 71 gap_cb.conn.reg_info.pAMP_TxComplete_Cb = NULL; 72 gap_cb.conn.reg_info.pAMP_MoveInd_Cb = NULL; 73 gap_cb.conn.reg_info.pAMP_MoveRsp_Cb = NULL; 74 gap_cb.conn.reg_info.pAMP_MoveCfm_Cb = NULL; //gap_move_cfm 75 gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb = NULL; //gap_move_cfm_rsp 76 77 #else 78 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; 79 gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm; 80 gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb = NULL; 81 gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind; 82 gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm; 83 gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind; 84 gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL; 85 gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL; 86 gap_cb.conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind; 87 gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind; 88 gap_cb.conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind; 89 #endif 90 } 91 92 93 /******************************************************************************* 94 ** 95 ** Function GAP_ConnOpen 96 ** 97 ** Description This function is called to open an L2CAP connection. 98 ** 99 ** Parameters: is_server - If TRUE, the connection is not created 100 ** but put into a "listen" mode waiting for 101 ** the remote side to connect. 102 ** 103 ** service_id - Unique service ID from 104 ** BTM_SEC_SERVICE_FIRST_EMPTY (6) 105 ** to BTM_SEC_MAX_SERVICE_RECORDS (32) 106 ** 107 ** p_rem_bda - Pointer to remote BD Address. 108 ** If a server, and we don't care about the 109 ** remote BD Address, then NULL should be passed. 110 ** 111 ** psm - the PSM used for the connection 112 ** 113 ** p_config - Optional pointer to configuration structure. 114 ** If NULL, the default GAP configuration will 115 ** be used. 116 ** 117 ** security - security flags 118 ** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM, 119 ** GAP_FCR_CHAN_OPT_STREAM) 120 ** 121 ** p_cb - Pointer to callback function for events. 122 ** 123 ** Returns handle of the connection if successful, else GAP_INVALID_HANDLE 124 ** 125 *******************************************************************************/ 126 UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server, 127 BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg, 128 tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask, 129 tGAP_CONN_CALLBACK *p_cb, tBT_TRANSPORT transport) 130 { 131 tGAP_CCB *p_ccb; 132 UINT16 cid; 133 134 GAP_TRACE_EVENT ("GAP_CONN - Open Request"); 135 136 /* Allocate a new CCB. Return if none available. */ 137 if ((p_ccb = gap_allocate_ccb()) == NULL) 138 return (GAP_INVALID_HANDLE); 139 140 /* update the transport */ 141 p_ccb->transport = transport; 142 143 /* If caller specified a BD address, save it */ 144 if (p_rem_bda) 145 { 146 /* the bd addr is not BT_BD_ANY, then a bd address was specified */ 147 if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN)) 148 p_ccb->rem_addr_specified = TRUE; 149 150 memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN); 151 } 152 else if (!is_server) 153 { 154 /* remore addr is not specified and is not a server -> bad */ 155 return (GAP_INVALID_HANDLE); 156 } 157 158 /* A client MUST have specified a bd addr to connect with */ 159 if (!p_ccb->rem_addr_specified && !is_server) 160 { 161 gap_release_ccb (p_ccb); 162 GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!"); 163 return (GAP_INVALID_HANDLE); 164 } 165 166 /* Check if configuration was specified */ 167 if (p_cfg) 168 p_ccb->cfg = *p_cfg; 169 170 /* Configure L2CAP COC, if transport is LE */ 171 if (transport == BT_TRANSPORT_LE) 172 { 173 p_ccb->local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT; 174 p_ccb->local_coc_cfg.mtu = p_cfg->mtu; 175 p_ccb->local_coc_cfg.mps = L2CAP_LE_DEFAULT_MPS; 176 } 177 178 p_ccb->p_callback = p_cb; 179 180 /* If originator, use a dynamic PSM */ 181 #if AMP_INCLUDED == TRUE 182 if (!is_server) 183 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL; 184 else 185 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind; 186 #else 187 if (!is_server) 188 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL; 189 else 190 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; 191 #endif 192 193 /* Register the PSM with L2CAP */ 194 if (transport == BT_TRANSPORT_BR_EDR) 195 { 196 p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info, 197 AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE); 198 if (p_ccb->psm == 0) 199 { 200 GAP_TRACE_ERROR ("%s: Failure registering PSM 0x%04x", __func__, psm); 201 gap_release_ccb (p_ccb); 202 return (GAP_INVALID_HANDLE); 203 } 204 } 205 206 if (transport == BT_TRANSPORT_LE) 207 { 208 p_ccb->psm = L2CA_REGISTER_COC (psm, &gap_cb.conn.reg_info, 209 AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE); 210 if (p_ccb->psm == 0) 211 { 212 GAP_TRACE_ERROR ("%s: Failure registering PSM 0x%04x", __func__, psm); 213 gap_release_ccb (p_ccb); 214 return (GAP_INVALID_HANDLE); 215 } 216 } 217 218 /* Register with Security Manager for the specific security level */ 219 p_ccb->service_id = service_id; 220 if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name, 221 p_ccb->service_id, security, p_ccb->psm, 0, 0)) 222 { 223 GAP_TRACE_ERROR ("GAP_CONN - Security Error"); 224 gap_release_ccb (p_ccb); 225 return (GAP_INVALID_HANDLE); 226 } 227 228 /* Fill in eL2CAP parameter data */ 229 if( p_ccb->cfg.fcr_present ) 230 { 231 if(ertm_info == NULL) { 232 p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode; 233 p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE; 234 p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE; 235 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE; 236 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE; 237 } else { 238 p_ccb->ertm_info = *ertm_info; 239 } 240 } 241 242 /* optional FCR channel modes */ 243 if(ertm_info != NULL) { 244 p_ccb->ertm_info.allowed_modes = 245 (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC; 246 } 247 248 if (is_server) 249 { 250 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */ 251 p_ccb->con_state = GAP_CCB_STATE_LISTENING; 252 return (p_ccb->gap_handle); 253 } 254 else 255 { 256 /* We are the originator of this connection */ 257 p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG; 258 259 /* Transition to the next appropriate state, waiting for connection confirm. */ 260 p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP; 261 262 /* mark security done flag, when security is not required */ 263 if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0) 264 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 265 266 /* Check if L2CAP started the connection process */ 267 if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR)) 268 { 269 cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info); 270 if (cid != 0) 271 { 272 p_ccb->connection_id = cid; 273 return (p_ccb->gap_handle); 274 } 275 } 276 277 if (p_rem_bda && (transport == BT_TRANSPORT_LE)) 278 { 279 cid = L2CA_CONNECT_COC_REQ (p_ccb->psm, p_rem_bda, &p_ccb->local_coc_cfg); 280 if (cid != 0) 281 { 282 p_ccb->connection_id = cid; 283 return (p_ccb->gap_handle); 284 } 285 } 286 287 gap_release_ccb (p_ccb); 288 return (GAP_INVALID_HANDLE); 289 } 290 } 291 292 293 /******************************************************************************* 294 ** 295 ** Function GAP_ConnClose 296 ** 297 ** Description This function is called to close a connection. 298 ** 299 ** Parameters: handle - Handle of the connection returned by GAP_ConnOpen 300 ** 301 ** Returns BT_PASS - closed OK 302 ** GAP_ERR_BAD_HANDLE - invalid handle 303 ** 304 *******************************************************************************/ 305 UINT16 GAP_ConnClose (UINT16 gap_handle) 306 { 307 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 308 309 GAP_TRACE_EVENT ("GAP_CONN - close handle: 0x%x", gap_handle); 310 311 if (p_ccb) 312 { 313 /* Check if we have a connection ID */ 314 if (p_ccb->con_state != GAP_CCB_STATE_LISTENING) 315 L2CA_DISCONNECT_REQ (p_ccb->connection_id); 316 317 gap_release_ccb (p_ccb); 318 319 return (BT_PASS); 320 } 321 322 return (GAP_ERR_BAD_HANDLE); 323 } 324 325 326 327 /******************************************************************************* 328 ** 329 ** Function GAP_ConnReadData 330 ** 331 ** Description Normally not GKI aware application will call this function 332 ** after receiving GAP_EVT_RXDATA event. 333 ** 334 ** Parameters: handle - Handle of the connection returned in the Open 335 ** p_data - Data area 336 ** max_len - Byte count requested 337 ** p_len - Byte count received 338 ** 339 ** Returns BT_PASS - data read 340 ** GAP_ERR_BAD_HANDLE - invalid handle 341 ** GAP_NO_DATA_AVAIL - no data available 342 ** 343 *******************************************************************************/ 344 UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len) 345 { 346 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 347 UINT16 copy_len; 348 349 if (!p_ccb) 350 return (GAP_ERR_BAD_HANDLE); 351 352 *p_len = 0; 353 354 if (fixed_queue_is_empty(p_ccb->rx_queue)) 355 return (GAP_NO_DATA_AVAIL); 356 357 mutex_global_lock(); 358 359 while (max_len) 360 { 361 BT_HDR *p_buf = fixed_queue_try_peek_first(p_ccb->rx_queue); 362 if (p_buf == NULL) 363 break; 364 365 copy_len = (p_buf->len > max_len)?max_len:p_buf->len; 366 max_len -= copy_len; 367 *p_len += copy_len; 368 if (p_data) 369 { 370 memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len); 371 p_data += copy_len; 372 } 373 374 if (p_buf->len > copy_len) 375 { 376 p_buf->offset += copy_len; 377 p_buf->len -= copy_len; 378 break; 379 } 380 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue)); 381 } 382 383 p_ccb->rx_queue_size -= *p_len; 384 385 mutex_global_unlock(); 386 387 GAP_TRACE_EVENT ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d", 388 p_ccb->rx_queue_size, *p_len); 389 390 return (BT_PASS); 391 } 392 393 /******************************************************************************* 394 ** 395 ** Function GAP_GetRxQueueCnt 396 ** 397 ** Description This function return number of bytes on the rx queue. 398 ** 399 ** Parameters: handle - Handle returned in the GAP_ConnOpen 400 ** p_rx_queue_count - Pointer to return queue count in. 401 ** 402 ** 403 *******************************************************************************/ 404 int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count) 405 { 406 tGAP_CCB *p_ccb; 407 int rc = BT_PASS; 408 409 /* Check that handle is valid */ 410 if (handle < GAP_MAX_CONNECTIONS) 411 { 412 p_ccb = &gap_cb.conn.ccb_pool[handle]; 413 414 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) 415 { 416 *p_rx_queue_count = p_ccb->rx_queue_size; 417 } 418 else 419 rc = GAP_INVALID_HANDLE; 420 } 421 else 422 rc = GAP_INVALID_HANDLE; 423 424 GAP_TRACE_EVENT ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d", 425 rc , *p_rx_queue_count); 426 427 return (rc); 428 } 429 430 /******************************************************************************* 431 ** 432 ** Function GAP_ConnBTRead 433 ** 434 ** Description Bluetooth aware applications will call this function after receiving 435 ** GAP_EVT_RXDATA event. 436 ** 437 ** Parameters: handle - Handle of the connection returned in the Open 438 ** pp_buf - pointer to address of buffer with data, 439 ** 440 ** Returns BT_PASS - data read 441 ** GAP_ERR_BAD_HANDLE - invalid handle 442 ** GAP_NO_DATA_AVAIL - no data available 443 ** 444 *******************************************************************************/ 445 UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf) 446 { 447 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 448 BT_HDR *p_buf; 449 450 if (!p_ccb) 451 return (GAP_ERR_BAD_HANDLE); 452 453 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rx_queue); 454 455 if (p_buf) 456 { 457 *pp_buf = p_buf; 458 459 p_ccb->rx_queue_size -= p_buf->len; 460 return (BT_PASS); 461 } 462 else 463 { 464 *pp_buf = NULL; 465 return (GAP_NO_DATA_AVAIL); 466 } 467 } 468 469 /******************************************************************************* 470 ** 471 ** Function GAP_ConnWriteData 472 ** 473 ** Description Normally not GKI aware application will call this function 474 ** to send data to the connection. 475 ** 476 ** Parameters: handle - Handle of the connection returned in the Open 477 ** p_data - Data area 478 ** max_len - Byte count requested 479 ** p_len - Byte count received 480 ** 481 ** Returns BT_PASS - data read 482 ** GAP_ERR_BAD_HANDLE - invalid handle 483 ** GAP_ERR_BAD_STATE - connection not established 484 ** GAP_CONGESTION - system is congested 485 ** 486 *******************************************************************************/ 487 UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len) 488 { 489 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 490 BT_HDR *p_buf; 491 492 *p_len = 0; 493 494 if (!p_ccb) 495 return (GAP_ERR_BAD_HANDLE); 496 497 if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) 498 return (GAP_ERR_BAD_STATE); 499 500 while (max_len) 501 { 502 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 503 p_buf = (BT_HDR *)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE); 504 else 505 p_buf = (BT_HDR *)osi_malloc(GAP_DATA_BUF_SIZE); 506 507 p_buf->offset = L2CAP_MIN_OFFSET; 508 p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len; 509 p_buf->event = BT_EVT_TO_BTU_SP_DATA; 510 511 memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len); 512 513 *p_len += p_buf->len; 514 max_len -= p_buf->len; 515 p_data += p_buf->len; 516 517 GAP_TRACE_EVENT ("GAP_WriteData %d bytes", p_buf->len); 518 519 fixed_queue_enqueue(p_ccb->tx_queue, p_buf); 520 } 521 522 if (p_ccb->is_congested) 523 { 524 return (BT_PASS); 525 } 526 527 /* Send the buffer through L2CAP */ 528 #if (GAP_CONN_POST_EVT_INCLUDED == TRUE) 529 gap_send_event (gap_handle); 530 #else 531 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) 532 { 533 UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf); 534 535 if (status == L2CAP_DW_CONGESTED) 536 { 537 p_ccb->is_congested = TRUE; 538 break; 539 } 540 else if (status != L2CAP_DW_SUCCESS) 541 return (GAP_ERR_BAD_STATE); 542 } 543 #endif 544 return (BT_PASS); 545 } 546 547 548 /******************************************************************************* 549 ** 550 ** Function GAP_ConnReconfig 551 ** 552 ** Description Applications can call this function to reconfigure the connection. 553 ** 554 ** Parameters: handle - Handle of the connection 555 ** p_cfg - Pointer to new configuration 556 ** 557 ** Returns BT_PASS - config process started 558 ** GAP_ERR_BAD_HANDLE - invalid handle 559 ** 560 *******************************************************************************/ 561 UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg) 562 { 563 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 564 565 if (!p_ccb) 566 return (GAP_ERR_BAD_HANDLE); 567 568 p_ccb->cfg = *p_cfg; 569 570 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) 571 L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg); 572 573 return (BT_PASS); 574 } 575 576 577 578 /******************************************************************************* 579 ** 580 ** Function GAP_ConnSetIdleTimeout 581 ** 582 ** Description Higher layers call this function to set the idle timeout for 583 ** a connection, or for all future connections. The "idle timeout" 584 ** is the amount of time that a connection can remain up with 585 ** no L2CAP channels on it. A timeout of zero means that the 586 ** connection will be torn down immediately when the last channel 587 ** is removed. A timeout of 0xFFFF means no timeout. Values are 588 ** in seconds. 589 ** 590 ** Parameters: handle - Handle of the connection 591 ** timeout - in secs 592 ** 0 = immediate disconnect when last channel is removed 593 ** 0xFFFF = no idle timeout 594 ** 595 ** Returns BT_PASS - config process started 596 ** GAP_ERR_BAD_HANDLE - invalid handle 597 ** 598 *******************************************************************************/ 599 UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout) 600 { 601 tGAP_CCB *p_ccb; 602 603 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) 604 return (GAP_ERR_BAD_HANDLE); 605 606 if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE)) 607 return (BT_PASS); 608 else 609 return (GAP_ERR_BAD_HANDLE); 610 } 611 612 613 614 /******************************************************************************* 615 ** 616 ** Function GAP_ConnGetRemoteAddr 617 ** 618 ** Description This function is called to get the remote BD address 619 ** of a connection. 620 ** 621 ** Parameters: handle - Handle of the connection returned by GAP_ConnOpen 622 ** 623 ** Returns BT_PASS - closed OK 624 ** GAP_ERR_BAD_HANDLE - invalid handle 625 ** 626 *******************************************************************************/ 627 UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle) 628 { 629 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); 630 631 GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle); 632 633 if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) 634 { 635 GAP_TRACE_EVENT("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \ 636 p_ccb->rem_dev_address[0],p_ccb->rem_dev_address[1],p_ccb->rem_dev_address[2], 637 p_ccb->rem_dev_address[3],p_ccb->rem_dev_address[4],p_ccb->rem_dev_address[5]); 638 return (p_ccb->rem_dev_address); 639 } 640 else 641 { 642 GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr return Error "); 643 return (NULL); 644 } 645 } 646 647 648 /******************************************************************************* 649 ** 650 ** Function GAP_ConnGetRemMtuSize 651 ** 652 ** Description Returns the remote device's MTU size 653 ** 654 ** Parameters: handle - Handle of the connection 655 ** 656 ** Returns UINT16 - maximum size buffer that can be transmitted to the peer 657 ** 658 *******************************************************************************/ 659 UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle) 660 { 661 tGAP_CCB *p_ccb; 662 663 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) 664 return (0); 665 666 return (p_ccb->rem_mtu_size); 667 } 668 669 /******************************************************************************* 670 ** 671 ** Function GAP_ConnGetL2CAPCid 672 ** 673 ** Description Returns the L2CAP channel id 674 ** 675 ** Parameters: handle - Handle of the connection 676 ** 677 ** Returns UINT16 - The L2CAP channel id 678 ** 0, if error 679 ** 680 *******************************************************************************/ 681 UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle) 682 { 683 tGAP_CCB *p_ccb; 684 685 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) 686 return (0); 687 688 return (p_ccb->connection_id); 689 } 690 691 /******************************************************************************* 692 ** 693 ** Function gap_tx_connect_ind 694 ** 695 ** Description Sends out GAP_EVT_TX_EMPTY when transmission has been 696 ** completed. 697 ** 698 ** Returns void 699 ** 700 *******************************************************************************/ 701 void gap_tx_complete_ind (UINT16 l2cap_cid, UINT16 sdu_sent) 702 { 703 tGAP_CCB *p_ccb = gap_find_ccb_by_cid (l2cap_cid); 704 if (p_ccb == NULL) 705 return; 706 707 if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) 708 { 709 GAP_TRACE_EVENT("%s: GAP_EVT_TX_EMPTY", __func__); 710 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_TX_EMPTY); 711 } 712 } 713 714 /******************************************************************************* 715 ** 716 ** Function gap_connect_ind 717 ** 718 ** Description This function handles an inbound connection indication 719 ** from L2CAP. This is the case where we are acting as a 720 ** server. 721 ** 722 ** Returns void 723 ** 724 *******************************************************************************/ 725 static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) 726 { 727 UINT16 xx; 728 tGAP_CCB *p_ccb; 729 730 /* See if we have a CCB listening for the connection */ 731 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) 732 { 733 if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) 734 && (p_ccb->psm == psm) 735 && ((p_ccb->rem_addr_specified == FALSE) 736 || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN)))) 737 break; 738 } 739 740 if (xx == GAP_MAX_CONNECTIONS) 741 { 742 GAP_TRACE_WARNING("*******"); 743 GAP_TRACE_WARNING("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting"); 744 GAP_TRACE_WARNING("*******"); 745 746 /* Disconnect because it is an unexpected connection */ 747 L2CA_DISCONNECT_REQ (l2cap_cid); 748 return; 749 } 750 751 /* Transition to the next appropriate state, waiting for config setup. */ 752 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 753 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP; 754 755 /* Save the BD Address and Channel ID. */ 756 memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN); 757 p_ccb->connection_id = l2cap_cid; 758 759 /* Send response to the L2CAP layer. */ 760 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 761 L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info); 762 763 if (p_ccb->transport == BT_TRANSPORT_LE) 764 { 765 L2CA_CONNECT_COC_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->local_coc_cfg); 766 767 /* get the remote coc configuration */ 768 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg); 769 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu; 770 771 /* configuration is not required for LE COC */ 772 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 773 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 774 gap_checks_con_flags (p_ccb); 775 } 776 777 GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id); 778 779 /* Send a Configuration Request. */ 780 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 781 L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg); 782 } 783 784 /******************************************************************************* 785 ** 786 ** Function gap_checks_con_flags 787 ** 788 ** Description This function processes the L2CAP configuration indication 789 ** event. 790 ** 791 ** Returns void 792 ** 793 *******************************************************************************/ 794 static void gap_checks_con_flags (tGAP_CCB *p_ccb) 795 { 796 GAP_TRACE_EVENT ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags); 797 /* if all the required con_flags are set, report the OPEN event now */ 798 if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) 799 { 800 p_ccb->con_state = GAP_CCB_STATE_CONNECTED; 801 802 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED); 803 } 804 } 805 806 /******************************************************************************* 807 ** 808 ** Function gap_sec_check_complete 809 ** 810 ** Description The function called when Security Manager finishes 811 ** verification of the service side connection 812 ** 813 ** Returns void 814 ** 815 *******************************************************************************/ 816 static void gap_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res) 817 { 818 tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data; 819 UNUSED(bd_addr); 820 UNUSED (transport); 821 822 GAP_TRACE_EVENT ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d", 823 p_ccb->con_state, p_ccb->con_flags, res); 824 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) 825 return; 826 827 if (res == BTM_SUCCESS) 828 { 829 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 830 gap_checks_con_flags (p_ccb); 831 } 832 else 833 { 834 /* security failed - disconnect the channel */ 835 L2CA_DISCONNECT_REQ (p_ccb->connection_id); 836 } 837 } 838 839 /******************************************************************************* 840 ** 841 ** Function gap_connect_cfm 842 ** 843 ** Description This function handles the connect confirm events 844 ** from L2CAP. This is the case when we are acting as a 845 ** client and have sent a connect request. 846 ** 847 ** Returns void 848 ** 849 *******************************************************************************/ 850 static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result) 851 { 852 tGAP_CCB *p_ccb; 853 854 /* Find CCB based on CID */ 855 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) 856 return; 857 858 /* initiate security process, if needed */ 859 if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 && p_ccb->transport != BT_TRANSPORT_LE) 860 { 861 btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE, 862 0, 0, &gap_sec_check_complete, p_ccb); 863 } 864 865 /* If the connection response contains success status, then */ 866 /* Transition to the next state and startup the timer. */ 867 if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) 868 { 869 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 870 { 871 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP; 872 873 /* Send a Configuration Request. */ 874 L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg); 875 } 876 877 if (p_ccb->transport == BT_TRANSPORT_LE) 878 { 879 /* get the remote coc configuration */ 880 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg); 881 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu; 882 883 /* configuration is not required for LE COC */ 884 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 885 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 886 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 887 gap_checks_con_flags (p_ccb); 888 } 889 } 890 else 891 { 892 /* Tell the user if he has a callback */ 893 if (p_ccb->p_callback) 894 (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 895 896 gap_release_ccb (p_ccb); 897 } 898 } 899 900 /******************************************************************************* 901 ** 902 ** Function gap_config_ind 903 ** 904 ** Description This function processes the L2CAP configuration indication 905 ** event. 906 ** 907 ** Returns void 908 ** 909 *******************************************************************************/ 910 static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 911 { 912 tGAP_CCB *p_ccb; 913 UINT16 local_mtu_size; 914 915 /* Find CCB based on CID */ 916 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) 917 return; 918 919 /* Remember the remote MTU size */ 920 921 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 922 { 923 local_mtu_size = p_ccb->ertm_info.user_tx_buf_size 924 - sizeof(BT_HDR) - L2CAP_MIN_OFFSET; 925 } 926 else 927 local_mtu_size = L2CAP_MTU_SIZE; 928 929 if ((!p_cfg->mtu_present)||(p_cfg->mtu > local_mtu_size)) 930 { 931 p_ccb->rem_mtu_size = local_mtu_size; 932 } 933 else 934 p_ccb->rem_mtu_size = p_cfg->mtu; 935 936 /* For now, always accept configuration from the other side */ 937 p_cfg->flush_to_present = FALSE; 938 p_cfg->mtu_present = FALSE; 939 p_cfg->result = L2CAP_CFG_OK; 940 p_cfg->fcs_present = FALSE; 941 942 L2CA_CONFIG_RSP (l2cap_cid, p_cfg); 943 944 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 945 946 gap_checks_con_flags (p_ccb); 947 } 948 949 950 /******************************************************************************* 951 ** 952 ** Function gap_config_cfm 953 ** 954 ** Description This function processes the L2CAP configuration confirmation 955 ** event. 956 ** 957 ** Returns void 958 ** 959 *******************************************************************************/ 960 static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 961 { 962 tGAP_CCB *p_ccb; 963 964 /* Find CCB based on CID */ 965 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) 966 return; 967 968 if (p_cfg->result == L2CAP_CFG_OK) 969 { 970 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 971 972 973 if (p_ccb->cfg.fcr_present) 974 p_ccb->cfg.fcr.mode = p_cfg->fcr.mode; 975 else 976 p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 977 978 gap_checks_con_flags (p_ccb); 979 } 980 else 981 { 982 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 983 gap_release_ccb (p_ccb); 984 } 985 } 986 987 988 /******************************************************************************* 989 ** 990 ** Function gap_disconnect_ind 991 ** 992 ** Description This function handles a disconnect event from L2CAP. If 993 ** requested to, we ack the disconnect before dropping the CCB 994 ** 995 ** Returns void 996 ** 997 *******************************************************************************/ 998 static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) 999 { 1000 tGAP_CCB *p_ccb; 1001 1002 GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); 1003 1004 /* Find CCB based on CID */ 1005 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) 1006 return; 1007 1008 if (ack_needed) 1009 L2CA_DISCONNECT_RSP (l2cap_cid); 1010 1011 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 1012 gap_release_ccb (p_ccb); 1013 } 1014 1015 1016 /******************************************************************************* 1017 ** 1018 ** Function gap_data_ind 1019 ** 1020 ** Description This function is called when data is received from L2CAP. 1021 ** 1022 ** Returns void 1023 ** 1024 *******************************************************************************/ 1025 static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) 1026 { 1027 tGAP_CCB *p_ccb; 1028 1029 /* Find CCB based on CID */ 1030 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) 1031 { 1032 osi_free(p_msg); 1033 return; 1034 } 1035 1036 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) 1037 { 1038 fixed_queue_enqueue(p_ccb->rx_queue, p_msg); 1039 1040 p_ccb->rx_queue_size += p_msg->len; 1041 /* 1042 GAP_TRACE_EVENT ("gap_data_ind - rx_queue_size=%d, msg len=%d", 1043 p_ccb->rx_queue_size, p_msg->len); 1044 */ 1045 1046 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL); 1047 } 1048 else 1049 { 1050 osi_free(p_msg); 1051 } 1052 } 1053 1054 1055 /******************************************************************************* 1056 ** 1057 ** Function gap_congestion_ind 1058 ** 1059 ** Description This is a callback function called by L2CAP when 1060 ** data L2CAP congestion status changes 1061 ** 1062 *******************************************************************************/ 1063 static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested) 1064 { 1065 tGAP_CCB *p_ccb; 1066 UINT16 event; 1067 BT_HDR *p_buf; 1068 UINT8 status; 1069 1070 GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x", 1071 is_congested, lcid); 1072 1073 /* Find CCB based on CID */ 1074 if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL) 1075 return; 1076 1077 p_ccb->is_congested = is_congested; 1078 1079 event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED; 1080 p_ccb->p_callback (p_ccb->gap_handle, event); 1081 1082 if (!is_congested) 1083 { 1084 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) 1085 { 1086 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf); 1087 1088 if (status == L2CAP_DW_CONGESTED) 1089 { 1090 p_ccb->is_congested = TRUE; 1091 break; 1092 } 1093 else if (status != L2CAP_DW_SUCCESS) 1094 break; 1095 } 1096 } 1097 } 1098 1099 1100 /******************************************************************************* 1101 ** 1102 ** Function gap_find_ccb_by_cid 1103 ** 1104 ** Description This function searches the CCB table for an entry with the 1105 ** passed CID. 1106 ** 1107 ** Returns the CCB address, or NULL if not found. 1108 ** 1109 *******************************************************************************/ 1110 static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid) 1111 { 1112 UINT16 xx; 1113 tGAP_CCB *p_ccb; 1114 1115 /* Look through each connection control block */ 1116 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) 1117 { 1118 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid)) 1119 return (p_ccb); 1120 } 1121 1122 /* If here, not found */ 1123 return (NULL); 1124 } 1125 1126 1127 /******************************************************************************* 1128 ** 1129 ** Function gap_find_ccb_by_handle 1130 ** 1131 ** Description This function searches the CCB table for an entry with the 1132 ** passed handle. 1133 ** 1134 ** Returns the CCB address, or NULL if not found. 1135 ** 1136 *******************************************************************************/ 1137 static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle) 1138 { 1139 tGAP_CCB *p_ccb; 1140 1141 /* Check that handle is valid */ 1142 if (handle < GAP_MAX_CONNECTIONS) 1143 { 1144 p_ccb = &gap_cb.conn.ccb_pool[handle]; 1145 1146 if (p_ccb->con_state != GAP_CCB_STATE_IDLE) 1147 return (p_ccb); 1148 } 1149 1150 /* If here, handle points to invalid connection */ 1151 return (NULL); 1152 } 1153 1154 1155 /******************************************************************************* 1156 ** 1157 ** Function gap_allocate_ccb 1158 ** 1159 ** Description This function allocates a new CCB. 1160 ** 1161 ** Returns CCB address, or NULL if none available. 1162 ** 1163 *******************************************************************************/ 1164 static tGAP_CCB *gap_allocate_ccb (void) 1165 { 1166 UINT16 xx; 1167 tGAP_CCB *p_ccb; 1168 1169 /* Look through each connection control block for a free one */ 1170 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) 1171 { 1172 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) 1173 { 1174 memset (p_ccb, 0, sizeof (tGAP_CCB)); 1175 p_ccb->tx_queue = fixed_queue_new(SIZE_MAX); 1176 p_ccb->rx_queue = fixed_queue_new(SIZE_MAX); 1177 1178 p_ccb->gap_handle = xx; 1179 p_ccb->rem_mtu_size = L2CAP_MTU_SIZE; 1180 1181 return (p_ccb); 1182 } 1183 } 1184 1185 /* If here, no free CCB found */ 1186 return (NULL); 1187 } 1188 1189 1190 /******************************************************************************* 1191 ** 1192 ** Function gap_release_ccb 1193 ** 1194 ** Description This function releases a CCB. 1195 ** 1196 ** Returns void 1197 ** 1198 *******************************************************************************/ 1199 static void gap_release_ccb (tGAP_CCB *p_ccb) 1200 { 1201 UINT16 xx; 1202 UINT16 psm = p_ccb->psm; 1203 UINT8 service_id = p_ccb->service_id; 1204 1205 /* Drop any buffers we may be holding */ 1206 p_ccb->rx_queue_size = 0; 1207 1208 while (!fixed_queue_is_empty(p_ccb->rx_queue)) 1209 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue)); 1210 fixed_queue_free(p_ccb->rx_queue, NULL); 1211 p_ccb->rx_queue = NULL; 1212 1213 while (!fixed_queue_is_empty(p_ccb->tx_queue)) 1214 osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue)); 1215 fixed_queue_free(p_ccb->tx_queue, NULL); 1216 p_ccb->tx_queue = NULL; 1217 1218 p_ccb->con_state = GAP_CCB_STATE_IDLE; 1219 1220 /* If no-one else is using the PSM, deregister from L2CAP */ 1221 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) 1222 { 1223 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm)) 1224 return; 1225 } 1226 1227 /* Free the security record for this PSM */ 1228 BTM_SecClrService(service_id); 1229 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 1230 L2CA_DEREGISTER (psm); 1231 1232 if(p_ccb->transport == BT_TRANSPORT_LE) 1233 L2CA_DEREGISTER_COC (psm); 1234 } 1235 1236 #if (GAP_CONN_POST_EVT_INCLUDED == TRUE) 1237 1238 /******************************************************************************* 1239 ** 1240 ** Function gap_send_event 1241 ** 1242 ** Description Send BT_EVT_TO_GAP_MSG event to BTU task 1243 ** 1244 ** Returns None 1245 ** 1246 *******************************************************************************/ 1247 void gap_send_event (UINT16 gap_handle) 1248 { 1249 BT_HDR *p_msg = (BT_HDR *)osi_malloc(BT_HDR_SIZE); 1250 1251 p_msg->event = BT_EVT_TO_GAP_MSG; 1252 p_msg->len = 0; 1253 p_msg->offset = 0; 1254 p_msg->layer_specific = gap_handle; 1255 1256 GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg); 1257 } 1258 1259 #endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */ 1260 #endif /* GAP_CONN_INCLUDED */ 1261