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