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_ERROR ("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_ERROR ("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_EVENT ("L2CAP - LCID: 0x%04x  st: CLOSED  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    155 #else
    156     L2CAP_TRACE_EVENT ("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_API ("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_API ("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_API ("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_API ("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_EVENT ("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_EVENT ("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_API ("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_API ("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_EVENT ("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_EVENT ("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_API ("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_API ("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_EVENT ("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_EVENT ("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_API ("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_API ("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_API ("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_API ("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_API ("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_EVENT ("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_EVENT ("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_API ("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_API ("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_API ("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_EVENT ("L2CAP - LCID: 0x%04x  st: CONFIG  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    712 #else
    713     L2CAP_TRACE_EVENT ("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_API ("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_EVENT ("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_EVENT ("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_EVENT ("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_WARNING ("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_API ("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_API ("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_API ("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_WARNING ("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_API ("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_FIRST_FIXED_CHNL &&
    896                 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL)
    897         {
    898             if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
    899             {
    900                 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
    901                     (*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);
    902                 else
    903                     GKI_freebuf (p_data);
    904             break;
    905             }
    906         }
    907 #endif
    908         (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
    909         break;
    910 
    911     case L2CEVT_L2CA_DATA_WRITE:                   /* Upper layer data to send */
    912         if (p_ccb->config_done & OB_CFG_DONE)
    913             l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
    914         else
    915             GKI_freebuf (p_data);
    916         break;
    917 
    918     case L2CEVT_TIMEOUT:
    919         l2cu_send_peer_disc_req (p_ccb);
    920         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    921         l2cu_release_ccb (p_ccb);
    922         (*disconnect_ind)(local_cid, FALSE);
    923         break;
    924     }
    925 }
    926 
    927 
    928 /*******************************************************************************
    929 **
    930 ** Function         l2c_csm_open
    931 **
    932 ** Description      This function handles events when the channel is in
    933 **                  OPEN state.
    934 **
    935 ** Returns          void
    936 **
    937 *******************************************************************************/
    938 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
    939 {
    940     UINT16                  local_cid = p_ccb->local_cid;
    941     tL2CAP_CFG_INFO         *p_cfg;
    942     tL2C_CHNL_STATE         tempstate;
    943     UINT8                   tempcfgdone;
    944     UINT8                   cfg_result;
    945 
    946 #if (BT_TRACE_VERBOSE == TRUE)
    947     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: OPEN  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
    948 #else
    949     L2CAP_TRACE_EVENT ("L2CAP - st: OPEN evt: %d", event);
    950 #endif
    951 
    952 #if (L2CAP_UCD_INCLUDED == TRUE)
    953     if ( local_cid == L2CAP_CONNECTIONLESS_CID )
    954     {
    955         /* check if this event can be processed by UCD */
    956         if ( l2c_ucd_process_event (p_ccb, event, p_data) )
    957         {
    958             /* The event is processed by UCD state machine */
    959             return;
    960         }
    961     }
    962 #endif
    963 
    964     switch (event)
    965     {
    966     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
    967         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
    968         l2cu_release_ccb (p_ccb);
    969         if (p_ccb->p_rcb)
    970             (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, FALSE);
    971         break;
    972 
    973     case L2CEVT_LP_QOS_VIOLATION_IND:               /* QOS violation         */
    974         /* Tell upper layer. If service guaranteed, then clear the channel   */
    975         if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
    976             (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(p_ccb->p_lcb->remote_bd_addr);
    977         break;
    978 
    979     case L2CEVT_L2CAP_CONFIG_REQ:                  /* Peer config request   */
    980         p_cfg = (tL2CAP_CFG_INFO *)p_data;
    981 
    982         tempstate = p_ccb->chnl_state;
    983         tempcfgdone = p_ccb->config_done;
    984         p_ccb->chnl_state = CST_CONFIG;
    985         p_ccb->config_done &= ~CFG_DONE_MASK;
    986 
    987         btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
    988 
    989         if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK)
    990         {
    991             (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
    992         }
    993 
    994         /* Error in config parameters: reset state and config flag */
    995         else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE)
    996         {
    997             btu_stop_timer(&p_ccb->timer_entry);
    998             p_ccb->chnl_state = tempstate;
    999             p_ccb->config_done = tempcfgdone;
   1000             l2cu_send_peer_config_rsp (p_ccb, p_cfg);
   1001         }
   1002         else    /* L2CAP_PEER_CFG_DISCONNECT */
   1003         {
   1004             /* Disconnect if channels are incompatible
   1005              * Note this should not occur if reconfigure
   1006              * since this should have never passed original config.
   1007              */
   1008             l2cu_disconnect_chnl (p_ccb);
   1009         }
   1010         break;
   1011 
   1012     case L2CEVT_L2CAP_DISCONNECT_REQ:                  /* Peer disconnected request */
   1013 // btla-specific ++
   1014         /* Make sure we are not in sniff mode */
   1015 #if BTM_PWR_MGR_INCLUDED == TRUE
   1016         {
   1017             tBTM_PM_PWR_MD settings;
   1018             memset((void*)&settings, 0, sizeof(settings));
   1019             settings.mode = BTM_PM_MD_ACTIVE;
   1020             BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
   1021         }
   1022 #else
   1023         BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr);
   1024 #endif
   1025 // btla-specific --
   1026 
   1027         p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
   1028         btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
   1029         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  Conf Needed", p_ccb->local_cid);
   1030         (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
   1031         break;
   1032 
   1033     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1034         (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
   1035         break;
   1036 
   1037     case L2CEVT_L2CA_DISCONNECT_REQ:                 /* Upper wants to disconnect */
   1038         /* Make sure we are not in sniff mode */
   1039 #if BTM_PWR_MGR_INCLUDED == TRUE
   1040         {
   1041             tBTM_PM_PWR_MD settings;
   1042             memset((void*)&settings, 0, sizeof(settings));
   1043             settings.mode = BTM_PM_MD_ACTIVE;
   1044             BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
   1045         }
   1046 #else
   1047         BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr);
   1048 #endif
   1049 
   1050         l2cu_send_peer_disc_req (p_ccb);
   1051         p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
   1052         btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
   1053         break;
   1054 
   1055     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1056         l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
   1057         l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
   1058         break;
   1059 
   1060     case L2CEVT_L2CA_CONFIG_REQ:                   /* Upper layer config req   */
   1061         p_ccb->chnl_state = CST_CONFIG;
   1062         p_ccb->config_done &= ~CFG_DONE_MASK;
   1063         l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
   1064         l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
   1065         btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
   1066         break;
   1067 
   1068     case L2CEVT_TIMEOUT:
   1069         /* Process the monitor/retransmission time-outs in flow control/retrans mode */
   1070         if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
   1071             l2c_fcr_proc_tout (p_ccb);
   1072         break;
   1073 
   1074     case L2CEVT_ACK_TIMEOUT:
   1075         l2c_fcr_proc_ack_tout (p_ccb);
   1076         break;
   1077     }
   1078 }
   1079 
   1080 
   1081 /*******************************************************************************
   1082 **
   1083 ** Function         l2c_csm_w4_l2cap_disconnect_rsp
   1084 **
   1085 ** Description      This function handles events when the channel is in
   1086 **                  CST_W4_L2CAP_DISCONNECT_RSP state.
   1087 **
   1088 ** Returns          void
   1089 **
   1090 *******************************************************************************/
   1091 static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
   1092 {
   1093     tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
   1094     UINT16                  local_cid = p_ccb->local_cid;
   1095 
   1096 #if (BT_TRACE_VERBOSE == TRUE)
   1097     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CAP_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
   1098 #else
   1099     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
   1100 #endif
   1101 
   1102     switch (event)
   1103     {
   1104     case L2CEVT_L2CAP_DISCONNECT_RSP:                /* Peer disconnect response */
   1105         l2cu_release_ccb (p_ccb);
   1106         if (disconnect_cfm)
   1107         {
   1108             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1109             (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
   1110         }
   1111         break;
   1112 
   1113     case L2CEVT_L2CAP_DISCONNECT_REQ:                /* Peer disconnect request  */
   1114         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1115         l2cu_release_ccb (p_ccb);
   1116         if (disconnect_cfm)
   1117         {
   1118             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1119             (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
   1120         }
   1121        break;
   1122 
   1123     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
   1124     case L2CEVT_TIMEOUT:                            /* Timeout */
   1125         l2cu_release_ccb (p_ccb);
   1126         if (disconnect_cfm)
   1127         {
   1128             L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
   1129             (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
   1130         }
   1131         break;
   1132 
   1133     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1134     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1135         GKI_freebuf (p_data);
   1136         break;
   1137     }
   1138 }
   1139 
   1140 
   1141 /*******************************************************************************
   1142 **
   1143 ** Function         l2c_csm_w4_l2ca_disconnect_rsp
   1144 **
   1145 ** Description      This function handles events when the channel is in
   1146 **                  CST_W4_L2CA_DISCONNECT_RSP state.
   1147 **
   1148 ** Returns          void
   1149 **
   1150 *******************************************************************************/
   1151 static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
   1152 {
   1153     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
   1154     UINT16                  local_cid = p_ccb->local_cid;
   1155 
   1156 #if (BT_TRACE_VERBOSE == TRUE)
   1157     L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x  st: W4_L2CA_DISC_RSP  evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
   1158 #else
   1159     L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
   1160 #endif
   1161 
   1162     switch (event)
   1163     {
   1164     case L2CEVT_LP_DISCONNECT_IND:                  /* Link was disconnected */
   1165         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
   1166         l2cu_release_ccb (p_ccb);
   1167         (*disconnect_ind)(local_cid, FALSE);
   1168         break;
   1169 
   1170     case L2CEVT_TIMEOUT:
   1171         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1172         L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed", p_ccb->local_cid);
   1173         l2cu_release_ccb (p_ccb);
   1174         (*disconnect_ind)(local_cid, FALSE);
   1175         break;
   1176 
   1177     case L2CEVT_L2CA_DISCONNECT_REQ:                /* Upper disconnect request */
   1178     case L2CEVT_L2CA_DISCONNECT_RSP:                /* Upper disconnect response */
   1179         l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
   1180         l2cu_release_ccb (p_ccb);
   1181         break;
   1182 
   1183     case L2CEVT_L2CAP_DATA:                         /* Peer data packet rcvd    */
   1184     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
   1185         GKI_freebuf (p_data);
   1186         break;
   1187     }
   1188 }
   1189 
   1190 
   1191 #if (BT_TRACE_VERBOSE == TRUE)
   1192 /*******************************************************************************
   1193 **
   1194 ** Function         l2c_csm_get_event_name
   1195 **
   1196 ** Description      This function returns the event name.
   1197 **
   1198 ** NOTE             conditionally compiled to save memory.
   1199 **
   1200 ** Returns          pointer to the name
   1201 **
   1202 *******************************************************************************/
   1203 static char *l2c_csm_get_event_name (UINT16 event)
   1204 {
   1205     switch (event)
   1206     {
   1207     case L2CEVT_LP_CONNECT_CFM:                  /* Lower layer connect confirm          */
   1208         return ("LOWER_LAYER_CONNECT_CFM");
   1209     case L2CEVT_LP_CONNECT_CFM_NEG:              /* Lower layer connect confirm (failed) */
   1210         return ("LOWER_LAYER_CONNECT_CFM_NEG");
   1211     case L2CEVT_LP_CONNECT_IND:                  /* Lower layer connect indication       */
   1212         return ("LOWER_LAYER_CONNECT_IND");
   1213     case L2CEVT_LP_DISCONNECT_IND:               /* Lower layer disconnect indication    */
   1214         return ("LOWER_LAYER_DISCONNECT_IND");
   1215     case L2CEVT_LP_QOS_CFM:                      /* Lower layer QOS confirmation         */
   1216         return ("LOWER_LAYER_QOS_CFM");
   1217     case L2CEVT_LP_QOS_CFM_NEG:                  /* Lower layer QOS confirmation (failed)*/
   1218         return ("LOWER_LAYER_QOS_CFM_NEG");
   1219     case L2CEVT_LP_QOS_VIOLATION_IND:            /* Lower layer QOS violation indication */
   1220         return ("LOWER_LAYER_QOS_VIOLATION_IND");
   1221 
   1222     case L2CEVT_SEC_COMP:                        /* Security cleared successfully        */
   1223         return ("SECURITY_COMPLETE");
   1224     case L2CEVT_SEC_COMP_NEG:                    /* Security procedure failed            */
   1225         return ("SECURITY_COMPLETE_NEG");
   1226 
   1227     case L2CEVT_L2CAP_CONNECT_REQ:               /* Peer connection request              */
   1228         return ("PEER_CONNECT_REQ");
   1229     case L2CEVT_L2CAP_CONNECT_RSP:               /* Peer connection response             */
   1230         return ("PEER_CONNECT_RSP");
   1231     case L2CEVT_L2CAP_CONNECT_RSP_PND:           /* Peer connection response pending     */
   1232         return ("PEER_CONNECT_RSP_PND");
   1233     case L2CEVT_L2CAP_CONNECT_RSP_NEG:           /* Peer connection response (failed)    */
   1234         return ("PEER_CONNECT_RSP_NEG");
   1235     case L2CEVT_L2CAP_CONFIG_REQ:                /* Peer configuration request           */
   1236         return ("PEER_CONFIG_REQ");
   1237     case L2CEVT_L2CAP_CONFIG_RSP:                /* Peer configuration response          */
   1238         return ("PEER_CONFIG_RSP");
   1239     case L2CEVT_L2CAP_CONFIG_RSP_NEG:            /* Peer configuration response (failed) */
   1240         return ("PEER_CONFIG_RSP_NEG");
   1241     case L2CEVT_L2CAP_DISCONNECT_REQ:            /* Peer disconnect request              */
   1242         return ("PEER_DISCONNECT_REQ");
   1243     case L2CEVT_L2CAP_DISCONNECT_RSP:            /* Peer disconnect response             */
   1244         return ("PEER_DISCONNECT_RSP");
   1245     case L2CEVT_L2CAP_DATA:                      /* Peer data                            */
   1246         return ("PEER_DATA");
   1247 
   1248     case L2CEVT_L2CA_CONNECT_REQ:                /* Upper layer connect request          */
   1249         return ("UPPER_LAYER_CONNECT_REQ");
   1250     case L2CEVT_L2CA_CONNECT_RSP:                /* Upper layer connect response         */
   1251         return ("UPPER_LAYER_CONNECT_RSP");
   1252     case L2CEVT_L2CA_CONNECT_RSP_NEG:            /* Upper layer connect response (failed)*/
   1253         return ("UPPER_LAYER_CONNECT_RSP_NEG");
   1254     case L2CEVT_L2CA_CONFIG_REQ:                 /* Upper layer config request           */
   1255         return ("UPPER_LAYER_CONFIG_REQ");
   1256     case L2CEVT_L2CA_CONFIG_RSP:                 /* Upper layer config response          */
   1257         return ("UPPER_LAYER_CONFIG_RSP");
   1258     case L2CEVT_L2CA_CONFIG_RSP_NEG:             /* Upper layer config response (failed) */
   1259         return ("UPPER_LAYER_CONFIG_RSP_NEG");
   1260     case L2CEVT_L2CA_DISCONNECT_REQ:             /* Upper layer disconnect request       */
   1261         return ("UPPER_LAYER_DISCONNECT_REQ");
   1262     case L2CEVT_L2CA_DISCONNECT_RSP:             /* Upper layer disconnect response      */
   1263         return ("UPPER_LAYER_DISCONNECT_RSP");
   1264     case L2CEVT_L2CA_DATA_READ:                  /* Upper layer data read                */
   1265         return ("UPPER_LAYER_DATA_READ");
   1266     case L2CEVT_L2CA_DATA_WRITE:                 /* Upper layer data write               */
   1267         return ("UPPER_LAYER_DATA_WRITE");
   1268     case L2CEVT_TIMEOUT:                         /* Timeout                              */
   1269         return ("TIMEOUT");
   1270     case L2CEVT_SEC_RE_SEND_CMD:
   1271         return ("SEC_RE_SEND_CMD");
   1272     case L2CEVT_L2CAP_INFO_RSP:                  /* Peer information response            */
   1273         return ("L2CEVT_L2CAP_INFO_RSP");
   1274     case L2CEVT_ACK_TIMEOUT:
   1275         return ("L2CEVT_ACK_TIMEOUT");
   1276 
   1277     default:
   1278         return ("???? UNKNOWN EVENT");
   1279     }
   1280 }
   1281 #endif /* (BT_TRACE_VERBOSE == TRUE) */
   1282 
   1283 
   1284 /*******************************************************************************
   1285 **
   1286 ** Function         l2c_enqueue_peer_data
   1287 **
   1288 ** Description      Enqueues data destined for the peer in the ccb. Handles
   1289 **                  FCR segmentation and checks for congestion.
   1290 **
   1291 ** Returns          void
   1292 **
   1293 *******************************************************************************/
   1294 void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
   1295 {
   1296     UINT8       *p;
   1297 
   1298     if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
   1299     {
   1300         p_buf->event = 0;
   1301     }
   1302     else
   1303     {
   1304         /* Save the channel ID for faster counting */
   1305         p_buf->event = p_ccb->local_cid;
   1306 
   1307         /* Step back to add the L2CAP header */
   1308         p_buf->offset -= L2CAP_PKT_OVERHEAD;
   1309         p_buf->len    += L2CAP_PKT_OVERHEAD;
   1310 
   1311         /* Set the pointer to the beginning of the data */
   1312         p = (UINT8 *)(p_buf + 1) + p_buf->offset;
   1313 
   1314         /* Now the L2CAP header */
   1315         UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
   1316         UINT16_TO_STREAM (p, p_ccb->remote_cid);
   1317     }
   1318 
   1319     GKI_enqueue (&p_ccb->xmit_hold_q, p_buf);
   1320 
   1321     l2cu_check_channel_congestion (p_ccb);
   1322 
   1323 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
   1324     /* if new packet is higher priority than serving ccb and it is not overrun */
   1325     if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority )
   1326       &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0))
   1327     {
   1328         /* send out higher priority packet */
   1329         p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
   1330     }
   1331 #endif
   1332 
   1333     /* if we are doing a round robin scheduling, set the flag */
   1334     if (p_ccb->p_lcb->link_xmit_quota == 0)
   1335         l2cb.check_round_robin = TRUE;
   1336 }
   1337 
   1338 
   1339