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