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 module contains functions for port emulation entity and RFCOMM
22 * communications
23 *
24 ******************************************************************************/
25
26 #define LOG_TAG "rfcomm"
27
28 #include <base/functional/callback.h>
29 #include <bluetooth/log.h>
30 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
31
32 #include <cstdint>
33
34 #include "hal/snoop_logger.h"
35 #include "internal_include/bt_target.h"
36 #include "internal_include/bt_trace.h"
37 #include "main/shim/entry.h"
38 #include "os/logging/log_adapter.h"
39 #include "osi/include/allocator.h"
40 #include "osi/include/mutex.h"
41 #include "stack/include/bt_hdr.h"
42 #include "stack/include/bt_uuid16.h"
43 #include "stack/include/stack_metrics_logging.h"
44 #include "stack/l2cap/l2c_int.h"
45 #include "stack/rfcomm/port_int.h"
46 #include "stack/rfcomm/rfc_int.h"
47
48 using namespace bluetooth;
49
50 /*
51 * Local function definitions
52 */
53 uint32_t port_rfc_send_tx_data(tPORT* p_port);
54 void port_rfc_closed(tPORT* p_port, uint8_t res);
55 void port_get_credits(tPORT* p_port, uint8_t k);
56
57 /*******************************************************************************
58 *
59 * Function port_open_continue
60 *
61 * Description This function is called after security manager completes
62 * required security checks.
63 *
64 * Returns PORT_SUCCESS or PORT_[ERROR]
65 *
66 ******************************************************************************/
port_open_continue(tPORT * p_port)67 int port_open_continue(tPORT* p_port) {
68 log::verbose("port_open_continue, p_port:{}", std::format_ptr(p_port));
69
70 /* Check if multiplexer channel has already been established */
71 tRFC_MCB* p_mcb = rfc_alloc_multiplexer_channel(p_port->bd_addr, true);
72 if (p_mcb == nullptr) {
73 log::warn("port_open_continue no mx channel");
74 port_release_port(p_port);
75 return PORT_NO_RESOURCES;
76 }
77
78 p_port->rfc.p_mcb = p_mcb;
79
80 p_mcb->port_handles[p_port->dlci] = p_port->handle;
81
82 /* Connection is up and we know local and remote features, select MTU */
83 port_select_mtu(p_port);
84
85 switch (p_mcb->state) {
86 case RFC_MX_STATE_CONNECTED:
87 RFCOMM_ParameterNegotiationRequest(p_mcb, p_port->dlci, p_port->mtu);
88 log::verbose("Multiplexer already connected peer:{} state:{} cid:{}", p_port->bd_addr,
89 p_mcb->state, p_mcb->lcid);
90 break;
91
92 case RFC_MX_STATE_IDLE:
93 case RFC_MX_STATE_DISC_WAIT_UA:
94 // In RFC_MX_STATE_IDLE state, MX state machine will create connection
95 // In RFC_MX_STATE_DISC_WAIT_UA state, MX state machine will recreate
96 // connection after disconnecting is completed
97 RFCOMM_StartReq(p_mcb);
98 log::verbose("Starting multiplexer connect peer:{} state:{} cid:{}", p_port->bd_addr,
99 p_mcb->state, p_mcb->lcid);
100 break;
101
102 default:
103 // MX state machine ignores RFC_MX_EVENT_START_REQ in these states
104 // When it enters RFC_MX_STATE_CONNECTED, it will check any opening ports
105 log::verbose("Ignoring RFC_MX_EVENT_START_REQ peer:{} state:{} cid:{}", p_port->bd_addr,
106 p_mcb->state, p_mcb->lcid);
107 break;
108 }
109 return PORT_SUCCESS;
110 }
111
112 /*******************************************************************************
113 *
114 * Function port_start_control
115 *
116 * Description This function is called in the BTU_TASK context to
117 * send control information
118 *
119 ******************************************************************************/
port_start_control(tPORT * p_port)120 void port_start_control(tPORT* p_port) {
121 tRFC_MCB* p_mcb = p_port->rfc.p_mcb;
122
123 if (p_mcb == NULL) {
124 return;
125 }
126
127 RFCOMM_ControlReq(p_mcb, p_port->dlci, &p_port->local_ctrl);
128 }
129
130 /*******************************************************************************
131 *
132 * Function port_start_par_neg
133 *
134 * Description This function is called in the BTU_TASK context to
135 * send configuration information
136 *
137 ******************************************************************************/
port_start_par_neg(tPORT * p_port)138 void port_start_par_neg(tPORT* p_port) {
139 tRFC_MCB* p_mcb = p_port->rfc.p_mcb;
140
141 if (p_mcb == NULL) {
142 return;
143 }
144
145 RFCOMM_PortParameterNegotiationRequest(p_mcb, p_port->dlci, &p_port->user_port_settings);
146 }
147
148 /*******************************************************************************
149 *
150 * Function port_start_close
151 *
152 * Description This function is called in the BTU_TASK context to
153 * release DLC
154 *
155 ******************************************************************************/
port_start_close(tPORT * p_port)156 void port_start_close(tPORT* p_port) {
157 tRFC_MCB* p_mcb = p_port->rfc.p_mcb;
158 uint8_t old_signals;
159 uint32_t events = 0;
160
161 /* At first indicate to the user that signals on the connection were dropped
162 */
163 p_port->line_status |= LINE_STATUS_FAILED;
164 old_signals = p_port->peer_ctrl.modem_signal;
165
166 p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
167
168 events |= port_get_signal_changes(p_port, old_signals, p_port->peer_ctrl.modem_signal);
169
170 if (p_port->ev_mask & PORT_EV_CONNECT_ERR) {
171 events |= PORT_EV_CONNECT_ERR;
172 }
173
174 if (p_port->ev_mask & PORT_EV_ERR) {
175 events |= PORT_EV_ERR;
176 }
177
178 if ((p_port->p_callback != NULL) && events) {
179 p_port->p_callback(events, p_port->handle);
180 }
181
182 /* Check if RFCOMM side has been closed while the message was queued */
183 if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) {
184 /* Call management callback function before calling port_release_port() to
185 * clear tPort */
186 if (p_port->p_mgmt_callback) {
187 p_port->p_mgmt_callback(PORT_CLOSED, p_port->handle);
188 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CLOSE, 1);
189 }
190
191 port_release_port(p_port);
192 } else {
193 RFCOMM_DlcReleaseReq(p_mcb, p_port->dlci);
194 }
195 }
196
197 /*******************************************************************************
198 *
199 * Function PORT_StartCnf
200 *
201 * Description This function is called from the RFCOMM layer when
202 * establishing of the multiplexer channel is completed.
203 * Continue establishing of the connection for all ports that
204 * are in the OPENING state
205 *
206 ******************************************************************************/
PORT_StartCnf(tRFC_MCB * p_mcb,uint16_t result)207 void PORT_StartCnf(tRFC_MCB* p_mcb, uint16_t result) {
208 bool no_ports_up = true;
209
210 log::verbose("result {}", result);
211
212 tPORT* p_port = &rfc_cb.port.port[0];
213 for (int i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
214 if (p_port->rfc.p_mcb == p_mcb) {
215 no_ports_up = false;
216
217 if (result == RFCOMM_SUCCESS) {
218 log::verbose("dlci {}", p_port->dlci);
219 RFCOMM_ParameterNegotiationRequest(p_mcb, p_port->dlci, p_port->mtu);
220 } else {
221 log::warn("Unable start configuration dlci:{} result:{}", p_port->dlci, result);
222
223 rfc_release_multiplexer_channel(p_mcb);
224
225 /* Send event to the application */
226 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR)) {
227 (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->handle);
228 }
229
230 if (p_port->p_mgmt_callback) {
231 p_port->p_mgmt_callback(PORT_START_FAILED, p_port->handle);
232 log_counter_metrics(
233 android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CNF_FAILED, 1);
234 }
235 port_release_port(p_port);
236 }
237 }
238 }
239
240 /* There can be a situation when after starting connection, user closes the */
241 /* port, we can catch it here to close multiplexor channel */
242 if (no_ports_up) {
243 rfc_check_mcb_active(p_mcb);
244 }
245 }
246
247 /*******************************************************************************
248 *
249 * Function PORT_StartInd
250 *
251 * Description This function is called from the RFCOMM layer when
252 * some peer device wants to establish a multiplexer
253 * connection. Check if there are any ports open with this
254 * or not assigned multiplexer.
255 *
256 ******************************************************************************/
PORT_StartInd(tRFC_MCB * p_mcb)257 void PORT_StartInd(tRFC_MCB* p_mcb) {
258 tPORT* p_port;
259 int i;
260
261 log::verbose("PORT_StartInd");
262
263 p_port = &rfc_cb.port.port[0];
264 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
265 if ((p_port->rfc.p_mcb == NULL) || (p_port->rfc.p_mcb == p_mcb)) {
266 log::verbose("PORT_StartInd, RFCOMM_StartRsp RFCOMM_SUCCESS: p_mcb:{}",
267 std::format_ptr(p_mcb));
268 RFCOMM_StartRsp(p_mcb, RFCOMM_SUCCESS);
269 return;
270 }
271 }
272 RFCOMM_StartRsp(p_mcb, RFCOMM_ERROR);
273 }
274
275 /*******************************************************************************
276 *
277 * Function PORT_ParNegInd
278 *
279 * Description This function is called from the RFCOMM layer to change
280 * DLCI parameters (currently only MTU is negotiated).
281 * If can not find the port do not accept the request.
282 * Otherwise save the MTU size supported by the peer.
283 *
284 ******************************************************************************/
PORT_ParNegInd(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu,uint8_t cl,uint8_t k)285 void PORT_ParNegInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl, uint8_t k) {
286 log::verbose("bd_addr={}, dlci={}, mtu={}", p_mcb->bd_addr, dlci, mtu);
287 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
288 if (!p_port) {
289 /* This can be a first request for this port */
290 p_port = port_find_dlci_port(dlci);
291 if (!p_port) {
292 log::error("Disconnect RFCOMM, port not found, dlci={}, p_mcb={}, bd_addr={}", dlci,
293 std::format_ptr(p_mcb), p_mcb->bd_addr);
294 /* If the port cannot be opened, send a DM. Per Errata 1205 */
295 rfc_send_dm(p_mcb, dlci, false);
296 /* check if this is the last port open, some headsets have
297 problem, they don't disconnect if we send DM */
298 rfc_check_mcb_active(p_mcb);
299 return;
300 }
301 log::verbose("port_handles[dlci:{}]:{}->{}", dlci, p_mcb->port_handles[dlci], p_port->handle);
302 p_mcb->port_handles[dlci] = p_port->handle;
303 }
304
305 p_port->bd_addr = p_mcb->bd_addr;
306
307 /* Connection is up and we know local and remote features, select MTU */
308 port_select_mtu(p_port);
309
310 p_port->rfc.p_mcb = p_mcb;
311 p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu;
312 p_port->peer_mtu = p_port->mtu;
313
314 /* Negotiate the flow control mechanism. If flow control mechanism for */
315 /* mux has not been set yet, set it now. If either we or peer wants TS 07.10,
316 */
317 /* use that. Otherwise both must want credit based, so use that. If flow is
318 */
319 /* already defined for this mux, we respond with that value. */
320 if (p_mcb->flow == PORT_FC_UNDEFINED) {
321 if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1) {
322 p_mcb->flow = PORT_FC_TS710;
323 } else {
324 p_mcb->flow = PORT_FC_CREDIT;
325 }
326 }
327
328 /* Regardless of our flow control mechanism, if the PN cl is zero, we must */
329 /* respond with zero. "A responding implementation must set this field to 14
330 */
331 /* if (and only if) the PN request was 15." This could happen if a PN is sent
332 */
333 /* after the DLCI is already established-- the PN in that case must have cl =
334 * 0. */
335 /* See RFCOMM spec 5.5.3 */
336 uint8_t our_cl;
337 uint8_t our_k;
338 if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1) {
339 our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
340 our_k = 0;
341 } else if (p_mcb->flow == PORT_FC_CREDIT) {
342 /* get credits */
343 port_get_credits(p_port, k);
344
345 /* Set convergence layer and number of credits (k) */
346 our_cl = RFCOMM_PN_CONV_LAYER_CBFC_R;
347 our_k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
348 p_port->credit_rx = our_k;
349 } else {
350 /* must not be using credit based flow control; use TS 7.10 */
351 our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
352 our_k = 0;
353 }
354 RFCOMM_ParameterNegotiationResponse(p_mcb, dlci, p_port->mtu, our_cl, our_k);
355 }
356
357 /*******************************************************************************
358 *
359 * Function PORT_ParNegCnf
360 *
361 * Description This function is called from the RFCOMM layer to change
362 * DLCI parameters (currently only MTU is negotiated).
363 * Save the MTU size supported by the peer.
364 * If the confirmation is received during the port opening
365 * procedure send EstablishRequest to continue.
366 *
367 ******************************************************************************/
PORT_ParNegCnf(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu,uint8_t cl,uint8_t k)368 void PORT_ParNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl, uint8_t k) {
369 log::verbose("PORT_ParNegCnf dlci:{} mtu:{} cl: {} k: {}", dlci, mtu, cl, k);
370 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
371 if (!p_port) {
372 log::warn("port is null for {}", p_mcb->bd_addr);
373 return;
374 }
375
376 /* Flow control mechanism not set yet. Negotiate flow control mechanism. */
377 if (p_mcb->flow == PORT_FC_UNDEFINED) {
378 if (cl == RFCOMM_PN_CONV_LAYER_CBFC_R) {
379 // Our stack is configured for credit-based and they responded with
380 // credit-based.
381 p_mcb->flow = PORT_FC_CREDIT;
382 } else {
383 // They responded with any other value. Treat this as negotiation to
384 // TS07.10.
385 p_mcb->flow = PORT_FC_TS710;
386 }
387 }
388 /* If mux flow control mechanism set, we honor that setting regardless of */
389 /* the CL value in their response. This allows us to gracefully accept any */
390 /* illegal PN negotiation scenarios. */
391
392 p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu;
393 p_port->peer_mtu = p_port->mtu;
394
395 if (p_mcb->flow == PORT_FC_CREDIT) {
396 port_get_credits(p_port, k);
397 }
398
399 if (p_port->state == PORT_CONNECTION_STATE_OPENING) {
400 RFCOMM_DlcEstablishReq(p_mcb, p_port->dlci, p_port->mtu);
401 }
402 }
403
404 /*******************************************************************************
405 *
406 * Function PORT_DlcEstablishInd
407 *
408 * Description This function is called from the RFCOMM layer when peer
409 * device wants to establish a new DLC. If this is not the
410 * first message in the establishment procedure port_handle
411 * has a handle to the port control block otherwise the control
412 * block should be found based on the muliplexer channel and
413 * dlci. The block should be allocated before meaning
414 * that application already made open.
415 *
416 ******************************************************************************/
PORT_DlcEstablishInd(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu)417 void PORT_DlcEstablishInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
418 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
419
420 log::verbose("p_mcb:{}, dlci:{} mtu:{}i, p_port:{}, bd_addr:{}", std::format_ptr(p_mcb), dlci,
421 mtu, std::format_ptr(p_port), p_mcb->bd_addr);
422
423 if (!p_port) {
424 /* This can be a first request for this port */
425 p_port = port_find_dlci_port(dlci);
426 if (!p_port) {
427 RFCOMM_DlcEstablishRsp(p_mcb, dlci, 0, RFCOMM_ERROR);
428 return;
429 }
430 p_mcb->port_handles[dlci] = p_port->handle;
431 }
432
433 /* If L2CAP's mtu less then RFCOMM's take it */
434 if (mtu && (mtu < p_port->peer_mtu)) {
435 p_port->peer_mtu = mtu;
436 }
437
438 /* If there was an inactivity timer running for MCB stop it */
439 rfc_timer_stop(p_mcb);
440
441 RFCOMM_DlcEstablishRsp(p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);
442
443 /* This is the server side. If application wants to know when connection */
444 /* is established, thats the place */
445 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED)) {
446 (p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
447 }
448
449 if (p_port->p_mgmt_callback) {
450 p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
451 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND,
452 1);
453 }
454
455 p_port->state = PORT_CONNECTION_STATE_OPENED;
456 }
457
458 /*******************************************************************************
459 *
460 * Function PORT_DlcEstablishCnf
461 *
462 * Description This function is called from the RFCOMM layer when peer
463 * acknowledges establish procedure (SABME/UA). Send reply
464 * to the user and set state to OPENED if result was
465 * successful.
466 *
467 ******************************************************************************/
PORT_DlcEstablishCnf(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu,uint16_t result)468 void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint16_t result) {
469 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
470
471 log::verbose("PORT_DlcEstablishCnf dlci:{} mtu:{} result:{}", dlci, mtu, result);
472
473 if (!p_port) {
474 return;
475 }
476
477 if (result != RFCOMM_SUCCESS) {
478 log::warn("Unable to establish configuration dlci:{} result:{}", dlci, result);
479 port_rfc_closed(p_port, PORT_START_FAILED);
480 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_FAILED, 1);
481 return;
482 }
483
484 /* If L2CAP's mtu less then RFCOMM's take it */
485 if (mtu && (mtu < p_port->peer_mtu)) {
486 p_port->peer_mtu = mtu;
487 }
488
489 /* If there was an inactivity timer running for MCB stop it */
490 rfc_timer_stop(p_mcb);
491
492 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED)) {
493 (p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
494 }
495
496 if (p_port->p_mgmt_callback) {
497 p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
498 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF,
499 1);
500 }
501 p_port->state = PORT_CONNECTION_STATE_OPENED;
502
503 /* RPN is required only if we want to tell DTE how the port should be opened
504 */
505 if ((p_port->uuid == UUID_SERVCLASS_DIALUP_NETWORKING) || (p_port->uuid == UUID_SERVCLASS_FAX)) {
506 RFCOMM_PortParameterNegotiationRequest(p_port->rfc.p_mcb, p_port->dlci, NULL);
507 } else {
508 RFCOMM_ControlReq(p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
509 }
510 }
511
512 /*******************************************************************************
513 *
514 * Function PORT_PortNegInd
515 *
516 * Description This function is called from the RFCOMM layer when peer
517 * device wants to set parameters of the port. As per the spec
518 * this message has to be sent before the first data packet
519 * and can be sent before establish. The block should be
520 * allocated before meaning that application already made open.
521 *
522 ******************************************************************************/
PORT_PortNegInd(tRFC_MCB * p_mcb,uint8_t dlci,PortSettings * p_settings,uint16_t param_mask)523 void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* p_settings, uint16_t param_mask) {
524 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
525
526 log::verbose("PORT_PortNegInd");
527
528 if (!p_port) {
529 /* This can be a first request for this port */
530 p_port = port_find_dlci_port(dlci);
531 if (!p_port) {
532 RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_settings, 0);
533 return;
534 }
535 p_mcb->port_handles[dlci] = p_port->handle;
536 }
537
538 /* Check if the flow control is acceptable on local side */
539 p_port->peer_port_settings = *p_settings;
540 RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_settings, param_mask);
541 }
542
543 /*******************************************************************************
544 *
545 * Function PORT_PortNegCnf
546 *
547 * Description This function is called from the RFCOMM layer to change
548 * state for the port. Propagate change to the user.
549 *
550 ******************************************************************************/
PORT_PortNegCnf(tRFC_MCB * p_mcb,uint8_t dlci,PortSettings *,uint16_t result)551 void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* /* p_settings */,
552 uint16_t result) {
553 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
554
555 log::verbose("PORT_PortNegCnf");
556
557 if (!p_port) {
558 log::warn("PORT_PortNegCnf no port");
559 return;
560 }
561 /* Port negotiation failed. Drop the connection */
562 if (result != RFCOMM_SUCCESS) {
563 log::warn("Unable to negotiate port state dlci:{} result:{}", dlci, result);
564 RFCOMM_DlcReleaseReq(p_mcb, p_port->dlci);
565
566 port_rfc_closed(p_port, PORT_PORT_NEG_FAILED);
567 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_NEG_FAILED, 1);
568 return;
569 }
570
571 if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT)) {
572 RFCOMM_ControlReq(p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
573 } else {
574 log::warn("PORT_PortNegCnf Control Already sent");
575 }
576 }
577
578 /*******************************************************************************
579 *
580 * Function PORT_ControlInd
581 *
582 * Description This function is called from the RFCOMM layer on the modem
583 * signal change. Propagate change to the user.
584 *
585 ******************************************************************************/
PORT_ControlInd(tRFC_MCB * p_mcb,uint8_t dlci,tPORT_CTRL * p_pars)586 void PORT_ControlInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) {
587 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
588 uint32_t event;
589 uint8_t old_signals;
590
591 log::verbose("PORT_ControlInd");
592
593 if (!p_port) {
594 return;
595 }
596
597 old_signals = p_port->peer_ctrl.modem_signal;
598
599 event = port_get_signal_changes(p_port, old_signals, p_pars->modem_signal);
600
601 p_port->peer_ctrl = *p_pars;
602
603 if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT)) {
604 RFCOMM_ControlReq(p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
605 } else {
606 /* If this is the first time we received control RFCOMM is connected */
607 if (!(p_port->port_ctrl & PORT_CTRL_IND_RECEIVED)) {
608 event |= (PORT_EV_CONNECTED & p_port->ev_mask);
609 }
610
611 if (p_port->port_ctrl & PORT_CTRL_REQ_CONFIRMED) {
612 event |= port_rfc_send_tx_data(p_port);
613 }
614 }
615
616 p_port->port_ctrl |= (PORT_CTRL_IND_RECEIVED | PORT_CTRL_IND_RESPONDED);
617
618 if (p_pars->break_signal) {
619 event |= (PORT_EV_BREAK & p_port->ev_mask);
620 }
621
622 /* execute call back function only if the application is registered for events
623 */
624 if (event && p_port->p_callback) {
625 (p_port->p_callback)(event, p_port->handle);
626 }
627
628 log::verbose("PORT_ControlInd DTR_DSR : {}, RTS_CTS : {}, RI : {}, DCD : {}",
629 (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0,
630 (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0,
631 (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0,
632 (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0);
633 }
634
635 /*******************************************************************************
636 *
637 * Function PORT_ControlCnf
638 *
639 * Description This function is called from the RFCOMM layer when
640 * peer acknowleges change of the modem signals.
641 *
642 ******************************************************************************/
PORT_ControlCnf(tRFC_MCB * p_mcb,uint8_t dlci,tPORT_CTRL *)643 void PORT_ControlCnf(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* /* p_pars */) {
644 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
645 uint32_t event = 0;
646
647 log::verbose("PORT_ControlCnf");
648
649 if (!p_port) {
650 return;
651 }
652
653 if (!(p_port->port_ctrl & PORT_CTRL_REQ_CONFIRMED)) {
654 p_port->port_ctrl |= PORT_CTRL_REQ_CONFIRMED;
655
656 if (p_port->port_ctrl & PORT_CTRL_IND_RECEIVED) {
657 event = (p_port->ev_mask & PORT_EV_CONNECTED);
658 }
659 }
660
661 if (p_port->port_ctrl & PORT_CTRL_IND_RECEIVED) {
662 event |= port_rfc_send_tx_data(p_port);
663 }
664
665 /* execute call back function only if the application is registered for events
666 */
667 if (event && p_port->p_callback) {
668 (p_port->p_callback)(event, p_port->handle);
669 }
670 }
671
672 /*******************************************************************************
673 *
674 * Function PORT_LineStatusInd
675 *
676 * Description This function is called from the RFCOMM layer when
677 * peer indicates change in the line status
678 *
679 ******************************************************************************/
PORT_LineStatusInd(tRFC_MCB * p_mcb,uint8_t dlci,uint8_t line_status)680 void PORT_LineStatusInd(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t line_status) {
681 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
682 uint32_t event = 0;
683
684 log::verbose("PORT_LineStatusInd");
685
686 if (!p_port) {
687 return;
688 }
689
690 p_port->line_status |= line_status;
691
692 if (line_status & PORT_ERR_OVERRUN) {
693 event |= PORT_EV_OVERRUN;
694 }
695
696 if (line_status & PORT_ERR_BREAK) {
697 event |= PORT_EV_BREAK;
698 }
699
700 if (line_status & ~(PORT_ERR_OVERRUN | PORT_ERR_BREAK)) {
701 event |= PORT_EV_ERR;
702 }
703
704 if ((p_port->p_callback != NULL) && (p_port->ev_mask & event)) {
705 p_port->p_callback((p_port->ev_mask & event), p_port->handle);
706 }
707 }
708
709 /*******************************************************************************
710 *
711 * Function PORT_DlcReleaseInd
712 *
713 * Description This function is called from the RFCOMM layer when
714 * DLC connection is released.
715 *
716 ******************************************************************************/
PORT_DlcReleaseInd(tRFC_MCB * p_mcb,uint8_t dlci)717 void PORT_DlcReleaseInd(tRFC_MCB* p_mcb, uint8_t dlci) {
718 log::verbose("dlci:{}, bd_addr:{}", dlci, p_mcb->bd_addr);
719 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
720 if (!p_port) {
721 return;
722 }
723 port_rfc_closed(p_port, PORT_CLOSED);
724 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_CLOSED, 1);
725 }
726
727 /*******************************************************************************
728 *
729 * Function PORT_CloseInd
730 *
731 * Description This function is called from the RFCOMM layer when
732 * multiplexer connection is released.
733 *
734 ******************************************************************************/
PORT_CloseInd(tRFC_MCB * p_mcb)735 void PORT_CloseInd(tRFC_MCB* p_mcb) {
736 tPORT* p_port;
737 int i;
738
739 log::verbose("PORT_CloseInd");
740
741 p_port = &rfc_cb.port.port[0];
742 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
743 if (p_port->rfc.p_mcb == p_mcb) {
744 port_rfc_closed(p_port, PORT_PEER_CONNECTION_FAILED);
745 log_counter_metrics(
746 android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_CONNECTION_FAILED, 1);
747 }
748 }
749 rfc_release_multiplexer_channel(p_mcb);
750 }
751
752 /*******************************************************************************
753 *
754 * Function PORT_TimeOutCloseMux
755 *
756 * Description This function is called when RFCOMM timesout on a command
757 * as a result multiplexer connection is closed.
758 *
759 ******************************************************************************/
PORT_TimeOutCloseMux(tRFC_MCB * p_mcb)760 void PORT_TimeOutCloseMux(tRFC_MCB* p_mcb) {
761 tPORT* p_port;
762 int i;
763
764 log::verbose("PORT_TimeOutCloseMux");
765
766 p_port = &rfc_cb.port.port[0];
767 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
768 if (p_port->rfc.p_mcb == p_mcb) {
769 port_rfc_closed(p_port, PORT_PEER_TIMEOUT);
770 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_TIMEOUT, 1);
771 }
772 }
773 }
774
775 /*******************************************************************************
776 *
777 * Function PORT_DataInd
778 *
779 * Description This function is called from the RFCOMM layer when data
780 * buffer is received from the peer.
781 *
782 ******************************************************************************/
PORT_DataInd(tRFC_MCB * p_mcb,uint8_t dlci,BT_HDR * p_buf)783 void PORT_DataInd(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) {
784 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
785 uint8_t rx_char1;
786 uint32_t events = 0;
787 uint8_t* p;
788 int i;
789
790 log::verbose("PORT_DataInd with data length {}, p_mcb:{},p_port:{},dlci:{}", p_buf->len,
791 std::format_ptr(p_mcb), std::format_ptr(p_port), dlci);
792 if (!p_port) {
793 osi_free(p_buf);
794 return;
795 }
796 /* If client registered callout callback with flow control we can just deliver
797 * receive data */
798 if (p_port->p_data_co_callback) {
799 /* Another packet is delivered to user. Send credits to peer if required */
800 if (p_port->p_data_co_callback(p_port->handle, (uint8_t*)p_buf, -1,
801 DATA_CO_CALLBACK_TYPE_INCOMING)) {
802 port_flow_control_peer(p_port, true, 1);
803 } else {
804 port_flow_control_peer(p_port, false, 0);
805 }
806 // osi_free(p_buf);
807 return;
808 }
809 /* If client registered callback we can just deliver receive data */
810 if (p_port->p_data_callback) {
811 /* Another packet is delivered to user. Send credits to peer if required */
812 port_flow_control_peer(p_port, true, 1);
813 p_port->p_data_callback(p_port->handle, (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
814 osi_free(p_buf);
815 return;
816 }
817 /* Check if rx queue exceeds the limit */
818 if ((p_port->rx.queue_size + p_buf->len > PORT_RX_CRITICAL_WM) ||
819 (fixed_queue_length(p_port->rx.queue) + 1 > p_port->rx_buf_critical)) {
820 log::verbose("PORT_DataInd. Buffer over run. Dropping the buffer");
821 osi_free(p_buf);
822 RFCOMM_LineStatusReq(p_mcb, dlci, LINE_STATUS_OVERRUN);
823 return;
824 }
825 /* If user registered to receive notification when a particular byte is */
826 /* received we mast check all received bytes */
827 if (((rx_char1 = p_port->user_port_settings.rx_char1) != 0) &&
828 (p_port->ev_mask & PORT_EV_RXFLAG)) {
829 for (i = 0, p = (uint8_t*)(p_buf + 1) + p_buf->offset; i < p_buf->len; i++) {
830 if (*p++ == rx_char1) {
831 events |= PORT_EV_RXFLAG;
832 break;
833 }
834 }
835 }
836
837 mutex_global_lock();
838
839 fixed_queue_enqueue(p_port->rx.queue, p_buf);
840 p_port->rx.queue_size += p_buf->len;
841
842 mutex_global_unlock();
843
844 /* perform flow control procedures if necessary */
845 port_flow_control_peer(p_port, false, 0);
846
847 /* If user indicated flow control can not deliver any notifications to them */
848 if (p_port->rx.user_fc) {
849 if (events & PORT_EV_RXFLAG) {
850 p_port->rx_flag_ev_pending = true;
851 }
852 return;
853 }
854
855 events |= PORT_EV_RXCHAR;
856
857 /* Mask out all events that are not of interest to user */
858 events &= p_port->ev_mask;
859
860 if (p_port->p_callback && events) {
861 p_port->p_callback(events, p_port->handle);
862 }
863 }
864
865 /*******************************************************************************
866 *
867 * Function PORT_FlowInd
868 *
869 * Description This function is called from the RFCOMM layer on the flow
870 * control signal change. Propagate change to the user.
871 *
872 ******************************************************************************/
PORT_FlowInd(tRFC_MCB * p_mcb,uint8_t dlci,bool enable_data)873 void PORT_FlowInd(tRFC_MCB* p_mcb, uint8_t dlci, bool enable_data) {
874 tPORT* p_port = (tPORT*)NULL;
875 uint32_t events = 0;
876 int i;
877
878 log::verbose("PORT_FlowInd fc:{}", enable_data);
879
880 if (dlci == 0) {
881 p_mcb->peer_ready = enable_data;
882 } else {
883 p_port = port_find_mcb_dlci_port(p_mcb, dlci);
884 if (p_port == NULL) {
885 return;
886 }
887
888 p_port->tx.peer_fc = !enable_data;
889 }
890
891 for (i = 0; i < MAX_RFC_PORTS; i++) {
892 /* If DLCI is 0 event applies to all ports */
893 if (dlci == 0) {
894 p_port = &rfc_cb.port.port[i];
895 if (!p_port->in_use || (p_port->rfc.p_mcb != p_mcb) ||
896 (p_port->rfc.state != RFC_STATE_OPENED)) {
897 continue;
898 }
899 }
900 events = 0;
901
902 /* Check if flow of data is still enabled */
903 events |= port_flow_control_user(p_port);
904
905 /* Check if data can be sent and send it */
906 events |= port_rfc_send_tx_data(p_port);
907
908 /* Mask out all events that are not of interest to user */
909 events &= p_port->ev_mask;
910
911 /* Send event to the application */
912 if (p_port->p_callback && events) {
913 (p_port->p_callback)(events, p_port->handle);
914 }
915
916 /* If DLCI is not 0 event applies to one port only */
917 if (dlci != 0) {
918 break;
919 }
920 }
921 }
922
923 /*******************************************************************************
924 *
925 * Function port_rfc_send_tx_data
926 *
927 * Description This function is when forward data can be sent to the peer
928 *
929 ******************************************************************************/
port_rfc_send_tx_data(tPORT * p_port)930 uint32_t port_rfc_send_tx_data(tPORT* p_port) {
931 uint32_t events = 0;
932 BT_HDR* p_buf;
933
934 /* if there is data to be sent */
935 if (p_port->tx.queue_size > 0) {
936 /* while the rfcomm peer is not flow controlling us, and peer is ready */
937 while (!p_port->tx.peer_fc && p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready) {
938 /* get data from tx queue and send it */
939 mutex_global_lock();
940
941 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue);
942 if (p_buf != NULL) {
943 p_port->tx.queue_size -= p_buf->len;
944
945 mutex_global_unlock();
946
947 log::verbose("Sending RFCOMM_DataReq tx.queue_size={}", p_port->tx.queue_size);
948
949 RFCOMM_DataReq(p_port->rfc.p_mcb, p_port->dlci, p_buf);
950
951 events |= PORT_EV_TXCHAR;
952
953 if (p_port->tx.queue_size == 0) {
954 events |= PORT_EV_TXEMPTY;
955 break;
956 }
957 } else {
958 /* queue is empty-- all data sent */
959 mutex_global_unlock();
960
961 events |= PORT_EV_TXEMPTY;
962 break;
963 }
964 }
965 /* If we flow controlled user based on the queue size enable data again */
966 events |= port_flow_control_user(p_port);
967 }
968 return events & p_port->ev_mask;
969 }
970
971 /*******************************************************************************
972 *
973 * Function port_rfc_closed
974 *
975 * Description Called when RFCOMM port is closed
976 *
977 ******************************************************************************/
port_rfc_closed(tPORT * p_port,uint8_t res)978 void port_rfc_closed(tPORT* p_port, uint8_t res) {
979 uint8_t old_signals;
980 uint32_t events = 0;
981 tRFC_MCB* p_mcb = p_port->rfc.p_mcb;
982
983 if ((p_port->state == PORT_CONNECTION_STATE_OPENING) && (p_port->is_server)) {
984 /* The server side was not informed that connection is up, ignore */
985 log::warn("port_rfc_closed in OPENING state ignored");
986
987 rfc_port_timer_stop(p_port);
988 p_port->rfc.state = RFC_STATE_CLOSED;
989
990 if (p_mcb) {
991 p_mcb->port_handles[p_port->dlci] = 0;
992
993 /* If there are no more ports opened on this MCB release it */
994 rfc_check_mcb_active(p_mcb);
995 p_port->rfc.p_mcb = NULL;
996 }
997
998 /* Need to restore DLCI to listening state
999 * if the server was on the initiating RFC
1000 */
1001 p_port->dlci &= 0xfe;
1002
1003 return;
1004 }
1005
1006 if (p_port->state >= PORT_CONNECTION_STATE_OPENED && p_mcb) {
1007 uint16_t lcid;
1008 tL2C_CCB* ccb;
1009
1010 lcid = p_mcb->lcid;
1011 ccb = l2cu_find_ccb_by_cid(nullptr, lcid);
1012
1013 if (ccb) {
1014 bluetooth::shim::GetSnoopLogger()->SetRfcommPortClose(ccb->p_lcb->Handle(), lcid,
1015 p_port->dlci, p_port->uuid);
1016 }
1017 }
1018
1019 if ((p_port->state != PORT_CONNECTION_STATE_CLOSING) &&
1020 (p_port->state != PORT_CONNECTION_STATE_CLOSED)) {
1021 p_port->line_status |= LINE_STATUS_FAILED;
1022
1023 old_signals = p_port->peer_ctrl.modem_signal;
1024
1025 p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
1026
1027 events |= port_get_signal_changes(p_port, old_signals, p_port->peer_ctrl.modem_signal);
1028
1029 if (p_port->ev_mask & PORT_EV_CONNECT_ERR) {
1030 events |= PORT_EV_CONNECT_ERR;
1031 }
1032 }
1033
1034 if ((p_port->p_callback != NULL) && events) {
1035 p_port->p_callback(events, p_port->handle);
1036 }
1037
1038 if (p_port->p_mgmt_callback) {
1039 uint32_t res2 = res;
1040 if (res2 >= PORT_ERR_MAX) {
1041 res2 = PORT_ERR_MAX;
1042 }
1043 p_port->p_mgmt_callback(static_cast<tPORT_RESULT>(res2), p_port->handle);
1044 }
1045
1046 p_port->rfc.state = RFC_STATE_CLOSED;
1047
1048 log::info(
1049 "RFCOMM connection closed, index={}, state={}, reason={}[{}], "
1050 "UUID=0x{:x}, bd_addr={}, is_server={}",
1051 p_port->handle, p_port->state, PORT_GetResultString(res), res, p_port->uuid,
1052 p_port->bd_addr, p_port->is_server);
1053
1054 port_release_port(p_port);
1055 }
1056
1057 /*******************************************************************************
1058 *
1059 * Function port_get_credits
1060 *
1061 * Description Set initial values for credits.
1062 * Adjust max number of rx credits based on negotiated MTU.
1063 * Check max allowed num of bytes, max allowed num buffers,
1064 * should be less then 255
1065 *
1066 ******************************************************************************/
port_get_credits(tPORT * p_port,uint8_t k)1067 void port_get_credits(tPORT* p_port, uint8_t k) {
1068 p_port->credit_tx = k;
1069 if (p_port->credit_tx == 0) {
1070 p_port->tx.peer_fc = true;
1071 }
1072 }
1073