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