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