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