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