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