• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *******************************************************************************/
rfc_mx_sm_execute(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_idle(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_wait_conn_cnf(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_configure(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_sabme_wait_ua(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_wait_sabme(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_connected(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_sm_state_disc_wait_ua(tRFC_MCB * p_mcb,UINT16 event,void * p_data)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 *******************************************************************************/
rfc_mx_send_config_req(tRFC_MCB * p_mcb)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 *******************************************************************************/
rfc_mx_conf_cnf(tRFC_MCB * p_mcb,tL2CAP_CFG_INFO * p_cfg)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 *******************************************************************************/
rfc_mx_conf_ind(tRFC_MCB * p_mcb,tL2CAP_CFG_INFO * p_cfg)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