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