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