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  *  Port Emulation entity utilities
22  *
23  ******************************************************************************/
24 
25 #define LOG_TAG "rfcomm_port_utils"
26 
27 #include <bluetooth/log.h>
28 
29 #include <cstdint>
30 #include <cstring>
31 
32 #include "internal_include/bt_target.h"
33 #include "osi/include/allocator.h"
34 #include "osi/include/mutex.h"
35 #include "stack/include/bt_hdr.h"
36 #include "stack/include/btm_client_interface.h"
37 #include "stack/include/l2cdefs.h"
38 #include "stack/rfcomm/port_int.h"
39 #include "stack/rfcomm/rfc_int.h"
40 #include "types/raw_address.h"
41 
42 using namespace bluetooth;
43 
44 static const PortSettings default_port_settings = {
45         PORT_BAUD_RATE_9600,
46         PORT_8_BITS,
47         PORT_ONESTOPBIT,
48         PORT_PARITY_NO,
49         PORT_ODD_PARITY,
50         PORT_FC_OFF,
51         0, /* No rx_char */
52         PORT_XON_DC1,
53         PORT_XOFF_DC3,
54 };
55 
56 /*******************************************************************************
57  *
58  * Function         port_allocate_port
59  *
60  * Description      Look through the Port Control Blocks for a free one.  Note
61  *                  that one server can open several ports with the same SCN
62  *                  if it can support simulteneous requests from different
63  *                  clients.
64  *
65  * Returns          Pointer to the PORT or NULL if not found
66  *
67  ******************************************************************************/
port_allocate_port(uint8_t dlci,const RawAddress & bd_addr)68 tPORT* port_allocate_port(uint8_t dlci, const RawAddress& bd_addr) {
69   uint8_t port_index = rfc_cb.rfc.last_port_index + static_cast<uint8_t>(1);
70   // Loop at most MAX_RFC_PORTS items
71   for (int loop_counter = 0; loop_counter < MAX_RFC_PORTS; loop_counter++, port_index++) {
72     if (port_index >= MAX_RFC_PORTS) {
73       port_index = 0;
74     }
75     tPORT* p_port = &rfc_cb.port.port[port_index];
76     if (!p_port->in_use) {
77       // Assume that we already called port_release_port on this
78       memset(p_port, 0, sizeof(tPORT));
79       p_port->in_use = true;
80       // handle is a port handle starting from 1
81       p_port->handle = port_index + static_cast<uint8_t>(1);
82       // During the open set default state for the port connection
83       port_set_defaults(p_port);
84       p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
85       p_port->dlci = dlci;
86       p_port->bd_addr = bd_addr;
87       rfc_cb.rfc.last_port_index = port_index;
88       log::verbose("rfc_cb.port.port[{}]:{} chosen, last_port_index:{}, bd_addr={}", port_index,
89                    std::format_ptr(p_port), rfc_cb.rfc.last_port_index, bd_addr);
90       return p_port;
91     }
92   }
93   log::warn("running out of free ports for dlci {}, bd_addr {}", dlci, bd_addr);
94   return nullptr;
95 }
96 
97 /*******************************************************************************
98  *
99  * Function         port_set_defaults
100  *
101  * Description      Set defualt port parameters
102  *
103  *
104  ******************************************************************************/
port_set_defaults(tPORT * p_port)105 void port_set_defaults(tPORT* p_port) {
106   p_port->ev_mask = 0;
107   p_port->p_callback = nullptr;
108   p_port->port_ctrl = 0;
109   p_port->line_status = 0;
110   p_port->rx_flag_ev_pending = false;
111   p_port->peer_mtu = RFCOMM_DEFAULT_MTU;
112 
113   p_port->user_port_settings = default_port_settings;
114   p_port->peer_port_settings = default_port_settings;
115 
116   p_port->credit_tx = 0;
117   p_port->credit_rx = 0;
118 
119   memset(&p_port->local_ctrl, 0, sizeof(p_port->local_ctrl));
120   memset(&p_port->peer_ctrl, 0, sizeof(p_port->peer_ctrl));
121   memset(&p_port->rx, 0, sizeof(p_port->rx));
122   memset(&p_port->tx, 0, sizeof(p_port->tx));
123 
124   p_port->tx.queue = fixed_queue_new(SIZE_MAX);
125   p_port->rx.queue = fixed_queue_new(SIZE_MAX);
126 }
127 
128 /*******************************************************************************
129  *
130  * Function         port_select_mtu
131  *
132  * Description      Select MTU which will best serve connection from our
133  *                  point of view.
134  *                  If our device is 1.2 or lower we calculate how many DH5s
135  *                  fit into 1 RFCOMM buffer.
136  *
137  *
138  ******************************************************************************/
port_select_mtu(tPORT * p_port)139 void port_select_mtu(tPORT* p_port) {
140   uint16_t packet_size;
141 
142   /* Will select MTU only if application did not setup something */
143   if (p_port->mtu == 0) {
144     /* find packet size which connection supports */
145     packet_size = get_btm_client_interface().peer.BTM_GetMaxPacketSize(p_port->bd_addr);
146     if (packet_size == 0) {
147       /* something is very wrong */
148       log::warn("bad packet size 0 for{}", p_port->bd_addr);
149       p_port->mtu = RFCOMM_DEFAULT_MTU;
150     } else {
151       /* We try to negotiate MTU that each packet can be split into whole
152       number of max packets.  For example if link is 1.2 max packet size is 339
153       bytes.
154       At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4
155       overhead.
156       1695, that will be 5 Dh5 packets.  Now maximum RFCOMM packet is
157       5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.  Minus RFCOMM 6 bytes
158       header overhead 1685
159 
160       For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1
161       3DH5 packet
162       1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  Minus RFCOMM 6 bytes
163       header overhead 1017 */
164       if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size) {
165         p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) -
166                       RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
167         log::verbose("selected {} based on connection speed", p_port->mtu);
168       } else {
169         p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
170         log::verbose("selected {} based on l2cap PDU size", p_port->mtu);
171       }
172     }
173   } else {
174     log::verbose("application selected {}", p_port->mtu);
175   }
176   p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
177   if (p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM) {
178     p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
179   }
180   p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu);
181   if (p_port->credit_rx_low > PORT_RX_BUF_LOW_WM) {
182     p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
183   }
184   p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
185   if (p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM) {
186     p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
187   }
188   log::verbose("credit_rx_max {}, credit_rx_low {}, rx_buf_critical {}", p_port->credit_rx_max,
189                p_port->credit_rx_low, p_port->rx_buf_critical);
190 }
191 
192 /*******************************************************************************
193  *
194  * Function         port_release_port
195  *
196  * Description      Release port control block.
197  *
198  * Returns          Pointer to the PORT or NULL if not found
199  *
200  ******************************************************************************/
port_release_port(tPORT * p_port)201 void port_release_port(tPORT* p_port) {
202   log::verbose("p_port: {} state: {} keep_handle: {}", std::format_ptr(p_port), p_port->rfc.state,
203                p_port->keep_port_handle);
204 
205   mutex_global_lock();
206   BT_HDR* p_buf;
207   while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) != nullptr) {
208     osi_free(p_buf);
209   }
210   p_port->rx.queue_size = 0;
211 
212   while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) != nullptr) {
213     osi_free(p_buf);
214   }
215   p_port->tx.queue_size = 0;
216   mutex_global_unlock();
217 
218   alarm_cancel(p_port->rfc.port_timer);
219 
220   p_port->state = PORT_CONNECTION_STATE_CLOSED;
221 
222   if (p_port->rfc.state == RFC_STATE_CLOSED) {
223     if (p_port->rfc.p_mcb) {
224       p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0;
225 
226       /* If there are no more ports opened on this MCB release it */
227       rfc_check_mcb_active(p_port->rfc.p_mcb);
228     }
229 
230     rfc_port_timer_stop(p_port);
231 
232     mutex_global_lock();
233     fixed_queue_free(p_port->tx.queue, nullptr);
234     p_port->tx.queue = nullptr;
235     fixed_queue_free(p_port->rx.queue, nullptr);
236     p_port->rx.queue = nullptr;
237     mutex_global_unlock();
238 
239     if (p_port->keep_port_handle) {
240       log::verbose("Re-initialize handle: {}", p_port->handle);
241 
242       /* save event mask and callback */
243       uint32_t mask = p_port->ev_mask;
244       tPORT_CALLBACK* p_port_cb = p_port->p_callback;
245       PortSettings user_port_settings = p_port->user_port_settings;
246 
247       port_set_defaults(p_port);
248 
249       /* restore */
250       p_port->ev_mask = mask;
251       p_port->p_callback = p_port_cb;
252       p_port->user_port_settings = user_port_settings;
253       p_port->mtu = p_port->keep_mtu;
254 
255       p_port->state = PORT_CONNECTION_STATE_OPENING;
256       p_port->rfc.p_mcb = nullptr;
257       if (p_port->is_server) {
258         p_port->dlci &= 0xfe;
259       }
260 
261       p_port->local_ctrl.modem_signal = p_port->default_signal_state;
262       p_port->bd_addr = RawAddress::kAny;
263     } else {
264       log::verbose("Clean-up handle: {}", p_port->handle);
265       alarm_free(p_port->rfc.port_timer);
266       memset(p_port, 0, sizeof(tPORT));
267     }
268   }
269 }
270 
271 /*******************************************************************************
272  *
273  * Function         port_find_mcb
274  *
275  * Description      This function checks if connection exists to device with
276  *                  the address.
277  *
278  ******************************************************************************/
port_find_mcb(const RawAddress & bd_addr)279 tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) {
280   for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) {
281     if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) {
282       /* Multiplexer channel found do not change anything */
283       log::verbose("found, bd_addr:{}, rfc_mcb:{}, lcid:0x{:x}", bd_addr, std::format_ptr(&mcb),
284                    mcb.lcid);
285       return &mcb;
286     }
287   }
288   log::warn("not found, bd_addr:{}", bd_addr);
289   return nullptr;
290 }
291 
292 /*******************************************************************************
293  *
294  * Function         port_find_mcb_dlci_port
295  *
296  * Description      Find port on the multiplexer channel based on DLCI.  If
297  *                  this port with DLCI not found try to use even DLCI.  This
298  *                  is for the case when client is establishing connection on
299  *                  none-initiator MCB.
300  *
301  * Returns          Pointer to the PORT or NULL if not found
302  *
303  ******************************************************************************/
port_find_mcb_dlci_port(tRFC_MCB * p_mcb,uint8_t dlci)304 tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
305   if (!p_mcb) {
306     log::error("p_mcb is null, dlci={}", dlci);
307     return nullptr;
308   }
309 
310   if (dlci > RFCOMM_MAX_DLCI) {
311     log::warn("DLCI {} is too large, bd_addr={}, p_mcb={}", dlci, p_mcb->bd_addr,
312               std::format_ptr(p_mcb));
313     return nullptr;
314   }
315 
316   uint8_t handle = p_mcb->port_handles[dlci];
317   if (handle == 0) {
318     log::info("Cannot find allocated RFCOMM app port for DLCI {} on {}, p_mcb={}", dlci,
319               p_mcb->bd_addr, std::format_ptr(p_mcb));
320     return nullptr;
321   }
322   return &rfc_cb.port.port[handle - 1];
323 }
324 
325 /*******************************************************************************
326  *
327  * Function         port_find_dlci_port
328  *
329  * Description      Find port with DLCI not assigned to multiplexer channel
330  *
331  * Returns          Pointer to the PORT or NULL if not found
332  *
333  ******************************************************************************/
port_find_dlci_port(uint8_t dlci)334 tPORT* port_find_dlci_port(uint8_t dlci) {
335   for (tPORT& port : rfc_cb.port.port) {
336     if (port.in_use && (port.rfc.p_mcb == nullptr)) {
337       if (port.dlci == dlci) {
338         return &port;
339       } else if ((dlci & 0x01) && (port.dlci == (dlci - 1))) {
340         port.dlci++;
341         return &port;
342       }
343     }
344   }
345   return nullptr;
346 }
347 
348 /*******************************************************************************
349  *
350  * Function         port_find_port
351  *
352  * Description      Find port with DLCI, address
353  *
354  * Returns          Pointer to the PORT or NULL if not found
355  *
356  ******************************************************************************/
port_find_port(uint8_t dlci,const RawAddress & bd_addr)357 tPORT* port_find_port(uint8_t dlci, const RawAddress& bd_addr) {
358   for (tPORT& port : rfc_cb.port.port) {
359     if (port.in_use && (port.dlci == dlci) && (port.bd_addr == bd_addr)) {
360       return &port;
361     }
362   }
363   return nullptr;
364 }
365 
366 /*******************************************************************************
367  *
368  * Function         port_flow_control_user
369  *
370  * Description      Check the current user flow control and if necessary return
371  *                  events to be send to the user based on the user's specified
372  *                  flow control type.
373  *
374  * Returns          event mask to be returned to the application
375  *
376  ******************************************************************************/
port_flow_control_user(tPORT * p_port)377 uint32_t port_flow_control_user(tPORT* p_port) {
378   uint32_t event = 0;
379 
380   /* Flow control to the user can be caused by flow controlling by the peer */
381   /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
382   /* tx_queue is full */
383   bool fc = p_port->tx.peer_fc || !p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready ||
384             (p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
385             (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
386 
387   if (p_port->tx.user_fc == fc) {
388     return 0;
389   }
390 
391   p_port->tx.user_fc = fc;
392 
393   if (fc) {
394     event = PORT_EV_FC;
395   } else {
396     event = PORT_EV_FC | PORT_EV_FCS;
397   }
398 
399   return event;
400 }
401 
402 /*******************************************************************************
403  *
404  * Function         port_get_signal_changes
405  *
406  * Description      Check modem signals that has been changed
407  *
408  * Returns          event mask to be returned to the application
409  *
410  ******************************************************************************/
port_get_signal_changes(tPORT * p_port,uint8_t old_signals,uint8_t signal)411 uint32_t port_get_signal_changes(tPORT* p_port, uint8_t old_signals, uint8_t signal) {
412   uint8_t changed_signals = (signal ^ old_signals);
413   uint32_t events = 0;
414 
415   if (changed_signals & PORT_DTRDSR_ON) {
416     events |= PORT_EV_DSR;
417 
418     if (signal & PORT_DTRDSR_ON) {
419       events |= PORT_EV_DSRS;
420     }
421   }
422 
423   if (changed_signals & PORT_CTSRTS_ON) {
424     events |= PORT_EV_CTS;
425 
426     if (signal & PORT_CTSRTS_ON) {
427       events |= PORT_EV_CTSS;
428     }
429   }
430 
431   if (changed_signals & PORT_RING_ON) {
432     events |= PORT_EV_RING;
433   }
434 
435   if (changed_signals & PORT_DCD_ON) {
436     events |= PORT_EV_RLSD;
437 
438     if (signal & PORT_DCD_ON) {
439       events |= PORT_EV_RLSDS;
440     }
441   }
442 
443   return p_port->ev_mask & events;
444 }
445 
446 /*******************************************************************************
447  *
448  * Function         port_flow_control_peer
449  *
450  * Description      Send flow control messages to the peer for both enabling
451  *                  and disabling flow control, for both credit-based and
452  *                  TS 07.10 flow control mechanisms.
453  *
454  * Returns          nothing
455  *
456  ******************************************************************************/
port_flow_control_peer(tPORT * p_port,bool enable,uint16_t count)457 void port_flow_control_peer(tPORT* p_port, bool enable, uint16_t count) {
458   if (!p_port->rfc.p_mcb) {
459     return;
460   }
461 
462   /* If using credit based flow control */
463   if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
464     /* if want to enable flow from peer */
465     if (enable) {
466       /* update rx credits */
467       if (count > p_port->credit_rx) {
468         p_port->credit_rx = 0;
469       } else {
470         p_port->credit_rx -= count;
471       }
472 
473       /* If credit count is less than low credit watermark, and user */
474       /* did not force flow control, send a credit update */
475       /* There might be a special case when we just adjusted rx_max */
476       if ((p_port->credit_rx <= p_port->credit_rx_low) && !p_port->rx.user_fc &&
477           (p_port->credit_rx_max > p_port->credit_rx)) {
478         rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
479                         (uint8_t)(p_port->credit_rx_max - p_port->credit_rx));
480 
481         p_port->credit_rx = p_port->credit_rx_max;
482 
483         p_port->rx.peer_fc = false;
484       }
485     } else {
486       /* else want to disable flow from peer */
487       /* if client registered data callback, just do what they want */
488       if (p_port->p_data_callback || p_port->p_data_co_callback) {
489         p_port->rx.peer_fc = true;
490       } else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) {
491         /* if queue count reached credit rx max, set peer fc */
492         p_port->rx.peer_fc = true;
493       }
494     }
495   } else {
496     /* else using TS 07.10 flow control */
497     /* if want to enable flow from peer */
498     if (enable) {
499       /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
500       /* check if it can be resumed now */
501       if (p_port->rx.peer_fc && (p_port->rx.queue_size < PORT_RX_LOW_WM) &&
502           (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) {
503         p_port->rx.peer_fc = false;
504 
505         /* If user did not force flow control allow traffic now */
506         if (!p_port->rx.user_fc) {
507           RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, true);
508         }
509       }
510     } else {
511       /* else want to disable flow from peer */
512       /* if client registered data callback, just do what they want */
513       if (p_port->p_data_callback || p_port->p_data_co_callback) {
514         p_port->rx.peer_fc = true;
515         RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
516       } else if (((p_port->rx.queue_size > PORT_RX_HIGH_WM) ||
517                   (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM)) &&
518                  !p_port->rx.peer_fc) {
519         /* Check the size of the rx queue.  If it exceeds certain */
520         /* level and flow control has not been sent to the peer do it now */
521         log::verbose("PORT_DataInd Data reached HW. Sending FC set.");
522 
523         p_port->rx.peer_fc = true;
524         RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
525       }
526     }
527   }
528 }
529