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