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