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 PortSettings default_port_settings = {
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; loop_counter++, port_index++) {
72 if (port_index >= MAX_RFC_PORTS) {
73 port_index = 0;
74 }
75 tPORT* p_port = &rfc_cb.port.port[port_index];
76 if (!p_port->in_use) {
77 // Assume that we already called port_release_port on this
78 memset(p_port, 0, sizeof(tPORT));
79 p_port->in_use = true;
80 // handle is a port handle starting from 1
81 p_port->handle = port_index + static_cast<uint8_t>(1);
82 // During the open set default state for the port connection
83 port_set_defaults(p_port);
84 p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
85 p_port->dlci = dlci;
86 p_port->bd_addr = bd_addr;
87 rfc_cb.rfc.last_port_index = port_index;
88 log::verbose("rfc_cb.port.port[{}]:{} chosen, last_port_index:{}, bd_addr={}", port_index,
89 std::format_ptr(p_port), rfc_cb.rfc.last_port_index, bd_addr);
90 return p_port;
91 }
92 }
93 log::warn("running out of free ports for dlci {}, bd_addr {}", dlci, 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->line_status = 0;
110 p_port->rx_flag_ev_pending = false;
111 p_port->peer_mtu = RFCOMM_DEFAULT_MTU;
112
113 p_port->user_port_settings = default_port_settings;
114 p_port->peer_port_settings = default_port_settings;
115
116 p_port->credit_tx = 0;
117 p_port->credit_rx = 0;
118
119 memset(&p_port->local_ctrl, 0, sizeof(p_port->local_ctrl));
120 memset(&p_port->peer_ctrl, 0, sizeof(p_port->peer_ctrl));
121 memset(&p_port->rx, 0, sizeof(p_port->rx));
122 memset(&p_port->tx, 0, sizeof(p_port->tx));
123
124 p_port->tx.queue = fixed_queue_new(SIZE_MAX);
125 p_port->rx.queue = fixed_queue_new(SIZE_MAX);
126 }
127
128 /*******************************************************************************
129 *
130 * Function port_select_mtu
131 *
132 * Description Select MTU which will best serve connection from our
133 * point of view.
134 * If our device is 1.2 or lower we calculate how many DH5s
135 * fit into 1 RFCOMM buffer.
136 *
137 *
138 ******************************************************************************/
port_select_mtu(tPORT * p_port)139 void port_select_mtu(tPORT* p_port) {
140 uint16_t packet_size;
141
142 /* Will select MTU only if application did not setup something */
143 if (p_port->mtu == 0) {
144 /* find packet size which connection supports */
145 packet_size = get_btm_client_interface().peer.BTM_GetMaxPacketSize(p_port->bd_addr);
146 if (packet_size == 0) {
147 /* something is very wrong */
148 log::warn("bad packet size 0 for{}", p_port->bd_addr);
149 p_port->mtu = RFCOMM_DEFAULT_MTU;
150 } else {
151 /* We try to negotiate MTU that each packet can be split into whole
152 number of max packets. For example if link is 1.2 max packet size is 339
153 bytes.
154 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4
155 overhead.
156 1695, that will be 5 Dh5 packets. Now maximum RFCOMM packet is
157 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691. Minus RFCOMM 6 bytes
158 header overhead 1685
159
160 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1
161 3DH5 packet
162 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. Minus RFCOMM 6 bytes
163 header overhead 1017 */
164 if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size) {
165 p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) -
166 RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
167 log::verbose("selected {} based on connection speed", p_port->mtu);
168 } else {
169 p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
170 log::verbose("selected {} based on l2cap PDU size", p_port->mtu);
171 }
172 }
173 } else {
174 log::verbose("application selected {}", p_port->mtu);
175 }
176 p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
177 if (p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM) {
178 p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
179 }
180 p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu);
181 if (p_port->credit_rx_low > PORT_RX_BUF_LOW_WM) {
182 p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
183 }
184 p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
185 if (p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM) {
186 p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
187 }
188 log::verbose("credit_rx_max {}, credit_rx_low {}, rx_buf_critical {}", p_port->credit_rx_max,
189 p_port->credit_rx_low, p_port->rx_buf_critical);
190 }
191
192 /*******************************************************************************
193 *
194 * Function port_release_port
195 *
196 * Description Release port control block.
197 *
198 * Returns Pointer to the PORT or NULL if not found
199 *
200 ******************************************************************************/
port_release_port(tPORT * p_port)201 void port_release_port(tPORT* p_port) {
202 log::verbose("p_port: {} state: {} keep_handle: {}", std::format_ptr(p_port),
203 p_port->rfc.sm_cb.state, p_port->keep_port_handle);
204
205 mutex_global_lock();
206 BT_HDR* p_buf;
207 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) != nullptr) {
208 osi_free(p_buf);
209 }
210 p_port->rx.queue_size = 0;
211
212 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) != nullptr) {
213 osi_free(p_buf);
214 }
215 p_port->tx.queue_size = 0;
216 mutex_global_unlock();
217
218 alarm_cancel(p_port->rfc.port_timer);
219
220 p_port->state = PORT_CONNECTION_STATE_CLOSED;
221
222 if (p_port->rfc.sm_cb.state == RFC_STATE_CLOSED) {
223 if (p_port->rfc.p_mcb) {
224 p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0;
225
226 /* If there are no more ports opened on this MCB release it */
227 rfc_check_mcb_active(p_port->rfc.p_mcb);
228 }
229
230 rfc_port_timer_stop(p_port);
231 p_port->rfc.sm_cb = {};
232
233 mutex_global_lock();
234 fixed_queue_free(p_port->tx.queue, nullptr);
235 p_port->tx.queue = nullptr;
236 fixed_queue_free(p_port->rx.queue, nullptr);
237 p_port->rx.queue = nullptr;
238 mutex_global_unlock();
239
240 if (p_port->keep_port_handle) {
241 log::verbose("Re-initialize handle: {}", p_port->handle);
242
243 /* save event mask and callback */
244 uint32_t mask = p_port->ev_mask;
245 tPORT_CALLBACK* p_port_cb = p_port->p_callback;
246 PortSettings user_port_settings = p_port->user_port_settings;
247
248 port_set_defaults(p_port);
249
250 /* restore */
251 p_port->ev_mask = mask;
252 p_port->p_callback = p_port_cb;
253 p_port->user_port_settings = user_port_settings;
254 p_port->mtu = p_port->keep_mtu;
255
256 p_port->state = PORT_CONNECTION_STATE_OPENING;
257 p_port->rfc.p_mcb = nullptr;
258 if (p_port->is_server) {
259 p_port->dlci &= 0xfe;
260 }
261
262 p_port->local_ctrl.modem_signal = p_port->default_signal_state;
263 p_port->bd_addr = RawAddress::kAny;
264 } else {
265 log::verbose("Clean-up handle: {}", p_port->handle);
266 alarm_free(p_port->rfc.port_timer);
267 memset(p_port, 0, sizeof(tPORT));
268 }
269 }
270 }
271
272 /*******************************************************************************
273 *
274 * Function port_find_mcb
275 *
276 * Description This function checks if connection exists to device with
277 * the address.
278 *
279 ******************************************************************************/
port_find_mcb(const RawAddress & bd_addr)280 tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) {
281 for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) {
282 if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) {
283 /* Multiplexer channel found do not change anything */
284 log::verbose("found, bd_addr:{}, rfc_mcb:{}, lcid:0x{:x}", bd_addr, std::format_ptr(&mcb),
285 mcb.lcid);
286 return &mcb;
287 }
288 }
289 log::warn("not found, bd_addr:{}", bd_addr);
290 return nullptr;
291 }
292
293 /*******************************************************************************
294 *
295 * Function port_find_mcb_dlci_port
296 *
297 * Description Find port on the multiplexer channel based on DLCI. If
298 * this port with DLCI not found try to use even DLCI. This
299 * is for the case when client is establishing connection on
300 * none-initiator MCB.
301 *
302 * Returns Pointer to the PORT or NULL if not found
303 *
304 ******************************************************************************/
port_find_mcb_dlci_port(tRFC_MCB * p_mcb,uint8_t dlci)305 tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
306 if (!p_mcb) {
307 log::error("p_mcb is null, dlci={}", dlci);
308 return nullptr;
309 }
310
311 if (dlci > RFCOMM_MAX_DLCI) {
312 log::warn("DLCI {} is too large, bd_addr={}, p_mcb={}", dlci, p_mcb->bd_addr,
313 std::format_ptr(p_mcb));
314 return nullptr;
315 }
316
317 uint8_t handle = p_mcb->port_handles[dlci];
318 if (handle == 0) {
319 log::info("Cannot find allocated RFCOMM app port for DLCI {} on {}, p_mcb={}", dlci,
320 p_mcb->bd_addr, std::format_ptr(p_mcb));
321 return nullptr;
322 }
323 return &rfc_cb.port.port[handle - 1];
324 }
325
326 /*******************************************************************************
327 *
328 * Function port_find_dlci_port
329 *
330 * Description Find port with DLCI not assigned to multiplexer channel
331 *
332 * Returns Pointer to the PORT or NULL if not found
333 *
334 ******************************************************************************/
port_find_dlci_port(uint8_t dlci)335 tPORT* port_find_dlci_port(uint8_t dlci) {
336 for (tPORT& port : rfc_cb.port.port) {
337 if (port.in_use && (port.rfc.p_mcb == nullptr)) {
338 if (port.dlci == dlci) {
339 return &port;
340 } else if ((dlci & 0x01) && (port.dlci == (dlci - 1))) {
341 port.dlci++;
342 return &port;
343 }
344 }
345 }
346 return nullptr;
347 }
348
349 /*******************************************************************************
350 *
351 * Function port_find_port
352 *
353 * Description Find port with DLCI, address
354 *
355 * Returns Pointer to the PORT or NULL if not found
356 *
357 ******************************************************************************/
port_find_port(uint8_t dlci,const RawAddress & bd_addr)358 tPORT* port_find_port(uint8_t dlci, const RawAddress& bd_addr) {
359 for (tPORT& port : rfc_cb.port.port) {
360 if (port.in_use && (port.dlci == dlci) && (port.bd_addr == bd_addr)) {
361 return &port;
362 }
363 }
364 return nullptr;
365 }
366
367 /*******************************************************************************
368 *
369 * Function port_flow_control_user
370 *
371 * Description Check the current user flow control and if necessary return
372 * events to be send to the user based on the user's specified
373 * flow control type.
374 *
375 * Returns event mask to be returned to the application
376 *
377 ******************************************************************************/
port_flow_control_user(tPORT * p_port)378 uint32_t port_flow_control_user(tPORT* p_port) {
379 uint32_t event = 0;
380
381 /* Flow control to the user can be caused by flow controlling by the peer */
382 /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
383 /* tx_queue is full */
384 bool fc = p_port->tx.peer_fc || !p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready ||
385 (p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
386 (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
387
388 if (p_port->tx.user_fc == fc) {
389 return 0;
390 }
391
392 p_port->tx.user_fc = fc;
393
394 if (fc) {
395 event = PORT_EV_FC;
396 } else {
397 event = PORT_EV_FC | PORT_EV_FCS;
398 }
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, uint8_t signal) {
413 uint8_t changed_signals = (signal ^ old_signals);
414 uint32_t events = 0;
415
416 if (changed_signals & PORT_DTRDSR_ON) {
417 events |= PORT_EV_DSR;
418
419 if (signal & PORT_DTRDSR_ON) {
420 events |= PORT_EV_DSRS;
421 }
422 }
423
424 if (changed_signals & PORT_CTSRTS_ON) {
425 events |= PORT_EV_CTS;
426
427 if (signal & PORT_CTSRTS_ON) {
428 events |= PORT_EV_CTSS;
429 }
430 }
431
432 if (changed_signals & PORT_RING_ON) {
433 events |= PORT_EV_RING;
434 }
435
436 if (changed_signals & PORT_DCD_ON) {
437 events |= PORT_EV_RLSD;
438
439 if (signal & PORT_DCD_ON) {
440 events |= PORT_EV_RLSDS;
441 }
442 }
443
444 return p_port->ev_mask & events;
445 }
446
447 /*******************************************************************************
448 *
449 * Function port_flow_control_peer
450 *
451 * Description Send flow control messages to the peer for both enabling
452 * and disabling flow control, for both credit-based and
453 * TS 07.10 flow control mechanisms.
454 *
455 * Returns nothing
456 *
457 ******************************************************************************/
port_flow_control_peer(tPORT * p_port,bool enable,uint16_t count)458 void port_flow_control_peer(tPORT* p_port, bool enable, uint16_t count) {
459 if (!p_port->rfc.p_mcb) {
460 return;
461 }
462
463 /* If using credit based flow control */
464 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
465 /* if want to enable flow from peer */
466 if (enable) {
467 /* update rx credits */
468 if (count > p_port->credit_rx) {
469 p_port->credit_rx = 0;
470 } else {
471 p_port->credit_rx -= count;
472 }
473
474 /* If credit count is less than low credit watermark, and user */
475 /* did not force flow control, send a credit update */
476 /* There might be a special case when we just adjusted rx_max */
477 if ((p_port->credit_rx <= p_port->credit_rx_low) && !p_port->rx.user_fc &&
478 (p_port->credit_rx_max > p_port->credit_rx)) {
479 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
480 (uint8_t)(p_port->credit_rx_max - p_port->credit_rx));
481
482 p_port->credit_rx = p_port->credit_rx_max;
483
484 p_port->rx.peer_fc = false;
485 }
486 } else {
487 /* else want to disable flow from peer */
488 /* if client registered data callback, just do what they want */
489 if (p_port->p_data_callback || p_port->p_data_co_callback) {
490 p_port->rx.peer_fc = true;
491 } else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) {
492 /* if queue count reached credit rx max, set peer fc */
493 p_port->rx.peer_fc = true;
494 }
495 }
496 } else {
497 /* else using TS 07.10 flow control */
498 /* if want to enable flow from peer */
499 if (enable) {
500 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
501 /* check if it can be resumed now */
502 if (p_port->rx.peer_fc && (p_port->rx.queue_size < PORT_RX_LOW_WM) &&
503 (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) {
504 p_port->rx.peer_fc = false;
505
506 /* If user did not force flow control allow traffic now */
507 if (!p_port->rx.user_fc) {
508 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, true);
509 }
510 }
511 } else {
512 /* else want to disable flow from peer */
513 /* if client registered data callback, just do what they want */
514 if (p_port->p_data_callback || p_port->p_data_co_callback) {
515 p_port->rx.peer_fc = true;
516 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
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 /* Check the size of the rx queue. If it exceeds certain */
521 /* level and flow control has not been sent to the peer do it now */
522 log::verbose("PORT_DataInd Data reached HW. Sending FC set.");
523
524 p_port->rx.peer_fc = true;
525 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
526 }
527 }
528 }
529 }
530