Home | History | Annotate | Download | only in rfcomm
      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 state machine and action routines for multiplexer
     22  *  channel of the RFCOMM unit
     23  *
     24  ******************************************************************************/
     25 #include <string.h>
     26 #include "bt_common.h"
     27 #include "bt_types.h"
     28 #include "bt_utils.h"
     29 #include "l2c_api.h"
     30 #include "l2cdefs.h"
     31 #include "osi/include/osi.h"
     32 #include "port_api.h"
     33 #include "port_int.h"
     34 #include "rfc_int.h"
     35 #include "rfcdefs.h"
     36 
     37 #define L2CAP_SUCCESS 0
     38 #define L2CAP_ERROR 1
     39 
     40 /******************************************************************************/
     41 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
     42 /******************************************************************************/
     43 static void rfc_mx_sm_state_idle(tRFC_MCB* p_mcb, uint16_t event, void* p_data);
     44 static void rfc_mx_sm_state_wait_conn_cnf(tRFC_MCB* p_mcb, uint16_t event,
     45                                           void* p_data);
     46 static void rfc_mx_sm_state_configure(tRFC_MCB* p_mcb, uint16_t event,
     47                                       void* p_data);
     48 static void rfc_mx_sm_sabme_wait_ua(tRFC_MCB* p_mcb, uint16_t event,
     49                                     void* p_data);
     50 static void rfc_mx_sm_state_wait_sabme(tRFC_MCB* p_mcb, uint16_t event,
     51                                        void* p_data);
     52 static void rfc_mx_sm_state_connected(tRFC_MCB* p_mcb, uint16_t event,
     53                                       UNUSED_ATTR void* p_data);
     54 static void rfc_mx_sm_state_disc_wait_ua(tRFC_MCB* p_mcb, uint16_t event,
     55                                          void* p_data);
     56 
     57 static void rfc_mx_send_config_req(tRFC_MCB* p_mcb);
     58 static void rfc_mx_conf_ind(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg);
     59 static void rfc_mx_conf_cnf(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg);
     60 
     61 /*******************************************************************************
     62  *
     63  * Function         rfc_mx_sm_execute
     64  *
     65  * Description      This function sends multiplexor events through the state
     66  *                  machine.
     67  *
     68  * Returns          void
     69  *
     70  ******************************************************************************/
     71 void rfc_mx_sm_execute(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
     72   switch (p_mcb->state) {
     73     case RFC_MX_STATE_IDLE:
     74       rfc_mx_sm_state_idle(p_mcb, event, p_data);
     75       break;
     76 
     77     case RFC_MX_STATE_WAIT_CONN_CNF:
     78       rfc_mx_sm_state_wait_conn_cnf(p_mcb, event, p_data);
     79       break;
     80 
     81     case RFC_MX_STATE_CONFIGURE:
     82       rfc_mx_sm_state_configure(p_mcb, event, p_data);
     83       break;
     84 
     85     case RFC_MX_STATE_SABME_WAIT_UA:
     86       rfc_mx_sm_sabme_wait_ua(p_mcb, event, p_data);
     87       break;
     88 
     89     case RFC_MX_STATE_WAIT_SABME:
     90       rfc_mx_sm_state_wait_sabme(p_mcb, event, p_data);
     91       break;
     92 
     93     case RFC_MX_STATE_CONNECTED:
     94       rfc_mx_sm_state_connected(p_mcb, event, p_data);
     95       break;
     96 
     97     case RFC_MX_STATE_DISC_WAIT_UA:
     98       rfc_mx_sm_state_disc_wait_ua(p_mcb, event, p_data);
     99       break;
    100   }
    101 }
    102 
    103 /*******************************************************************************
    104  *
    105  * Function         rfc_mx_sm_state_idle
    106  *
    107  * Description      This function handles events when the multiplexer is in
    108  *                  IDLE state. This state exists when connection is being
    109  *                  initially established.
    110  *
    111  * Returns          void
    112  *
    113  ******************************************************************************/
    114 void rfc_mx_sm_state_idle(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
    115   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_idle - evt:%d", event);
    116   switch (event) {
    117     case RFC_MX_EVENT_START_REQ: {
    118       /* Initialize L2CAP MTU */
    119       p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1;
    120 
    121       uint16_t lcid = L2CA_ConnectReq(BT_PSM_RFCOMM, p_mcb->bd_addr);
    122       if (lcid == 0) {
    123         rfc_save_lcid_mcb(NULL, p_mcb->lcid);
    124         p_mcb->lcid = 0;
    125         PORT_StartCnf(p_mcb, RFCOMM_ERROR);
    126         return;
    127       }
    128       p_mcb->lcid = lcid;
    129       /* Save entry for quicker access to mcb based on the LCID */
    130       rfc_save_lcid_mcb(p_mcb, p_mcb->lcid);
    131 
    132       p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF;
    133       return;
    134     }
    135 
    136     case RFC_MX_EVENT_START_RSP:
    137     case RFC_MX_EVENT_CONN_CNF:
    138     case RFC_MX_EVENT_CONF_IND:
    139     case RFC_MX_EVENT_CONF_CNF:
    140       RFCOMM_TRACE_ERROR("Mx error state %d event %d", p_mcb->state, event);
    141       return;
    142 
    143     case RFC_MX_EVENT_CONN_IND:
    144 
    145       rfc_timer_start(p_mcb, RFCOMM_CONN_TIMEOUT);
    146       L2CA_ConnectRsp(p_mcb->bd_addr, *((uint8_t*)p_data), p_mcb->lcid,
    147                       L2CAP_CONN_OK, 0);
    148 
    149       rfc_mx_send_config_req(p_mcb);
    150 
    151       p_mcb->state = RFC_MX_STATE_CONFIGURE;
    152       return;
    153 
    154     case RFC_EVENT_SABME:
    155       break;
    156 
    157     case RFC_EVENT_UA:
    158     case RFC_EVENT_DM:
    159       return;
    160 
    161     case RFC_EVENT_DISC:
    162       rfc_send_dm(p_mcb, RFCOMM_MX_DLCI, true);
    163       return;
    164 
    165     case RFC_EVENT_UIH:
    166       rfc_send_dm(p_mcb, RFCOMM_MX_DLCI, false);
    167       return;
    168   }
    169   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    170                      p_mcb->state);
    171 }
    172 
    173 /*******************************************************************************
    174  *
    175  * Function         rfc_mx_sm_state_wait_conn_cnf
    176  *
    177  * Description      This function handles events when the multiplexer is
    178  *                  waiting for Connection Confirm from L2CAP.
    179  *
    180  * Returns          void
    181  *
    182  ******************************************************************************/
    183 void rfc_mx_sm_state_wait_conn_cnf(tRFC_MCB* p_mcb, uint16_t event,
    184                                    void* p_data) {
    185   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_wait_conn_cnf - evt:%d", event);
    186   switch (event) {
    187     case RFC_MX_EVENT_START_REQ:
    188       RFCOMM_TRACE_ERROR("Mx error state %d event %d", p_mcb->state, event);
    189       return;
    190 
    191     /* There is some new timing so that Config Ind comes before security is
    192        completed
    193        so we are still waiting fo the confirmation. */
    194     case RFC_MX_EVENT_CONF_IND:
    195       rfc_mx_conf_ind(p_mcb, (tL2CAP_CFG_INFO*)p_data);
    196       return;
    197 
    198     case RFC_MX_EVENT_CONN_CNF:
    199       if (*((uint16_t*)p_data) != L2CAP_SUCCESS) {
    200         p_mcb->state = RFC_MX_STATE_IDLE;
    201 
    202         PORT_StartCnf(p_mcb, *((uint16_t*)p_data));
    203         return;
    204       }
    205       p_mcb->state = RFC_MX_STATE_CONFIGURE;
    206       rfc_mx_send_config_req(p_mcb);
    207       return;
    208 
    209     case RFC_MX_EVENT_DISC_IND:
    210       p_mcb->state = RFC_MX_STATE_IDLE;
    211       PORT_CloseInd(p_mcb);
    212       return;
    213 
    214     case RFC_EVENT_TIMEOUT:
    215       p_mcb->state = RFC_MX_STATE_IDLE;
    216       L2CA_DisconnectReq(p_mcb->lcid);
    217 
    218       /* we gave up outgoing connection request then try peer's request */
    219       if (p_mcb->pending_lcid) {
    220         uint16_t i;
    221         uint8_t idx;
    222 
    223         RFCOMM_TRACE_DEBUG(
    224             "RFCOMM MX retry as acceptor in collision case - evt:%d in "
    225             "state:%d",
    226             event, p_mcb->state);
    227 
    228         rfc_save_lcid_mcb(NULL, p_mcb->lcid);
    229         p_mcb->lcid = p_mcb->pending_lcid;
    230         rfc_save_lcid_mcb(p_mcb, p_mcb->lcid);
    231 
    232         p_mcb->is_initiator = false;
    233 
    234         /* update direction bit */
    235         for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
    236           idx = p_mcb->port_inx[i];
    237           if (idx != 0) {
    238             p_mcb->port_inx[i] = 0;
    239             p_mcb->port_inx[i + 1] = idx;
    240             rfc_cb.port.port[idx - 1].dlci += 1;
    241             RFCOMM_TRACE_DEBUG("RFCOMM MX - DLCI:%d -> %d", i,
    242                                rfc_cb.port.port[idx - 1].dlci);
    243           }
    244         }
    245 
    246         rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONN_IND, &(p_mcb->pending_id));
    247       } else {
    248         PORT_CloseInd(p_mcb);
    249       }
    250       return;
    251   }
    252   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    253                      p_mcb->state);
    254 }
    255 
    256 /*******************************************************************************
    257  *
    258  * Function         rfc_mx_sm_state_configure
    259  *
    260  * Description      This function handles events when the multiplexer in the
    261  *                  configuration state.
    262  *
    263  * Returns          void
    264  *
    265  ******************************************************************************/
    266 void rfc_mx_sm_state_configure(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
    267   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_configure - evt:%d", event);
    268   switch (event) {
    269     case RFC_MX_EVENT_START_REQ:
    270     case RFC_MX_EVENT_CONN_CNF:
    271 
    272       RFCOMM_TRACE_ERROR("Mx error state %d event %d", p_mcb->state, event);
    273       return;
    274 
    275     case RFC_MX_EVENT_CONF_IND:
    276       rfc_mx_conf_ind(p_mcb, (tL2CAP_CFG_INFO*)p_data);
    277       return;
    278 
    279     case RFC_MX_EVENT_CONF_CNF:
    280       rfc_mx_conf_cnf(p_mcb, (tL2CAP_CFG_INFO*)p_data);
    281       return;
    282 
    283     case RFC_MX_EVENT_DISC_IND:
    284       p_mcb->state = RFC_MX_STATE_IDLE;
    285       PORT_CloseInd(p_mcb);
    286       return;
    287 
    288     case RFC_EVENT_TIMEOUT:
    289       p_mcb->state = RFC_MX_STATE_IDLE;
    290       L2CA_DisconnectReq(p_mcb->lcid);
    291 
    292       PORT_StartCnf(p_mcb, RFCOMM_ERROR);
    293       return;
    294   }
    295   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    296                      p_mcb->state);
    297 }
    298 
    299 /*******************************************************************************
    300  *
    301  * Function         rfc_mx_sm_sabme_wait_ua
    302  *
    303  * Description      This function handles events when the multiplexer sent
    304  *                  SABME and is waiting for UA reply.
    305  *
    306  * Returns          void
    307  *
    308  ******************************************************************************/
    309 void rfc_mx_sm_sabme_wait_ua(tRFC_MCB* p_mcb, uint16_t event,
    310                              UNUSED_ATTR void* p_data) {
    311   RFCOMM_TRACE_EVENT("rfc_mx_sm_sabme_wait_ua - evt:%d", event);
    312   switch (event) {
    313     case RFC_MX_EVENT_START_REQ:
    314     case RFC_MX_EVENT_CONN_CNF:
    315       RFCOMM_TRACE_ERROR("Mx error state %d event %d", p_mcb->state, event);
    316       return;
    317 
    318     /* workaround: we don't support reconfig */
    319     /* commented out until we support reconfig
    320     case RFC_MX_EVENT_CONF_IND:
    321         rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data);
    322         return;
    323 
    324     case RFC_MX_EVENT_CONF_CNF:
    325         rfc_mx_conf_cnf (p_mcb, (tL2CAP_CFG_INFO *)p_data);
    326         return;
    327     */
    328 
    329     case RFC_MX_EVENT_DISC_IND:
    330       p_mcb->state = RFC_MX_STATE_IDLE;
    331       PORT_CloseInd(p_mcb);
    332       return;
    333 
    334     case RFC_EVENT_UA:
    335       rfc_timer_stop(p_mcb);
    336 
    337       p_mcb->state = RFC_MX_STATE_CONNECTED;
    338       p_mcb->peer_ready = true;
    339 
    340       PORT_StartCnf(p_mcb, RFCOMM_SUCCESS);
    341       return;
    342 
    343     case RFC_EVENT_DM:
    344       rfc_timer_stop(p_mcb);
    345     /* Case falls through */
    346 
    347     case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */
    348     case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */
    349     case RFC_EVENT_TIMEOUT:
    350       p_mcb->state = RFC_MX_STATE_IDLE;
    351       L2CA_DisconnectReq(p_mcb->lcid);
    352 
    353       PORT_StartCnf(p_mcb, RFCOMM_ERROR);
    354       return;
    355   }
    356   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    357                      p_mcb->state);
    358 }
    359 
    360 /*******************************************************************************
    361  *
    362  * Function         rfc_mx_sm_state_wait_sabme
    363  *
    364  * Description      This function handles events when the multiplexer is
    365  *                  waiting for SABME on the acceptor side after configuration
    366  *
    367  * Returns          void
    368  *
    369  ******************************************************************************/
    370 void rfc_mx_sm_state_wait_sabme(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
    371   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_wait_sabme - evt:%d", event);
    372   switch (event) {
    373     case RFC_MX_EVENT_DISC_IND:
    374       p_mcb->state = RFC_MX_STATE_IDLE;
    375       PORT_CloseInd(p_mcb);
    376       return;
    377 
    378     case RFC_EVENT_SABME:
    379       /* if we gave up outgoing connection request */
    380       if (p_mcb->pending_lcid) {
    381         p_mcb->pending_lcid = 0;
    382 
    383         rfc_send_ua(p_mcb, RFCOMM_MX_DLCI);
    384 
    385         rfc_timer_stop(p_mcb);
    386         p_mcb->state = RFC_MX_STATE_CONNECTED;
    387         p_mcb->peer_ready = true;
    388 
    389         /* MX channel collision has been resolved, continue to open ports */
    390         PORT_StartCnf(p_mcb, RFCOMM_SUCCESS);
    391       } else {
    392         rfc_timer_stop(p_mcb);
    393         PORT_StartInd(p_mcb);
    394       }
    395       return;
    396 
    397     case RFC_MX_EVENT_START_RSP:
    398       if (*((uint16_t*)p_data) != RFCOMM_SUCCESS)
    399         rfc_send_dm(p_mcb, RFCOMM_MX_DLCI, true);
    400       else {
    401         rfc_send_ua(p_mcb, RFCOMM_MX_DLCI);
    402 
    403         p_mcb->state = RFC_MX_STATE_CONNECTED;
    404         p_mcb->peer_ready = true;
    405         PORT_StartCnf(p_mcb, RFCOMM_SUCCESS);
    406       }
    407       return;
    408 
    409     case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */
    410     case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */
    411     case RFC_EVENT_TIMEOUT:
    412       p_mcb->state = RFC_MX_STATE_IDLE;
    413       L2CA_DisconnectReq(p_mcb->lcid);
    414 
    415       PORT_CloseInd(p_mcb);
    416       return;
    417   }
    418   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    419                      p_mcb->state);
    420 }
    421 
    422 /*******************************************************************************
    423  *
    424  * Function         rfc_mx_sm_state_connected
    425  *
    426  * Description      This function handles events when the multiplexer is
    427  *                  in the CONNECTED state
    428  *
    429  * Returns          void
    430  *
    431  ******************************************************************************/
    432 void rfc_mx_sm_state_connected(tRFC_MCB* p_mcb, uint16_t event,
    433                                UNUSED_ATTR void* p_data) {
    434   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_connected - evt:%d", event);
    435 
    436   switch (event) {
    437     case RFC_EVENT_TIMEOUT:
    438     case RFC_MX_EVENT_CLOSE_REQ:
    439       rfc_timer_start(p_mcb, RFC_DISC_TIMEOUT);
    440       p_mcb->state = RFC_MX_STATE_DISC_WAIT_UA;
    441       rfc_send_disc(p_mcb, RFCOMM_MX_DLCI);
    442       return;
    443 
    444     case RFC_MX_EVENT_DISC_IND:
    445       p_mcb->state = RFC_MX_STATE_IDLE;
    446       PORT_CloseInd(p_mcb);
    447       return;
    448 
    449     case RFC_EVENT_DISC:
    450       /* Reply with UA.  If initiator bring down L2CAP connection */
    451       /* If server wait for some time if client decide to reinitiate channel */
    452       rfc_send_ua(p_mcb, RFCOMM_MX_DLCI);
    453       if (p_mcb->is_initiator) {
    454         L2CA_DisconnectReq(p_mcb->lcid);
    455       }
    456       /* notify all ports that connection is gone */
    457       PORT_CloseInd(p_mcb);
    458       return;
    459   }
    460   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    461                      p_mcb->state);
    462 }
    463 
    464 /*******************************************************************************
    465  *
    466  * Function         rfc_mx_sm_state_disc_wait_ua
    467  *
    468  * Description      This function handles events when the multiplexer sent
    469  *                  DISC and is waiting for UA reply.
    470  *
    471  * Returns          void
    472  *
    473  ******************************************************************************/
    474 void rfc_mx_sm_state_disc_wait_ua(tRFC_MCB* p_mcb, uint16_t event,
    475                                   void* p_data) {
    476   BT_HDR* p_buf;
    477 
    478   RFCOMM_TRACE_EVENT("rfc_mx_sm_state_disc_wait_ua - evt:%d", event);
    479   switch (event) {
    480     case RFC_EVENT_UA:
    481     case RFC_EVENT_DM:
    482     case RFC_EVENT_TIMEOUT:
    483       L2CA_DisconnectReq(p_mcb->lcid);
    484 
    485       if (p_mcb->restart_required) {
    486         /* Start Request was received while disconnecting.  Execute it again */
    487         uint16_t lcid = L2CA_ConnectReq(BT_PSM_RFCOMM, p_mcb->bd_addr);
    488         if (lcid == 0) {
    489           rfc_save_lcid_mcb(NULL, p_mcb->lcid);
    490           p_mcb->lcid = 0;
    491           PORT_StartCnf(p_mcb, RFCOMM_ERROR);
    492           return;
    493         }
    494         p_mcb->lcid = lcid;
    495         /* Save entry for quicker access to mcb based on the LCID */
    496         rfc_save_lcid_mcb(p_mcb, p_mcb->lcid);
    497 
    498         /* clean up before reuse it */
    499         while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_mcb->cmd_q)) != NULL)
    500           osi_free(p_buf);
    501 
    502         rfc_timer_start(p_mcb, RFC_MCB_INIT_INACT_TIMER);
    503 
    504         p_mcb->is_initiator = true;
    505         p_mcb->restart_required = false;
    506         p_mcb->local_cfg_sent = false;
    507         p_mcb->peer_cfg_rcvd = false;
    508 
    509         p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF;
    510         return;
    511       }
    512       rfc_release_multiplexer_channel(p_mcb);
    513       return;
    514 
    515     case RFC_EVENT_DISC:
    516       rfc_send_ua(p_mcb, RFCOMM_MX_DLCI);
    517       return;
    518 
    519     case RFC_EVENT_UIH:
    520       osi_free(p_data);
    521       rfc_send_dm(p_mcb, RFCOMM_MX_DLCI, false);
    522       return;
    523 
    524     case RFC_MX_EVENT_START_REQ:
    525       p_mcb->restart_required = true;
    526       return;
    527 
    528     case RFC_MX_EVENT_DISC_IND:
    529       p_mcb->state = RFC_MX_STATE_IDLE;
    530       PORT_CloseInd(p_mcb);
    531       return;
    532 
    533     case RFC_MX_EVENT_CLOSE_REQ:
    534       return;
    535 
    536     case RFC_MX_EVENT_QOS_VIOLATION_IND:
    537       break;
    538   }
    539   RFCOMM_TRACE_EVENT("RFCOMM MX ignored - evt:%d in state:%d", event,
    540                      p_mcb->state);
    541 }
    542 
    543 /*******************************************************************************
    544  *
    545  * Function         rfc_mx_send_config_req
    546  *
    547  * Description      This function handles L2CA_ConnectInd message from the
    548  *                  L2CAP.  Accept connection.
    549  *
    550  ******************************************************************************/
    551 static void rfc_mx_send_config_req(tRFC_MCB* p_mcb) {
    552   tL2CAP_CFG_INFO cfg;
    553 
    554   RFCOMM_TRACE_EVENT("rfc_mx_send_config_req");
    555 
    556   memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
    557 
    558   cfg.mtu_present = true;
    559   cfg.mtu = L2CAP_MTU_SIZE;
    560 
    561   /* Defaults set by memset
    562       cfg.flush_to_present = false;
    563       cfg.qos_present      = false;
    564       cfg.fcr_present      = false;
    565       cfg.fcr.mode         = L2CAP_FCR_BASIC_MODE;
    566       cfg.fcs_present      = false;
    567       cfg.fcs              = N/A when fcs_present is false;
    568   */
    569   L2CA_ConfigReq(p_mcb->lcid, &cfg);
    570 }
    571 
    572 /*******************************************************************************
    573  *
    574  * Function         rfc_mx_conf_cnf
    575  *
    576  * Description      This function handles L2CA_ConfigCnf message from the
    577  *                  L2CAP.  If result is not success tell upper layer that
    578  *                  start has not been accepted.  If initiator send SABME
    579  *                  on DLCI 0.  T1 is still running.
    580  *
    581  ******************************************************************************/
    582 static void rfc_mx_conf_cnf(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg) {
    583   RFCOMM_TRACE_EVENT("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg,
    584                      (p_cfg) ? p_cfg->result : 0);
    585 
    586   if (p_cfg->result != L2CAP_CFG_OK) {
    587     if (p_mcb->is_initiator) {
    588       PORT_StartCnf(p_mcb, p_cfg->result);
    589       L2CA_DisconnectReq(p_mcb->lcid);
    590     }
    591     rfc_release_multiplexer_channel(p_mcb);
    592     return;
    593   }
    594 
    595   p_mcb->local_cfg_sent = true;
    596   if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->peer_cfg_rcvd) {
    597     if (p_mcb->is_initiator) {
    598       p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA;
    599       rfc_send_sabme(p_mcb, RFCOMM_MX_DLCI);
    600       rfc_timer_start(p_mcb, RFC_T1_TIMEOUT);
    601     } else {
    602       p_mcb->state = RFC_MX_STATE_WAIT_SABME;
    603       rfc_timer_start(
    604           p_mcb, RFCOMM_CONN_TIMEOUT); /* - increased from T2=20 to CONN=120
    605                              to allow the user more than 10 sec to type in the
    606                              pin which can be e.g. 16 digits */
    607     }
    608   }
    609 }
    610 
    611 /*******************************************************************************
    612  *
    613  * Function         rfc_mx_conf_ind
    614  *
    615  * Description      This function handles L2CA_ConfigInd message from the
    616  *                  L2CAP.  Send the L2CA_ConfigRsp message.
    617  *
    618  ******************************************************************************/
    619 static void rfc_mx_conf_ind(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg) {
    620   /* Save peer L2CAP MTU if present */
    621   /* RFCOMM adds 3-4 bytes in the beginning and 1 bytes FCS */
    622   if (p_cfg->mtu_present)
    623     p_mcb->peer_l2cap_mtu = p_cfg->mtu - RFCOMM_MIN_OFFSET - 1;
    624   else
    625     p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1;
    626 
    627   p_cfg->mtu_present = false;
    628   p_cfg->flush_to_present = false;
    629   p_cfg->qos_present = false;
    630 
    631   p_cfg->result = L2CAP_CFG_OK;
    632 
    633   L2CA_ConfigRsp(p_mcb->lcid, p_cfg);
    634 
    635   p_mcb->peer_cfg_rcvd = true;
    636   if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->local_cfg_sent) {
    637     if (p_mcb->is_initiator) {
    638       p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA;
    639       rfc_send_sabme(p_mcb, RFCOMM_MX_DLCI);
    640       rfc_timer_start(p_mcb, RFC_T1_TIMEOUT);
    641     } else {
    642       p_mcb->state = RFC_MX_STATE_WAIT_SABME;
    643       rfc_timer_start(
    644           p_mcb, RFCOMM_CONN_TIMEOUT); /* - increased from T2=20 to CONN=120
    645                              to allow the user more than 10 sec to type in the
    646                              pin which can be e.g. 16 digits */
    647     }
    648   }
    649 }
    650