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