Home | History | Annotate | Download | only in l2cap
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 1999-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains the L2CAP channel state machine
     22  *
     23  ******************************************************************************/
     24 
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <stdio.h>
     28 
     29 #include "bt_target.h"
     30 #include "bt_common.h"
     31 #include "hcidefs.h"
     32 #include "hcimsgs.h"
     33 #include "l2cdefs.h"
     34 #include "l2c_int.h"
     35 #include "btm_int.h"
     36 #include "btu.h"
     37 #include "hcimsgs.h"
     38 
     39 
     40 extern fixed_queue_t *btu_general_alarm_queue;
     41 
     42 /********************************************************************************/
     43 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
     44 /********************************************************************************/
     45 static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     46 static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     47 static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     48 static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     49 static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     50 static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     51 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     52 static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     53 static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
     54 
     55 #if (BT_TRACE_VERBOSE == TRUE)
     56 static char *l2c_csm_get_event_name (UINT16 event);
     57 #endif
     58 
     59 /*******************************************************************************
     60 **
     61 ** Function         l2c_csm_execute
     62 **
     63 ** Description      This function executes the state machine.
     64 **
     65 ** Returns          void
     66 **
     67 *******************************************************************************/
     68 void l2c_csm_execute (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
     69 {
     70     switch (p_ccb->chnl_state)
     71     {
     72     case CST_CLOSED:
     73         l2c_csm_closed (p_ccb, event, p_data);
     74         break;
     75 
     76     case CST_ORIG_W4_SEC_COMP:
     77         l2c_csm_orig_w4_sec_comp (p_ccb, event, p_data);
     78         break;
     79 
     80     case CST_TERM_W4_SEC_COMP:
     81         l2c_csm_term_w4_sec_comp (p_ccb, event, p_data);
     82         break;
     83 
     84     case CST_W4_L2CAP_CONNECT_RSP:
     85         l2c_csm_w4_l2cap_connect_rsp (p_ccb, event, p_data);
     86         break;
     87 
     88     case CST_W4_L2CA_CONNECT_RSP:
     89         l2c_csm_w4_l2ca_connect_rsp (p_ccb, event, p_data);
     90         break;
     91 
     92     case CST_CONFIG:
     93         l2c_csm_config (p_ccb, event, p_data);
     94         break;
     95 
     96     case CST_OPEN:
     97         l2c_csm_open (p_ccb, event, p_data);
     98         break;
     99 
    100     case CST_W4_L2CAP_DISCONNECT_RSP:
    101         l2c_csm_w4_l2cap_disconnect_rsp (p_ccb, event, p_data);
    102         break;
    103 
    104     case CST_W4_L2CA_DISCONNECT_RSP:
    105         l2c_csm_w4_l2ca_disconnect_rsp (p_ccb, event, p_data);
    106         break;
    107 
    108     default:
    109         L2CAP_TRACE_DEBUG("Unhandled event! event = %d",event);
    110         break;
    111     }
    112 }
    113 
    114 /*******************************************************************************
    115 **
    116 ** Function         l2c_csm_closed
    117 **
    118 ** Description      This function handles events when the channel is in
    119 **                  CLOSED state. This state exists only when the link is
    120 **                  being initially established.
    121 **
    122 ** Returns          void
    123 **
    124 *******************************************************************************/
    125 static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    126 {
    127     tL2C_CONN_INFO          *p_ci = (tL2C_CONN_INFO *)p_data;
    128     UINT16                  local_cid = p_ccb->local_cid;
    129     tL2CA_DISCONNECT_IND_CB *disconnect_ind;
    130     tL2CA_CONNECT_CFM_CB    *connect_cfm;
    131 
    132     if (p_ccb->p_rcb == NULL)
    133     {
    134 #if (BT_TRACE_VERBOSE == TRUE)
    135         L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x  st: CLOSED  evt: %s p_rcb == NULL", p_ccb->local_cid, l2c_csm_get_event_name (event));
    136 #else
    137         L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x  st: CLOSED  evt: 0x%04x p_rcb == NULL", p_ccb->local_cid, event);
    138 #endif
    139         return;
    140     }
    141 
    142 #if (L2CAP_UCD_INCLUDED == TRUE)
    143     if ( local_cid == L2CAP_CONNECTIONLESS_CID )
    144     {
    145         /* check if this event can be processed by UCD */
    146         if ( l2c_ucd_process_event (p_ccb, event, p_data) )
    147         {
    148             /* The event is processed by UCD state machine */
    149             return;
    150         }
    151     }
    152 #endif
    153 
    154     disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
    155     connect_cfm    = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
    156 
    157 #if (BT_TRACE_VERBOSE == TRUE)
    158     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: CLOSED  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    159 #else
    160     L2CAP_TRACE_EVENT ("L2CAP - st: CLOSED evt: %d", event);
    161 #endif
    162 
    163     switch (event)
    164     {
    165     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    166         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    167         l2cu_release_ccb (p_ccb);
    168         (*disconnect_ind)(local_cid, FALSE);
    169         break;
    170 
    171     case L2CEVT_LP_CONNECT_CFM:                         /* Link came up         */
    172         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    173         {
    174             p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
    175             l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, TRUE,
    176                     &l2c_link_sec_comp, p_ccb);
    177         }
    178         else
    179         {
    180             p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
    181             btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
    182                                       p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb);
    183         }
    184         break;
    185 
    186     case L2CEVT_LP_CONNECT_CFM_NEG:                     /* Link failed          */
    187         /* Disconnect unless ACL collision and upper layer wants to handle it */
    188         if (p_ci->status != HCI_ERR_CONNECTION_EXISTS
    189             || !btm_acl_notif_conn_collision(p_ccb->p_lcb->remote_bd_addr))
    190         {
    191             L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x  Status: %d", p_ccb->local_cid, p_ci->status);
    192             l2cu_release_ccb (p_ccb);
    193             (*connect_cfm)(local_cid, p_ci->status);
    194         }
    195         break;
    196 
    197     case L2CEVT_L2CA_CONNECT_REQ:                       /* API connect request  */
    198         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    199         {
    200             p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
    201             l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, TRUE,
    202                     &l2c_link_sec_comp, p_ccb);
    203         }
    204         else
    205         {
    206             /* Cancel sniff mode if needed */
    207             {
    208                 tBTM_PM_PWR_MD settings;
    209                 memset((void*)&settings, 0, sizeof(settings));
    210                 settings.mode = BTM_PM_MD_ACTIVE;
    211 /* COVERITY
    212 Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
    213 Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
    214 Event uninit_use_in_call: Using uninitialized value "settings.min" in call to function "BTM_SetPowerMode"
    215 // FALSE-POSITIVE error from Coverity test-tool. Please do NOT remove following comment.
    216 // coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode the other data members of tBTM_PM_PWR_MD are ignored
    217 */
    218                 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
    219             }
    220 
    221             /* If sec access does not result in started SEC_COM or COMP_NEG are already processed */
    222             if (btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
    223                                           p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb) == BTM_CMD_STARTED)
    224                 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
    225         }
    226         break;
    227 
    228     case L2CEVT_SEC_COMP:
    229         p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
    230 
    231         /* Wait for the info resp in this state before sending connect req (if needed) */
    232         if (!p_ccb->p_lcb->w4_info_rsp)
    233         {
    234             /* Need to have at least one compatible channel to continue */
    235             if (!l2c_fcr_chk_chan_modes(p_ccb))
    236             {
    237                 l2cu_release_ccb (p_ccb);
    238                 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_NO_LINK);
    239             }
    240             else
    241             {
    242                 l2cu_send_peer_connect_req (p_ccb);
    243                 alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    244                                    L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    245                                    l2c_ccb_timer_timeout, p_ccb,
    246                                    btu_general_alarm_queue);
    247             }
    248         }
    249         break;
    250 
    251     case L2CEVT_SEC_COMP_NEG:                           /* something is really bad with security */
    252         L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x  Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
    253         l2cu_release_ccb (p_ccb);
    254         (*connect_cfm)(local_cid, L2CAP_CONN_SECURITY_BLOCK);
    255         break;
    256 
    257     case L2CEVT_L2CAP_CONNECT_REQ:                      /* Peer connect request */
    258         /* stop link timer to avoid race condition between A2MP, Security, and L2CAP */
    259         alarm_cancel(p_ccb->p_lcb->l2c_lcb_timer);
    260 
    261         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    262         {
    263             p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
    264              l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, FALSE,
    265                     &l2c_link_sec_comp, p_ccb);
    266         }
    267         else
    268         {
    269             /* Cancel sniff mode if needed */
    270             {
    271                 tBTM_PM_PWR_MD settings;
    272                 memset((void*)&settings, 0, sizeof(settings));
    273                 settings.mode = BTM_PM_MD_ACTIVE;
    274 /* COVERITY
    275 Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
    276 Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
    277 Event uninit_use_in_call: Using uninitialized value "settings.min" in call to function "BTM_SetPowerMode"
    278 // FALSE-POSITIVE error from Coverity test-tool. Please do NOT remove following comment.
    279 // coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode the other data members of tBTM_PM_PWR_MD are ignored
    280 */
    281                 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
    282             }
    283 
    284             p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
    285             if (btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
    286                                       p_ccb->p_lcb->handle, FALSE, &l2c_link_sec_comp, p_ccb) == BTM_CMD_STARTED)
    287             {
    288                 /* started the security process, tell the peer to set a longer timer */
    289                 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
    290             }
    291         }
    292         break;
    293 
    294     case L2CEVT_TIMEOUT:
    295         L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x  Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
    296         l2cu_release_ccb (p_ccb);
    297         (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
    298         break;
    299 
    300     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
    301     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
    302         osi_free(p_data);
    303         break;
    304 
    305     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
    306         l2cu_release_ccb (p_ccb);
    307         break;
    308 
    309     case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
    310     case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
    311         osi_free(p_data);
    312         break;
    313     }
    314 }
    315 
    316 
    317 /*******************************************************************************
    318 **
    319 ** Function         l2c_csm_orig_w4_sec_comp
    320 **
    321 ** Description      This function handles events when the channel is in
    322 **                  CST_ORIG_W4_SEC_COMP state.
    323 **
    324 ** Returns          void
    325 **
    326 *******************************************************************************/
    327 static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    328 {
    329     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
    330     tL2CA_CONNECT_CFM_CB    *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
    331     UINT16                  local_cid = p_ccb->local_cid;
    332 
    333 #if (BT_TRACE_VERBOSE == TRUE)
    334     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: ORIG_W4_SEC_COMP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    335 #else
    336     L2CAP_TRACE_EVENT ("L2CAP - st: ORIG_W4_SEC_COMP evt: %d", event);
    337 #endif
    338 
    339 #if (L2CAP_UCD_INCLUDED == TRUE)
    340     if ( local_cid == L2CAP_CONNECTIONLESS_CID )
    341     {
    342         /* check if this event can be processed by UCD */
    343         if ( l2c_ucd_process_event (p_ccb, event, p_data) )
    344         {
    345             /* The event is processed by UCD state machine */
    346             return;
    347         }
    348     }
    349 #endif
    350 
    351     switch (event)
    352     {
    353     case L2CEVT_LP_DISCONNECT_IND:                   /* Link was disconnected */
    354         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    355         l2cu_release_ccb (p_ccb);
    356         (*disconnect_ind)(local_cid, FALSE);
    357         break;
    358 
    359     case L2CEVT_SEC_RE_SEND_CMD:                    /* BTM has enough info to proceed */
    360     case L2CEVT_LP_CONNECT_CFM:                     /* Link came up         */
    361         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    362         {
    363              l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, FALSE,
    364                     &l2c_link_sec_comp, p_ccb);
    365         }
    366         else
    367         {
    368             btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
    369                                   p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb);
    370         }
    371         break;
    372 
    373     case L2CEVT_SEC_COMP:                            /* Security completed success */
    374         /* Wait for the info resp in this state before sending connect req (if needed) */
    375         p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
    376         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    377         {
    378             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    379                                L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    380                                l2c_ccb_timer_timeout, p_ccb,
    381                                btu_general_alarm_queue);
    382             l2cble_credit_based_conn_req (p_ccb);          /* Start Connection     */
    383         }
    384         else
    385         {
    386             if (!p_ccb->p_lcb->w4_info_rsp)
    387             {
    388                 /* Need to have at least one compatible channel to continue */
    389                 if (!l2c_fcr_chk_chan_modes(p_ccb))
    390                 {
    391                     l2cu_release_ccb (p_ccb);
    392                     (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
    393                 }
    394                 else
    395                 {
    396                     alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    397                                        L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    398                                        l2c_ccb_timer_timeout, p_ccb,
    399                                        btu_general_alarm_queue);
    400                     l2cu_send_peer_connect_req (p_ccb);          /* Start Connection     */
    401                 }
    402             }
    403         }
    404         break;
    405 
    406     case L2CEVT_SEC_COMP_NEG:
    407         L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x  Status: %d", p_ccb->local_cid, HCI_ERR_AUTH_FAILURE);
    408 
    409         /* If last channel immediately disconnect the ACL for better security.
    410            Also prevents a race condition between BTM and L2CAP */
    411         if ( (p_ccb == p_ccb->p_lcb->ccb_queue.p_first_ccb) && (p_ccb == p_ccb->p_lcb->ccb_queue.p_last_ccb) )
    412         {
    413             p_ccb->p_lcb->idle_timeout = 0;
    414         }
    415 
    416         l2cu_release_ccb (p_ccb);
    417         (*connect_cfm)(local_cid, HCI_ERR_AUTH_FAILURE);
    418         break;
    419 
    420     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
    421     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
    422         osi_free(p_data);
    423         break;
    424 
    425     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
    426         /* Tell security manager to abort */
    427         btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
    428 
    429         l2cu_release_ccb (p_ccb);
    430         break;
    431     }
    432 }
    433 
    434 
    435 /*******************************************************************************
    436 **
    437 ** Function         l2c_csm_term_w4_sec_comp
    438 **
    439 ** Description      This function handles events when the channel is in
    440 **                  CST_TERM_W4_SEC_COMP state.
    441 **
    442 ** Returns          void
    443 **
    444 *******************************************************************************/
    445 static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    446 {
    447 #if (BT_TRACE_VERBOSE == TRUE)
    448     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: TERM_W4_SEC_COMP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    449 #else
    450     L2CAP_TRACE_EVENT ("L2CAP - st: TERM_W4_SEC_COMP evt: %d", event);
    451 #endif
    452 
    453 #if (L2CAP_UCD_INCLUDED == TRUE)
    454     if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )
    455     {
    456         /* check if this event can be processed by UCD */
    457         if ( l2c_ucd_process_event (p_ccb, event, p_data) )
    458         {
    459             /* The event is processed by UCD state machine */
    460             return;
    461         }
    462     }
    463 #endif
    464 
    465     switch (event)
    466     {
    467     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    468         /* Tell security manager to abort */
    469         btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
    470 
    471         l2cu_release_ccb (p_ccb);
    472         break;
    473 
    474     case L2CEVT_SEC_COMP:
    475         p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP;
    476 
    477         /* Wait for the info resp in next state before sending connect ind (if needed) */
    478         if (!p_ccb->p_lcb->w4_info_rsp)
    479         {
    480             /* Don't need to get info from peer or already retrieved so continue */
    481             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    482                                L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    483                                l2c_ccb_timer_timeout, p_ccb,
    484                                btu_general_alarm_queue);
    485             L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
    486 
    487             (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb) (p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid,
    488                                                       p_ccb->p_rcb->psm, p_ccb->remote_id);
    489         }
    490         else
    491         {
    492             /*
    493             ** L2CAP Connect Response will be sent out by 3 sec timer expiration
    494             ** because Bluesoleil doesn't respond to L2CAP Information Request.
    495             ** Bluesoleil seems to disconnect ACL link as failure case, because
    496             ** it takes too long (4~7secs) to get response.
    497             ** product version : Bluesoleil 2.1.1.0 EDR Release 060123
    498             ** stack version   : 05.04.11.20060119
    499             */
    500 
    501             /* Waiting for the info resp, tell the peer to set a longer timer */
    502             l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
    503         }
    504         break;
    505 
    506     case L2CEVT_SEC_COMP_NEG:
    507         if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK)
    508         {
    509             /* start a timer - encryption change not received before L2CAP connect req */
    510             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    511                                L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS,
    512                                l2c_ccb_timer_timeout, p_ccb,
    513                                btu_general_alarm_queue);
    514         }
    515         else
    516         {
    517             if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    518                 l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id, L2CAP_LE_INSUFFICIENT_AUTHENTICATION);
    519             else
    520                 l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
    521             l2cu_release_ccb (p_ccb);
    522         }
    523         break;
    524 
    525     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
    526     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
    527         osi_free(p_data);
    528         break;
    529 
    530     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
    531         l2cu_release_ccb (p_ccb);
    532         break;
    533 
    534     case L2CEVT_L2CAP_DISCONNECT_REQ:                  /* Peer disconnected request */
    535         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
    536 
    537         /* Tell security manager to abort */
    538         btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
    539 
    540         l2cu_release_ccb (p_ccb);
    541         break;
    542 
    543     case L2CEVT_TIMEOUT:
    544         /* SM4 related. */
    545         if (!btsnd_hcic_disconnect (p_ccb->p_lcb->handle, HCI_ERR_AUTH_FAILURE))
    546         {
    547             L2CAP_TRACE_API ("L2CAP - Calling btsnd_hcic_disconnect for handle %i failed", p_ccb->p_lcb->handle);
    548             alarm_set_on_queue(p_ccb->l2c_ccb_timer, BT_1SEC_TIMEOUT_MS,
    549                                l2c_ccb_timer_timeout, p_ccb,
    550                                btu_general_alarm_queue);
    551         }
    552         break;
    553 
    554     case L2CEVT_SEC_RE_SEND_CMD:                    /* BTM has enough info to proceed */
    555         btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
    556                                   p_ccb->p_lcb->handle, FALSE, &l2c_link_sec_comp, p_ccb);
    557         break;
    558     }
    559 }
    560 
    561 
    562 /*******************************************************************************
    563 **
    564 ** Function         l2c_csm_w4_l2cap_connect_rsp
    565 **
    566 ** Description      This function handles events when the channel is in
    567 **                  CST_W4_L2CAP_CONNECT_RSP state.
    568 **
    569 ** Returns          void
    570 **
    571 *******************************************************************************/
    572 static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    573 {
    574     tL2C_CONN_INFO          *p_ci = (tL2C_CONN_INFO *)p_data;
    575     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
    576     tL2CA_CONNECT_CFM_CB    *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
    577     UINT16                  local_cid = p_ccb->local_cid;
    578 
    579 #if (BT_TRACE_VERBOSE == TRUE)
    580     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CAP_CON_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    581 #else
    582     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_CON_RSP evt: %d", event);
    583 #endif
    584 
    585     switch (event)
    586     {
    587     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    588         /* Send disc indication unless peer to peer race condition AND normal disconnect */
    589         /* *((UINT8 *)p_data) != HCI_ERR_PEER_USER happens when peer device try to disconnect for normal reason */
    590         p_ccb->chnl_state = CST_CLOSED;
    591         if ((p_ccb->flags & CCB_FLAG_NO_RETRY) || !p_data || (*((UINT8 *)p_data) != HCI_ERR_PEER_USER))
    592         {
    593             L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed",
    594                               p_ccb->local_cid);
    595             l2cu_release_ccb (p_ccb);
    596             (*disconnect_ind)(local_cid, FALSE);
    597         }
    598         p_ccb->flags |= CCB_FLAG_NO_RETRY;
    599         break;
    600 
    601     case L2CEVT_L2CAP_CONNECT_RSP:                  /* Got peer connect confirm */
    602         p_ccb->remote_cid = p_ci->remote_cid;
    603         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    604         {
    605             /* Connection is completed */
    606             alarm_cancel(p_ccb->l2c_ccb_timer);
    607             p_ccb->chnl_state = CST_OPEN;
    608         }
    609         else
    610         {
    611             p_ccb->chnl_state = CST_CONFIG;
    612             alarm_set_on_queue(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
    613                                l2c_ccb_timer_timeout, p_ccb,
    614                                btu_general_alarm_queue);
    615         }
    616         L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Success", p_ccb->local_cid);
    617 
    618         (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_OK);
    619         break;
    620 
    621     case L2CEVT_L2CAP_CONNECT_RSP_PND:              /* Got peer connect pending */
    622         p_ccb->remote_cid = p_ci->remote_cid;
    623         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    624                            L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
    625                            l2c_ccb_timer_timeout, p_ccb,
    626                            btu_general_alarm_queue);
    627         if (p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb)
    628         {
    629             L2CAP_TRACE_API ("L2CAP - Calling Connect_Pnd_Cb(), CID: 0x%04x", p_ccb->local_cid);
    630             (*p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb)(p_ccb->local_cid);
    631         }
    632         break;
    633 
    634     case L2CEVT_L2CAP_CONNECT_RSP_NEG:              /* Peer rejected connection */
    635         L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Failure Code: %d", p_ccb->local_cid, p_ci->l2cap_result);
    636         l2cu_release_ccb (p_ccb);
    637         (*connect_cfm)(local_cid, p_ci->l2cap_result);
    638         break;
    639 
    640     case L2CEVT_TIMEOUT:
    641         L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Timeout", p_ccb->local_cid);
    642         l2cu_release_ccb (p_ccb);
    643         (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
    644         break;
    645 
    646     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
    647         /* If we know peer CID from connect pending, we can send disconnect */
    648         if (p_ccb->remote_cid != 0)
    649         {
    650             l2cu_send_peer_disc_req (p_ccb);
    651             p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
    652             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    653                                L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
    654                                l2c_ccb_timer_timeout, p_ccb,
    655                                btu_general_alarm_queue);
    656         }
    657         else
    658             l2cu_release_ccb (p_ccb);
    659         break;
    660 
    661     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
    662     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
    663         osi_free(p_data);
    664         break;
    665 
    666     case L2CEVT_L2CAP_INFO_RSP:
    667         /* Need to have at least one compatible channel to continue */
    668         if (!l2c_fcr_chk_chan_modes(p_ccb))
    669         {
    670             l2cu_release_ccb (p_ccb);
    671             (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
    672         }
    673         else
    674         {
    675             /* We have feature info, so now send peer connect request */
    676             alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    677                                L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    678                                l2c_ccb_timer_timeout, p_ccb,
    679                                btu_general_alarm_queue);
    680             l2cu_send_peer_connect_req (p_ccb);          /* Start Connection     */
    681         }
    682         break;
    683 
    684     case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
    685     case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
    686         osi_free(p_data);
    687         break;
    688     }
    689 }
    690 
    691 
    692 /*******************************************************************************
    693 **
    694 ** Function         l2c_csm_w4_l2ca_connect_rsp
    695 **
    696 ** Description      This function handles events when the channel is in
    697 **                  CST_W4_L2CA_CONNECT_RSP state.
    698 **
    699 ** Returns          void
    700 **
    701 *******************************************************************************/
    702 static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    703 {
    704     tL2C_CONN_INFO          *p_ci;
    705     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
    706     UINT16                  local_cid = p_ccb->local_cid;
    707 
    708 #if (BT_TRACE_VERBOSE == TRUE)
    709     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CA_CON_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    710 #else
    711     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_CON_RSP evt: %d", event);
    712 #endif
    713 
    714     switch (event)
    715     {
    716     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    717         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    718         l2cu_release_ccb (p_ccb);
    719         (*disconnect_ind)(local_cid, FALSE);
    720         break;
    721 
    722     case L2CEVT_L2CA_CONNECT_RSP:
    723         p_ci = (tL2C_CONN_INFO *)p_data;
    724         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    725         {
    726             /* Result should be OK or Reject */
    727             if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK))
    728             {
    729                 l2cble_credit_based_conn_res (p_ccb, L2CAP_CONN_OK);
    730                 p_ccb->chnl_state = CST_OPEN;
    731                 alarm_cancel(p_ccb->l2c_ccb_timer);
    732             }
    733             else
    734             {
    735                 l2cble_credit_based_conn_res (p_ccb, p_ci->l2cap_result);
    736                 l2cu_release_ccb (p_ccb);
    737             }
    738         }
    739         else
    740         {
    741             /* Result should be OK or PENDING */
    742             if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK))
    743             {
    744                 l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_OK, 0);
    745                 p_ccb->chnl_state = CST_CONFIG;
    746                 alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    747                                    L2CAP_CHNL_CFG_TIMEOUT_MS,
    748                                    l2c_ccb_timer_timeout, p_ccb,
    749                                    btu_general_alarm_queue);
    750             }
    751             else
    752             {
    753                 /* If pending, stay in same state and start extended timer */
    754                 l2cu_send_peer_connect_rsp (p_ccb, p_ci->l2cap_result, p_ci->l2cap_status);
    755                 alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    756                                    L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
    757                                    l2c_ccb_timer_timeout, p_ccb,
    758                                    btu_general_alarm_queue);
    759             }
    760         }
    761         break;
    762 
    763     case L2CEVT_L2CA_CONNECT_RSP_NEG:
    764         p_ci = (tL2C_CONN_INFO *)p_data;
    765         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
    766             l2cble_credit_based_conn_res (p_ccb, p_ci->l2cap_result);
    767         else
    768             l2cu_send_peer_connect_rsp (p_ccb, p_ci->l2cap_result, p_ci->l2cap_status);
    769         l2cu_release_ccb (p_ccb);
    770         break;
    771 
    772     case L2CEVT_TIMEOUT:
    773         l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_NO_PSM, 0);
    774         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    775         l2cu_release_ccb (p_ccb);
    776         (*disconnect_ind)(local_cid, FALSE);
    777         break;
    778 
    779     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
    780     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
    781         osi_free(p_data);
    782         break;
    783 
    784     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
    785         l2cu_send_peer_disc_req (p_ccb);
    786         p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
    787         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    788                            L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
    789                            l2c_ccb_timer_timeout, p_ccb,
    790                            btu_general_alarm_queue);
    791         break;
    792 
    793     case L2CEVT_L2CAP_INFO_RSP:
    794         /* We have feature info, so now give the upper layer connect IND */
    795         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    796                            L2CAP_CHNL_CONNECT_TIMEOUT_MS,
    797                            l2c_ccb_timer_timeout, p_ccb,
    798                            btu_general_alarm_queue);
    799         L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
    800 
    801         (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb) (p_ccb->p_lcb->remote_bd_addr,
    802                                                   p_ccb->local_cid,
    803                                                   p_ccb->p_rcb->psm,
    804                                                   p_ccb->remote_id);
    805         break;
    806     }
    807 }
    808 
    809 
    810 /*******************************************************************************
    811 **
    812 ** Function         l2c_csm_config
    813 **
    814 ** Description      This function handles events when the channel is in
    815 **                  CONFIG state.
    816 **
    817 ** Returns          void
    818 **
    819 *******************************************************************************/
    820 static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    821 {
    822     tL2CAP_CFG_INFO         *p_cfg = (tL2CAP_CFG_INFO *)p_data;
    823     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
    824     UINT16                  local_cid = p_ccb->local_cid;
    825     UINT8                   cfg_result;
    826 
    827 #if (BT_TRACE_VERBOSE == TRUE)
    828     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: CONFIG  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    829 #else
    830     L2CAP_TRACE_EVENT ("L2CAP - st: CONFIG evt: %d", event);
    831 #endif
    832 
    833     switch (event)
    834     {
    835     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    836         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    837         l2cu_release_ccb (p_ccb);
    838         (*disconnect_ind)(local_cid, FALSE);
    839         break;
    840 
    841     case L2CEVT_L2CAP_CONFIG_REQ:                  /* Peer config request   */
    842 
    843         if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK)
    844         {
    845             L2CAP_TRACE_EVENT ("L2CAP - Calling Config_Req_Cb(), CID: 0x%04x, C-bit %d",
    846                                 p_ccb->local_cid, (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT));
    847             (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
    848         }
    849         else if (cfg_result == L2CAP_PEER_CFG_DISCONNECT)
    850         {
    851             /* Disconnect if channels are incompatible */
    852             L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations disconnect");
    853             l2cu_disconnect_chnl (p_ccb);
    854         }
    855         else /* Return error to peer so he can renegotiate if possible */
    856         {
    857             L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations trying reconfig");
    858             l2cu_send_peer_config_rsp (p_ccb, p_cfg);
    859         }
    860         break;
    861 
    862     case L2CEVT_L2CAP_CONFIG_RSP:                  /* Peer config response  */
    863          l2cu_process_peer_cfg_rsp (p_ccb, p_cfg);
    864 
    865          if (p_cfg->result != L2CAP_CFG_PENDING)
    866          {
    867              /* TBD: When config options grow beyong minimum MTU (48 bytes)
    868               *      logic needs to be added to handle responses with
    869               *      continuation bit set in flags field.
    870               *       1. Send additional config request out until C-bit is cleared in response
    871               */
    872              p_ccb->config_done |= OB_CFG_DONE;
    873 
    874              if (p_ccb->config_done & IB_CFG_DONE)
    875              {
    876                 /* Verify two sides are in compatible modes before continuing */
    877                 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode)
    878                 {
    879                     l2cu_send_peer_disc_req (p_ccb);
    880                     L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    881                     l2cu_release_ccb (p_ccb);
    882                     (*disconnect_ind)(local_cid, FALSE);
    883                     break;
    884                 }
    885 
    886                 p_ccb->config_done |= RECONFIG_FLAG;
    887                 p_ccb->chnl_state = CST_OPEN;
    888                 l2c_link_adjust_chnl_allocation ();
    889                 alarm_cancel(p_ccb->l2c_ccb_timer);
    890 
    891                 /* If using eRTM and waiting for an ACK, restart the ACK timer */
    892                 if (p_ccb->fcrb.wait_ack)
    893                     l2c_fcr_start_timer(p_ccb);
    894 
    895                 /*
    896                 ** check p_ccb->our_cfg.fcr.mon_tout and p_ccb->our_cfg.fcr.rtrans_tout
    897                 ** we may set them to zero when sending config request during renegotiation
    898                 */
    899                 if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
    900                    &&((p_ccb->our_cfg.fcr.mon_tout == 0)||(p_ccb->our_cfg.fcr.rtrans_tout)))
    901                 {
    902                     l2c_fcr_adj_monitor_retran_timeout (p_ccb);
    903                 }
    904 
    905 #if (L2CAP_ERTM_STATS == TRUE)
    906                 p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
    907 #endif
    908                 /* See if we can forward anything on the hold queue */
    909                 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q))
    910                 {
    911                     l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
    912                 }
    913             }
    914         }
    915 
    916         L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x", p_ccb->local_cid);
    917         (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
    918         break;
    919 
    920     case L2CEVT_L2CAP_CONFIG_RSP_NEG:              /* Peer config error rsp */
    921         /* Disable the Timer */
    922          alarm_cancel(p_ccb->l2c_ccb_timer);
    923 
    924         /* If failure was channel mode try to renegotiate */
    925         if (l2c_fcr_renegotiate_chan(p_ccb, p_cfg) == FALSE)
    926         {
    927             L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d", p_ccb->local_cid, p_cfg->result);
    928             (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
    929         }
    930         break;
    931 
    932     case L2CEVT_L2CAP_DISCONNECT_REQ:                  /* Peer disconnected request */
    933         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    934                            L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
    935                            l2c_ccb_timer_timeout, p_ccb,
    936                            btu_general_alarm_queue);
    937         p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
    938         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  Conf Needed", p_ccb->local_cid);
    939         (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
    940         break;
    941 
    942     case L2CEVT_L2CA_CONFIG_REQ:                   /* Upper layer config req   */
    943         l2cu_process_our_cfg_req (p_ccb, p_cfg);
    944         l2cu_send_peer_config_req (p_ccb, p_cfg);
    945         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
    946                            L2CAP_CHNL_CFG_TIMEOUT_MS,
    947                            l2c_ccb_timer_timeout, p_ccb,
    948                            btu_general_alarm_queue);
    949         break;
    950 
    951     case L2CEVT_L2CA_CONFIG_RSP:                   /* Upper layer config rsp   */
    952         l2cu_process_our_cfg_rsp (p_ccb, p_cfg);
    953 
    954         /* Not finished if continuation flag is set */
    955         if ( (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT) || (p_cfg->result == L2CAP_CFG_PENDING) )
    956         {
    957             /* Send intermediate response; remain in cfg state */
    958             l2cu_send_peer_config_rsp (p_ccb, p_cfg);
    959             break;
    960         }
    961 
    962         /* Local config done; clear cached configuration in case reconfig takes place later */
    963         p_ccb->peer_cfg.mtu_present = FALSE;
    964         p_ccb->peer_cfg.flush_to_present = FALSE;
    965         p_ccb->peer_cfg.qos_present = FALSE;
    966 
    967         p_ccb->config_done |= IB_CFG_DONE;
    968 
    969         if (p_ccb->config_done & OB_CFG_DONE)
    970         {
    971             /* Verify two sides are in compatible modes before continuing */
    972             if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode)
    973             {
    974                 l2cu_send_peer_disc_req (p_ccb);
    975                 L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    976                 l2cu_release_ccb (p_ccb);
    977                 (*disconnect_ind)(local_cid, FALSE);
    978                 break;
    979             }
    980 
    981             p_ccb->config_done |= RECONFIG_FLAG;
    982             p_ccb->chnl_state = CST_OPEN;
    983             l2c_link_adjust_chnl_allocation ();
    984             alarm_cancel(p_ccb->l2c_ccb_timer);
    985         }
    986 
    987         l2cu_send_peer_config_rsp (p_ccb, p_cfg);
    988 
    989         /* If using eRTM and waiting for an ACK, restart the ACK timer */
    990         if (p_ccb->fcrb.wait_ack)
    991             l2c_fcr_start_timer(p_ccb);
    992 
    993 #if (L2CAP_ERTM_STATS == TRUE)
    994         p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
    995 #endif
    996 
    997         /* See if we can forward anything on the hold queue */
    998         if ( (p_ccb->chnl_state == CST_OPEN) &&
    999              (!fixed_queue_is_empty(p_ccb->xmit_hold_q)))
   1000         {
   1001             l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
   1002         }
   1003         break;
   1004 
   1005     case L2CEVT_L2CA_CONFIG_RSP_NEG:               /* Upper layer config reject */
   1006         l2cu_send_peer_config_rsp (p_ccb, p_cfg);
   1007         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1008                            L2CAP_CHNL_CFG_TIMEOUT_MS,
   1009                            l2c_ccb_timer_timeout, p_ccb,
   1010                            btu_general_alarm_queue);
   1011         break;
   1012 
   1013     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
   1014         l2cu_send_peer_disc_req (p_ccb);
   1015         p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
   1016         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1017                            L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
   1018                            l2c_ccb_timer_timeout, p_ccb,
   1019                            btu_general_alarm_queue);
   1020         break;
   1021 
   1022     case L2CEVT_L2CAP_DATA:                        /* Peer data packet rcvd    */
   1023         L2CAP_TRACE_API ("L2CAP - Calling DataInd_Cb(), CID: 0x%04x", p_ccb->local_cid);
   1024 #if (L2CAP_NUM_FIXED_CHNLS > 0)
   1025         if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL &&
   1026                 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL)
   1027         {
   1028             if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
   1029             {
   1030                 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
   1031                     (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
   1032                         (p_ccb->local_cid, p_ccb->p_lcb->remote_bd_addr,(BT_HDR *)p_data);
   1033                 else
   1034                     osi_free(p_data);
   1035             break;
   1036             }
   1037         }
   1038 #endif
   1039         (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
   1040         break;
   1041 
   1042     case L2CEVT_L2CA_DATA_WRITE:                   /* Upper layer data to send */
   1043         if (p_ccb->config_done & OB_CFG_DONE)
   1044             l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
   1045         else
   1046             osi_free(p_data);
   1047         break;
   1048 
   1049     case L2CEVT_TIMEOUT:
   1050         l2cu_send_peer_disc_req (p_ccb);
   1051         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed",
   1052                 p_ccb->local_cid);
   1053         l2cu_release_ccb (p_ccb);
   1054         (*disconnect_ind)(local_cid, FALSE);
   1055         break;
   1056     }
   1057 }
   1058 
   1059 
   1060 /*******************************************************************************
   1061 **
   1062 ** Function         l2c_csm_open
   1063 **
   1064 ** Description      This function handles events when the channel is in
   1065 **                  OPEN state.
   1066 **
   1067 ** Returns          void
   1068 **
   1069 *******************************************************************************/
   1070 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
   1071 {
   1072     UINT16                  local_cid = p_ccb->local_cid;
   1073     tL2CAP_CFG_INFO         *p_cfg;
   1074     tL2C_CHNL_STATE         tempstate;
   1075     UINT8                   tempcfgdone;
   1076     UINT8                   cfg_result;
   1077     UINT16                  *credit;
   1078 
   1079 #if (BT_TRACE_VERBOSE == TRUE)
   1080     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: OPEN  evt: %s",
   1081             p_ccb->local_cid, l2c_csm_get_event_name (event));
   1082 #else
   1083     L2CAP_TRACE_EVENT ("L2CAP - st: OPEN evt: %d", event);
   1084 #endif
   1085 
   1086 #if (L2CAP_UCD_INCLUDED == TRUE)
   1087     if ( local_cid == L2CAP_CONNECTIONLESS_CID )
   1088     {
   1089         /* check if this event can be processed by UCD */
   1090         if ( l2c_ucd_process_event (p_ccb, event, p_data) )
   1091         {
   1092             /* The event is processed by UCD state machine */
   1093             return;
   1094         }
   1095     }
   1096 #endif
   1097 
   1098     switch (event)
   1099     {
   1100     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
   1101         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed",
   1102                 p_ccb->local_cid);
   1103         l2cu_release_ccb (p_ccb);
   1104         if (p_ccb->p_rcb)
   1105             (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, FALSE);
   1106         break;
   1107 
   1108     case L2CEVT_LP_QOS_VIOLATION_IND:               /* QOS violation         */
   1109         /* Tell upper layer. If service guaranteed, then clear the channel   */
   1110         if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
   1111             (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(p_ccb->p_lcb->remote_bd_addr);
   1112         break;
   1113 
   1114     case L2CEVT_L2CAP_CONFIG_REQ:                  /* Peer config request   */
   1115         p_cfg = (tL2CAP_CFG_INFO *)p_data;
   1116 
   1117         tempstate = p_ccb->chnl_state;
   1118         tempcfgdone = p_ccb->config_done;
   1119         p_ccb->chnl_state = CST_CONFIG;
   1120         p_ccb->config_done &= ~CFG_DONE_MASK;
   1121 
   1122         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1123                            L2CAP_CHNL_CFG_TIMEOUT_MS,
   1124                            l2c_ccb_timer_timeout, p_ccb,
   1125                            btu_general_alarm_queue);
   1126 
   1127         if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK)
   1128         {
   1129             (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
   1130         }
   1131 
   1132         /* Error in config parameters: reset state and config flag */
   1133         else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE)
   1134         {
   1135             alarm_cancel(p_ccb->l2c_ccb_timer);
   1136             p_ccb->chnl_state = tempstate;
   1137             p_ccb->config_done = tempcfgdone;
   1138             l2cu_send_peer_config_rsp (p_ccb, p_cfg);
   1139         }
   1140         else    /* L2CAP_PEER_CFG_DISCONNECT */
   1141         {
   1142             /* Disconnect if channels are incompatible
   1143              * Note this should not occur if reconfigure
   1144              * since this should have never passed original config.
   1145              */
   1146             l2cu_disconnect_chnl (p_ccb);
   1147         }
   1148         break;
   1149 
   1150     case L2CEVT_L2CAP_DISCONNECT_REQ:                  /* Peer disconnected request */
   1151         if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
   1152         {
   1153         /* Make sure we are not in sniff mode */
   1154             {
   1155                 tBTM_PM_PWR_MD settings;
   1156                 memset((void*)&settings, 0, sizeof(settings));
   1157                 settings.mode = BTM_PM_MD_ACTIVE;
   1158                 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
   1159             }
   1160         }
   1161 
   1162         p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
   1163         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1164                            L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
   1165                            l2c_ccb_timer_timeout, p_ccb,
   1166                            btu_general_alarm_queue);
   1167         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  Conf Needed", p_ccb->local_cid);
   1168         (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
   1169         break;
   1170 
   1171     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1172         if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb))
   1173             (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
   1174         break;
   1175 
   1176     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
   1177         if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
   1178         {
   1179             /* Make sure we are not in sniff mode */
   1180             {
   1181                 tBTM_PM_PWR_MD settings;
   1182                 memset((void*)&settings, 0, sizeof(settings));
   1183                 settings.mode = BTM_PM_MD_ACTIVE;
   1184                 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
   1185             }
   1186         }
   1187 
   1188         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
   1189             l2cble_send_peer_disc_req (p_ccb);
   1190         else
   1191             l2cu_send_peer_disc_req (p_ccb);
   1192 
   1193         p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
   1194         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1195                            L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
   1196                            l2c_ccb_timer_timeout, p_ccb,
   1197                            btu_general_alarm_queue);
   1198         break;
   1199 
   1200     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1201         l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
   1202         l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
   1203         break;
   1204 
   1205     case L2CEVT_L2CA_CONFIG_REQ:                   /* Upper layer config req   */
   1206         p_ccb->chnl_state = CST_CONFIG;
   1207         p_ccb->config_done &= ~CFG_DONE_MASK;
   1208         l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
   1209         l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
   1210         alarm_set_on_queue(p_ccb->l2c_ccb_timer,
   1211                            L2CAP_CHNL_CFG_TIMEOUT_MS,
   1212                            l2c_ccb_timer_timeout, p_ccb,
   1213                            btu_general_alarm_queue);
   1214         break;
   1215 
   1216     case L2CEVT_TIMEOUT:
   1217         /* Process the monitor/retransmission time-outs in flow control/retrans mode */
   1218         if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
   1219             l2c_fcr_proc_tout (p_ccb);
   1220         break;
   1221 
   1222     case L2CEVT_ACK_TIMEOUT:
   1223         l2c_fcr_proc_ack_tout (p_ccb);
   1224         break;
   1225 
   1226     case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
   1227         L2CAP_TRACE_DEBUG("%s Sending credit",__func__);
   1228         credit = (UINT16*)p_data;
   1229         l2cble_send_flow_control_credit(p_ccb, *credit);
   1230         break;
   1231 
   1232     case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
   1233         credit = (UINT16*)p_data;
   1234         L2CAP_TRACE_DEBUG("%s Credits received %d",__func__, *credit);
   1235         if((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_MAX_CREDIT)
   1236         {
   1237             /* we have received credits more than max coc credits,
   1238              * so disconnecting the Le Coc Channel
   1239              */
   1240             l2cble_send_peer_disc_req (p_ccb);
   1241         }
   1242         else
   1243         {
   1244             p_ccb->peer_conn_cfg.credits += *credit;
   1245             l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
   1246         }
   1247         break;
   1248     }
   1249 }
   1250 
   1251 
   1252 /*******************************************************************************
   1253 **
   1254 ** Function         l2c_csm_w4_l2cap_disconnect_rsp
   1255 **
   1256 ** Description      This function handles events when the channel is in
   1257 **                  CST_W4_L2CAP_DISCONNECT_RSP state.
   1258 **
   1259 ** Returns          void
   1260 **
   1261 *******************************************************************************/
   1262 static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
   1263 {
   1264     tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
   1265     UINT16                  local_cid = p_ccb->local_cid;
   1266 
   1267 #if (BT_TRACE_VERBOSE == TRUE)
   1268     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CAP_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
   1269 #else
   1270     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
   1271 #endif
   1272 
   1273     switch (event)
   1274     {
   1275     case L2CEVT_L2CAP_DISCONNECT_RSP:                /* Peer disconnect response */
   1276         l2cu_release_ccb (p_ccb);
   1277         if (disconnect_cfm)
   1278         {
   1279             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1280             (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
   1281         }
   1282         break;
   1283 
   1284     case L2CEVT_L2CAP_DISCONNECT_REQ:                /* Peer disconnect request  */
   1285         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1286         l2cu_release_ccb (p_ccb);
   1287         if (disconnect_cfm)
   1288         {
   1289             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1290             (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
   1291         }
   1292        break;
   1293 
   1294     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
   1295     case L2CEVT_TIMEOUT:                            /* Timeout */
   1296         l2cu_release_ccb (p_ccb);
   1297         if (disconnect_cfm)
   1298         {
   1299             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1300             (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
   1301         }
   1302         break;
   1303 
   1304     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1305     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1306         osi_free(p_data);
   1307         break;
   1308 
   1309     case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
   1310     case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
   1311         osi_free(p_data);
   1312         break;
   1313     }
   1314 }
   1315 
   1316 
   1317 /*******************************************************************************
   1318 **
   1319 ** Function         l2c_csm_w4_l2ca_disconnect_rsp
   1320 **
   1321 ** Description      This function handles events when the channel is in
   1322 **                  CST_W4_L2CA_DISCONNECT_RSP state.
   1323 **
   1324 ** Returns          void
   1325 **
   1326 *******************************************************************************/
   1327 static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
   1328 {
   1329     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
   1330     UINT16                  local_cid = p_ccb->local_cid;
   1331 
   1332 #if (BT_TRACE_VERBOSE == TRUE)
   1333     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CA_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
   1334 #else
   1335     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
   1336 #endif
   1337 
   1338     switch (event)
   1339     {
   1340     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
   1341         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
   1342         l2cu_release_ccb (p_ccb);
   1343         (*disconnect_ind)(local_cid, FALSE);
   1344         break;
   1345 
   1346     case L2CEVT_TIMEOUT:
   1347         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1348         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
   1349         l2cu_release_ccb (p_ccb);
   1350         (*disconnect_ind)(local_cid, FALSE);
   1351         break;
   1352 
   1353     case L2CEVT_L2CA_DISCONNECT_REQ:                /* Upper disconnect request */
   1354     case L2CEVT_L2CA_DISCONNECT_RSP:                /* Upper disconnect response */
   1355         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1356         l2cu_release_ccb (p_ccb);
   1357         break;
   1358 
   1359     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1360     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1361         osi_free(p_data);
   1362         break;
   1363     }
   1364 }
   1365 
   1366 
   1367 #if (BT_TRACE_VERBOSE == TRUE)
   1368 /*******************************************************************************
   1369 **
   1370 ** Function         l2c_csm_get_event_name
   1371 **
   1372 ** Description      This function returns the event name.
   1373 **
   1374 ** NOTE             conditionally compiled to save memory.
   1375 **
   1376 ** Returns          pointer to the name
   1377 **
   1378 *******************************************************************************/
   1379 static char *l2c_csm_get_event_name (UINT16 event)
   1380 {
   1381     switch (event)
   1382     {
   1383     case L2CEVT_LP_CONNECT_CFM:                  /* Lower layer connect confirm          */
   1384         return ("LOWER_LAYER_CONNECT_CFM");
   1385     case L2CEVT_LP_CONNECT_CFM_NEG:              /* Lower layer connect confirm (failed) */
   1386         return ("LOWER_LAYER_CONNECT_CFM_NEG");
   1387     case L2CEVT_LP_CONNECT_IND:                  /* Lower layer connect indication       */
   1388         return ("LOWER_LAYER_CONNECT_IND");
   1389     case L2CEVT_LP_DISCONNECT_IND:               /* Lower layer disconnect indication    */
   1390         return ("LOWER_LAYER_DISCONNECT_IND");
   1391     case L2CEVT_LP_QOS_CFM:                      /* Lower layer QOS confirmation         */
   1392         return ("LOWER_LAYER_QOS_CFM");
   1393     case L2CEVT_LP_QOS_CFM_NEG:                  /* Lower layer QOS confirmation (failed)*/
   1394         return ("LOWER_LAYER_QOS_CFM_NEG");
   1395     case L2CEVT_LP_QOS_VIOLATION_IND:            /* Lower layer QOS violation indication */
   1396         return ("LOWER_LAYER_QOS_VIOLATION_IND");
   1397 
   1398     case L2CEVT_SEC_COMP:                        /* Security cleared successfully        */
   1399         return ("SECURITY_COMPLETE");
   1400     case L2CEVT_SEC_COMP_NEG:                    /* Security procedure failed            */
   1401         return ("SECURITY_COMPLETE_NEG");
   1402 
   1403     case L2CEVT_L2CAP_CONNECT_REQ:               /* Peer connection request              */
   1404         return ("PEER_CONNECT_REQ");
   1405     case L2CEVT_L2CAP_CONNECT_RSP:               /* Peer connection response             */
   1406         return ("PEER_CONNECT_RSP");
   1407     case L2CEVT_L2CAP_CONNECT_RSP_PND:           /* Peer connection response pending     */
   1408         return ("PEER_CONNECT_RSP_PND");
   1409     case L2CEVT_L2CAP_CONNECT_RSP_NEG:           /* Peer connection response (failed)    */
   1410         return ("PEER_CONNECT_RSP_NEG");
   1411     case L2CEVT_L2CAP_CONFIG_REQ:                /* Peer configuration request           */
   1412         return ("PEER_CONFIG_REQ");
   1413     case L2CEVT_L2CAP_CONFIG_RSP:                /* Peer configuration response          */
   1414         return ("PEER_CONFIG_RSP");
   1415     case L2CEVT_L2CAP_CONFIG_RSP_NEG:            /* Peer configuration response (failed) */
   1416         return ("PEER_CONFIG_RSP_NEG");
   1417     case L2CEVT_L2CAP_DISCONNECT_REQ:            /* Peer disconnect request              */
   1418         return ("PEER_DISCONNECT_REQ");
   1419     case L2CEVT_L2CAP_DISCONNECT_RSP:            /* Peer disconnect response             */
   1420         return ("PEER_DISCONNECT_RSP");
   1421     case L2CEVT_L2CAP_DATA:                      /* Peer data                            */
   1422         return ("PEER_DATA");
   1423 
   1424     case L2CEVT_L2CA_CONNECT_REQ:                /* Upper layer connect request          */
   1425         return ("UPPER_LAYER_CONNECT_REQ");
   1426     case L2CEVT_L2CA_CONNECT_RSP:                /* Upper layer connect response         */
   1427         return ("UPPER_LAYER_CONNECT_RSP");
   1428     case L2CEVT_L2CA_CONNECT_RSP_NEG:            /* Upper layer connect response (failed)*/
   1429         return ("UPPER_LAYER_CONNECT_RSP_NEG");
   1430     case L2CEVT_L2CA_CONFIG_REQ:                 /* Upper layer config request           */
   1431         return ("UPPER_LAYER_CONFIG_REQ");
   1432     case L2CEVT_L2CA_CONFIG_RSP:                 /* Upper layer config response          */
   1433         return ("UPPER_LAYER_CONFIG_RSP");
   1434     case L2CEVT_L2CA_CONFIG_RSP_NEG:             /* Upper layer config response (failed) */
   1435         return ("UPPER_LAYER_CONFIG_RSP_NEG");
   1436     case L2CEVT_L2CA_DISCONNECT_REQ:             /* Upper layer disconnect request       */
   1437         return ("UPPER_LAYER_DISCONNECT_REQ");
   1438     case L2CEVT_L2CA_DISCONNECT_RSP:             /* Upper layer disconnect response      */
   1439         return ("UPPER_LAYER_DISCONNECT_RSP");
   1440     case L2CEVT_L2CA_DATA_READ:                  /* Upper layer data read                */
   1441         return ("UPPER_LAYER_DATA_READ");
   1442     case L2CEVT_L2CA_DATA_WRITE:                 /* Upper layer data write               */
   1443         return ("UPPER_LAYER_DATA_WRITE");
   1444     case L2CEVT_TIMEOUT:                         /* Timeout                              */
   1445         return ("TIMEOUT");
   1446     case L2CEVT_SEC_RE_SEND_CMD:
   1447         return ("SEC_RE_SEND_CMD");
   1448     case L2CEVT_L2CAP_INFO_RSP:                  /* Peer information response            */
   1449         return ("L2CEVT_L2CAP_INFO_RSP");
   1450     case L2CEVT_ACK_TIMEOUT:
   1451         return ("L2CEVT_ACK_TIMEOUT");
   1452     case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:   /* Upper layer send credit packet       */
   1453         return ("SEND_FLOW_CONTROL_CREDIT");
   1454     case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:  /* Peer send credit packet              */
   1455         return ("RECV_FLOW_CONTROL_CREDIT");
   1456 
   1457     default:
   1458         return ("???? UNKNOWN EVENT");
   1459     }
   1460 }
   1461 #endif /* (BT_TRACE_VERBOSE == TRUE) */
   1462 
   1463 
   1464 /*******************************************************************************
   1465 **
   1466 ** Function         l2c_enqueue_peer_data
   1467 **
   1468 ** Description      Enqueues data destined for the peer in the ccb. Handles
   1469 **                  FCR segmentation and checks for congestion.
   1470 **
   1471 ** Returns          void
   1472 **
   1473 *******************************************************************************/
   1474 void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
   1475 {
   1476     UINT8       *p;
   1477 
   1478     if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
   1479     {
   1480         p_buf->event = 0;
   1481     }
   1482     else
   1483     {
   1484         /* Save the channel ID for faster counting */
   1485         p_buf->event = p_ccb->local_cid;
   1486 
   1487         /* Step back to add the L2CAP header */
   1488         p_buf->offset -= L2CAP_PKT_OVERHEAD;
   1489         p_buf->len    += L2CAP_PKT_OVERHEAD;
   1490 
   1491         /* Set the pointer to the beginning of the data */
   1492         p = (UINT8 *)(p_buf + 1) + p_buf->offset;
   1493 
   1494         /* Now the L2CAP header */
   1495         UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
   1496         UINT16_TO_STREAM (p, p_ccb->remote_cid);
   1497     }
   1498 
   1499     if (p_ccb->xmit_hold_q == NULL) {
   1500       L2CAP_TRACE_ERROR("%s: empty queue: p_ccb = %p p_ccb->in_use = %d p_ccb->chnl_state = %d p_ccb->local_cid = %u p_ccb->remote_cid = %u",
   1501                         __func__, p_ccb, p_ccb->in_use, p_ccb->chnl_state,
   1502                         p_ccb->local_cid, p_ccb->remote_cid);
   1503     }
   1504     fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf);
   1505 
   1506     l2cu_check_channel_congestion (p_ccb);
   1507 
   1508 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
   1509     /* if new packet is higher priority than serving ccb and it is not overrun */
   1510     if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority )
   1511       &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0))
   1512     {
   1513         /* send out higher priority packet */
   1514         p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
   1515     }
   1516 #endif
   1517 
   1518     /* if we are doing a round robin scheduling, set the flag */
   1519     if (p_ccb->p_lcb->link_xmit_quota == 0)
   1520         l2cb.check_round_robin = TRUE;
   1521 }
   1522 
   1523 
   1524