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