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