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