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