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