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/********************************************************************************/
42static void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
43static void rfc_mx_sm_state_wait_conn_cnf (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
44static void rfc_mx_sm_state_configure (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
45static void rfc_mx_sm_sabme_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
46static void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
47static void rfc_mx_sm_state_connected (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
48static void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data);
49
50static void rfc_mx_send_config_req (tRFC_MCB *p_mcb);
51static void rfc_mx_conf_ind (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg);
52static 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*******************************************************************************/
66void 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*******************************************************************************/
113void 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*******************************************************************************/
180void 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*******************************************************************************/
264void 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*******************************************************************************/
309void 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*******************************************************************************/
370void 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*******************************************************************************/
437void 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*******************************************************************************/
481void 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*******************************************************************************/
557static 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*******************************************************************************/
590static 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*******************************************************************************/
631static 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