• 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  *  Port Emulation entity utilities
22  *
23  ******************************************************************************/
24 #include <base/logging.h>
25 #include <string.h>
26 
27 #include "osi/include/mutex.h"
28 
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "btm_int.h"
32 #include "btu.h"
33 #include "l2cdefs.h"
34 #include "port_api.h"
35 #include "port_int.h"
36 #include "rfc_int.h"
37 #include "rfcdefs.h"
38 #include "stack/include/btm_client_interface.h"
39 
40 static const tPORT_STATE default_port_pars = {
41     PORT_BAUD_RATE_9600,
42     PORT_8_BITS,
43     PORT_ONESTOPBIT,
44     PORT_PARITY_NO,
45     PORT_ODD_PARITY,
46     PORT_FC_OFF,
47     0, /* No rx_char */
48     PORT_XON_DC1,
49     PORT_XOFF_DC3,
50 };
51 
52 /*******************************************************************************
53  *
54  * Function         port_allocate_port
55  *
56  * Description      Look through the Port Control Blocks for a free one.  Note
57  *                  that one server can open several ports with the same SCN
58  *                  if it can support simulteneous requests from different
59  *                  clients.
60  *
61  * Returns          Pointer to the PORT or NULL if not found
62  *
63  ******************************************************************************/
port_allocate_port(uint8_t dlci,const RawAddress & bd_addr)64 tPORT* port_allocate_port(uint8_t dlci, const RawAddress& bd_addr) {
65   uint8_t port_index = rfc_cb.rfc.last_port_index + static_cast<uint8_t>(1);
66   // Loop at most MAX_RFC_PORTS items
67   for (int loop_counter = 0; loop_counter < MAX_RFC_PORTS;
68        loop_counter++, port_index++) {
69     if (port_index >= MAX_RFC_PORTS) {
70       port_index = 0;
71     }
72     tPORT* p_port = &rfc_cb.port.port[port_index];
73     if (!p_port->in_use) {
74       // Assume that we already called port_release_port on this
75       memset(p_port, 0, sizeof(tPORT));
76       p_port->in_use = true;
77       // handle is a port handle starting from 1
78       p_port->handle = port_index + static_cast<uint8_t>(1);
79       // During the open set default state for the port connection
80       port_set_defaults(p_port);
81       p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
82       p_port->dlci = dlci;
83       p_port->bd_addr = bd_addr;
84       rfc_cb.rfc.last_port_index = port_index;
85       RFCOMM_TRACE_DEBUG(
86           "%s: rfc_cb.port.port[%d]:%p chosen, "
87           "last_port_index:%d, bd_addr=%s",
88           __func__, port_index, p_port, rfc_cb.rfc.last_port_index,
89           bd_addr.ToString().c_str());
90       return p_port;
91     }
92   }
93   LOG(WARNING) << __func__ << ": running out of free ports for dlci "
94                << std::to_string(dlci) << ", bd_addr " << bd_addr;
95   return nullptr;
96 }
97 
98 /*******************************************************************************
99  *
100  * Function         port_set_defaults
101  *
102  * Description      Set defualt port parameters
103  *
104  *
105  ******************************************************************************/
port_set_defaults(tPORT * p_port)106 void port_set_defaults(tPORT* p_port) {
107   p_port->ev_mask = 0;
108   p_port->p_callback = nullptr;
109   p_port->port_ctrl = 0;
110   p_port->error = 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(WARNING) << __func__ << ": 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         RFCOMM_TRACE_DEBUG("%s: selected %d based on connection speed",
172                            __func__, p_port->mtu);
173       } else {
174         p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
175         RFCOMM_TRACE_DEBUG("%s: selected %d based on l2cap PDU size", __func__,
176                            p_port->mtu);
177       }
178     }
179   } else {
180     RFCOMM_TRACE_DEBUG("%s: application selected %d", __func__, p_port->mtu);
181   }
182   p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
183   if (p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM)
184     p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
185   p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu);
186   if (p_port->credit_rx_low > PORT_RX_BUF_LOW_WM)
187     p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
188   p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
189   if (p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM)
190     p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
191   RFCOMM_TRACE_DEBUG(
192       "%s: credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d", __func__,
193       p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
194 }
195 
196 /*******************************************************************************
197  *
198  * Function         port_release_port
199  *
200  * Description      Release port control block.
201  *
202  * Returns          Pointer to the PORT or NULL if not found
203  *
204  ******************************************************************************/
port_release_port(tPORT * p_port)205 void port_release_port(tPORT* p_port) {
206   RFCOMM_TRACE_DEBUG("%s p_port: %p state: %d keep_handle: %d", __func__,
207                      p_port, p_port->rfc.state, p_port->keep_port_handle);
208 
209   mutex_global_lock();
210   BT_HDR* p_buf;
211   while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) !=
212          nullptr) {
213     osi_free(p_buf);
214   }
215   p_port->rx.queue_size = 0;
216 
217   while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) !=
218          nullptr) {
219     osi_free(p_buf);
220   }
221   p_port->tx.queue_size = 0;
222   mutex_global_unlock();
223 
224   alarm_cancel(p_port->rfc.port_timer);
225 
226   p_port->state = PORT_STATE_CLOSED;
227 
228   if (p_port->rfc.state == RFC_STATE_CLOSED) {
229     if (p_port->rfc.p_mcb) {
230       p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0;
231 
232       /* If there are no more ports opened on this MCB release it */
233       rfc_check_mcb_active(p_port->rfc.p_mcb);
234     }
235 
236     rfc_port_timer_stop(p_port);
237 
238     mutex_global_lock();
239     fixed_queue_free(p_port->tx.queue, nullptr);
240     p_port->tx.queue = nullptr;
241     fixed_queue_free(p_port->rx.queue, nullptr);
242     p_port->rx.queue = nullptr;
243     mutex_global_unlock();
244 
245     if (p_port->keep_port_handle) {
246       RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__,
247                          p_port->handle);
248 
249       /* save event mask and callback */
250       uint32_t mask = p_port->ev_mask;
251       tPORT_CALLBACK* p_port_cb = p_port->p_callback;
252       tPORT_STATE user_port_pars = p_port->user_port_pars;
253 
254       port_set_defaults(p_port);
255 
256       /* restore */
257       p_port->ev_mask = mask;
258       p_port->p_callback = p_port_cb;
259       p_port->user_port_pars = user_port_pars;
260       p_port->mtu = p_port->keep_mtu;
261 
262       p_port->state = PORT_STATE_OPENING;
263       p_port->rfc.p_mcb = nullptr;
264       if (p_port->is_server) p_port->dlci &= 0xfe;
265 
266       p_port->local_ctrl.modem_signal = p_port->default_signal_state;
267       p_port->bd_addr = RawAddress::kAny;
268     } else {
269       RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->handle);
270       alarm_free(p_port->rfc.port_timer);
271       memset(p_port, 0, sizeof(tPORT));
272     }
273   }
274 }
275 
276 /*******************************************************************************
277  *
278  * Function         port_find_mcb
279  *
280  * Description      This function checks if connection exists to device with
281  *                  the address.
282  *
283  ******************************************************************************/
port_find_mcb(const RawAddress & bd_addr)284 tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) {
285   for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) {
286     if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) {
287       /* Multiplexer channel found do not change anything */
288       VLOG(1) << __func__ << ": found bd_addr=" << bd_addr
289               << ", rfc_mcb=" << &mcb << ", lcid=" << loghex(mcb.lcid);
290       return &mcb;
291     }
292   }
293   VLOG(1) << __func__ << ": not found, bd_addr:" << bd_addr;
294   return nullptr;
295 }
296 
297 /*******************************************************************************
298  *
299  * Function         port_find_mcb_dlci_port
300  *
301  * Description      Find port on the multiplexer channel based on DLCI.  If
302  *                  this port with DLCI not found try to use even DLCI.  This
303  *                  is for the case when client is establishing connection on
304  *                  none-initiator MCB.
305  *
306  * Returns          Pointer to the PORT or NULL if not found
307  *
308  ******************************************************************************/
port_find_mcb_dlci_port(tRFC_MCB * p_mcb,uint8_t dlci)309 tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
310   if (!p_mcb) {
311     LOG(ERROR) << __func__ << ": p_mcb is null, dlci=" << std::to_string(dlci);
312     return nullptr;
313   }
314 
315   if (dlci > RFCOMM_MAX_DLCI) {
316     LOG(WARNING) << __func__ << ": DLCI " << std::to_string(dlci)
317                  << " is too large, bd_addr=" << p_mcb->bd_addr
318                  << ", p_mcb=" << p_mcb;
319     return nullptr;
320   }
321 
322   uint8_t handle = p_mcb->port_handles[dlci];
323   if (handle == 0) {
324     LOG(INFO) << __func__ << ": Cannot find allocated RFCOMM app port for DLCI "
325               << std::to_string(dlci) << " on " << p_mcb->bd_addr
326               << ", p_mcb=" << p_mcb;
327     return nullptr;
328   }
329   return &rfc_cb.port.port[handle - 1];
330 }
331 
332 /*******************************************************************************
333  *
334  * Function         port_find_dlci_port
335  *
336  * Description      Find port with DLCI not assigned to multiplexer channel
337  *
338  * Returns          Pointer to the PORT or NULL if not found
339  *
340  ******************************************************************************/
port_find_dlci_port(uint8_t dlci)341 tPORT* port_find_dlci_port(uint8_t dlci) {
342   for (tPORT& port : rfc_cb.port.port) {
343     if (port.in_use && (port.rfc.p_mcb == nullptr)) {
344       if (port.dlci == dlci) {
345         return &port;
346       } else if ((dlci & 0x01) && (port.dlci == (dlci - 1))) {
347         port.dlci++;
348         return &port;
349       }
350     }
351   }
352   return nullptr;
353 }
354 
355 /*******************************************************************************
356  *
357  * Function         port_find_port
358  *
359  * Description      Find port with DLCI, address
360  *
361  * Returns          Pointer to the PORT or NULL if not found
362  *
363  ******************************************************************************/
port_find_port(uint8_t dlci,const RawAddress & bd_addr)364 tPORT* port_find_port(uint8_t dlci, const RawAddress& bd_addr) {
365   for (tPORT& port : rfc_cb.port.port) {
366     if (port.in_use && (port.dlci == dlci) && (port.bd_addr == bd_addr)) {
367       return &port;
368     }
369   }
370   return nullptr;
371 }
372 
373 /*******************************************************************************
374  *
375  * Function         port_flow_control_user
376  *
377  * Description      Check the current user flow control and if necessary return
378  *                  events to be send to the user based on the user's specified
379  *                  flow control type.
380  *
381  * Returns          event mask to be returned to the application
382  *
383  ******************************************************************************/
port_flow_control_user(tPORT * p_port)384 uint32_t port_flow_control_user(tPORT* p_port) {
385   uint32_t event = 0;
386 
387   /* Flow control to the user can be caused by flow controlling by the peer */
388   /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
389   /* tx_queue is full */
390   bool fc = p_port->tx.peer_fc || !p_port->rfc.p_mcb ||
391             !p_port->rfc.p_mcb->peer_ready ||
392             (p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
393             (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
394 
395   if (p_port->tx.user_fc == fc) return (0);
396 
397   p_port->tx.user_fc = fc;
398 
399   if (fc)
400     event = PORT_EV_FC;
401   else
402     event = PORT_EV_FC | PORT_EV_FCS;
403 
404   return (event);
405 }
406 
407 /*******************************************************************************
408  *
409  * Function         port_get_signal_changes
410  *
411  * Description      Check modem signals that has been changed
412  *
413  * Returns          event mask to be returned to the application
414  *
415  ******************************************************************************/
port_get_signal_changes(tPORT * p_port,uint8_t old_signals,uint8_t signal)416 uint32_t port_get_signal_changes(tPORT* p_port, uint8_t old_signals,
417                                  uint8_t signal) {
418   uint8_t changed_signals = (signal ^ old_signals);
419   uint32_t events = 0;
420 
421   if (changed_signals & PORT_DTRDSR_ON) {
422     events |= PORT_EV_DSR;
423 
424     if (signal & PORT_DTRDSR_ON) events |= PORT_EV_DSRS;
425   }
426 
427   if (changed_signals & PORT_CTSRTS_ON) {
428     events |= PORT_EV_CTS;
429 
430     if (signal & PORT_CTSRTS_ON) events |= PORT_EV_CTSS;
431   }
432 
433   if (changed_signals & PORT_RING_ON) events |= PORT_EV_RING;
434 
435   if (changed_signals & PORT_DCD_ON) {
436     events |= PORT_EV_RLSD;
437 
438     if (signal & PORT_DCD_ON) events |= PORT_EV_RLSDS;
439   }
440 
441   return (p_port->ev_mask & events);
442 }
443 
444 /*******************************************************************************
445  *
446  * Function         port_flow_control_peer
447  *
448  * Description      Send flow control messages to the peer for both enabling
449  *                  and disabling flow control, for both credit-based and
450  *                  TS 07.10 flow control mechanisms.
451  *
452  * Returns          nothing
453  *
454  ******************************************************************************/
port_flow_control_peer(tPORT * p_port,bool enable,uint16_t count)455 void port_flow_control_peer(tPORT* p_port, bool enable, uint16_t count) {
456   if (!p_port->rfc.p_mcb) return;
457 
458   /* If using credit based flow control */
459   if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
460     /* if want to enable flow from peer */
461     if (enable) {
462       /* update rx credits */
463       if (count > p_port->credit_rx) {
464         p_port->credit_rx = 0;
465       } else {
466         p_port->credit_rx -= count;
467       }
468 
469       /* If credit count is less than low credit watermark, and user */
470       /* did not force flow control, send a credit update */
471       /* There might be a special case when we just adjusted rx_max */
472       if ((p_port->credit_rx <= p_port->credit_rx_low) && !p_port->rx.user_fc &&
473           (p_port->credit_rx_max > p_port->credit_rx)) {
474         rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
475                         (uint8_t)(p_port->credit_rx_max - p_port->credit_rx));
476 
477         p_port->credit_rx = p_port->credit_rx_max;
478 
479         p_port->rx.peer_fc = false;
480       }
481     }
482     /* else want to disable flow from peer */
483     else {
484       /* if client registered data callback, just do what they want */
485       if (p_port->p_data_callback || p_port->p_data_co_callback) {
486         p_port->rx.peer_fc = true;
487       }
488       /* if queue count reached credit rx max, set peer fc */
489       else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) {
490         p_port->rx.peer_fc = true;
491       }
492     }
493   }
494   /* else using TS 07.10 flow control */
495   else {
496     /* if want to enable flow from peer */
497     if (enable) {
498       /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
499       /* check if it can be resumed now */
500       if (p_port->rx.peer_fc && (p_port->rx.queue_size < PORT_RX_LOW_WM) &&
501           (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) {
502         p_port->rx.peer_fc = false;
503 
504         /* If user did not force flow control allow traffic now */
505         if (!p_port->rx.user_fc)
506           RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, true);
507       }
508     }
509     /* else want to disable flow from peer */
510     else {
511       /* if client registered data callback, just do what they want */
512       if (p_port->p_data_callback || p_port->p_data_co_callback) {
513         p_port->rx.peer_fc = true;
514         RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
515       }
516       /* Check the size of the rx queue.  If it exceeds certain */
517       /* level and flow control has not been sent to the peer do it now */
518       else if (((p_port->rx.queue_size > PORT_RX_HIGH_WM) ||
519                 (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM)) &&
520                !p_port->rx.peer_fc) {
521         RFCOMM_TRACE_EVENT("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