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