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