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