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 #include "stack/include/btm_client_interface.h"
39
40 static const tPORT_STATE default_port_pars = {
41 PORT_BAUD_RATE_9600,
42 PORT_8_BITS,
43 PORT_ONESTOPBIT,
44 PORT_PARITY_NO,
45 PORT_ODD_PARITY,
46 PORT_FC_OFF,
47 0, /* No rx_char */
48 PORT_XON_DC1,
49 PORT_XOFF_DC3,
50 };
51
52 /*******************************************************************************
53 *
54 * Function port_allocate_port
55 *
56 * Description Look through the Port Control Blocks for a free one. Note
57 * that one server can open several ports with the same SCN
58 * if it can support simulteneous requests from different
59 * clients.
60 *
61 * Returns Pointer to the PORT or NULL if not found
62 *
63 ******************************************************************************/
port_allocate_port(uint8_t dlci,const RawAddress & bd_addr)64 tPORT* port_allocate_port(uint8_t dlci, const RawAddress& bd_addr) {
65 uint8_t port_index = rfc_cb.rfc.last_port_index + static_cast<uint8_t>(1);
66 // Loop at most MAX_RFC_PORTS items
67 for (int loop_counter = 0; loop_counter < MAX_RFC_PORTS;
68 loop_counter++, port_index++) {
69 if (port_index >= MAX_RFC_PORTS) {
70 port_index = 0;
71 }
72 tPORT* p_port = &rfc_cb.port.port[port_index];
73 if (!p_port->in_use) {
74 // Assume that we already called port_release_port on this
75 memset(p_port, 0, sizeof(tPORT));
76 p_port->in_use = true;
77 // handle is a port handle starting from 1
78 p_port->handle = port_index + static_cast<uint8_t>(1);
79 // During the open set default state for the port connection
80 port_set_defaults(p_port);
81 p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
82 p_port->dlci = dlci;
83 p_port->bd_addr = bd_addr;
84 rfc_cb.rfc.last_port_index = port_index;
85 RFCOMM_TRACE_DEBUG(
86 "%s: rfc_cb.port.port[%d]:%p chosen, "
87 "last_port_index:%d, bd_addr=%s",
88 __func__, port_index, p_port, rfc_cb.rfc.last_port_index,
89 bd_addr.ToString().c_str());
90 return p_port;
91 }
92 }
93 LOG(WARNING) << __func__ << ": running out of free ports for dlci "
94 << std::to_string(dlci) << ", bd_addr " << bd_addr;
95 return nullptr;
96 }
97
98 /*******************************************************************************
99 *
100 * Function port_set_defaults
101 *
102 * Description Set defualt port parameters
103 *
104 *
105 ******************************************************************************/
port_set_defaults(tPORT * p_port)106 void port_set_defaults(tPORT* p_port) {
107 p_port->ev_mask = 0;
108 p_port->p_callback = nullptr;
109 p_port->port_ctrl = 0;
110 p_port->error = 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(WARNING) << __func__ << ": 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 RFCOMM_TRACE_DEBUG("%s: selected %d based on connection speed",
172 __func__, p_port->mtu);
173 } else {
174 p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
175 RFCOMM_TRACE_DEBUG("%s: selected %d based on l2cap PDU size", __func__,
176 p_port->mtu);
177 }
178 }
179 } else {
180 RFCOMM_TRACE_DEBUG("%s: application selected %d", __func__, p_port->mtu);
181 }
182 p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
183 if (p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM)
184 p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
185 p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu);
186 if (p_port->credit_rx_low > PORT_RX_BUF_LOW_WM)
187 p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
188 p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
189 if (p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM)
190 p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
191 RFCOMM_TRACE_DEBUG(
192 "%s: credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d", __func__,
193 p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
194 }
195
196 /*******************************************************************************
197 *
198 * Function port_release_port
199 *
200 * Description Release port control block.
201 *
202 * Returns Pointer to the PORT or NULL if not found
203 *
204 ******************************************************************************/
port_release_port(tPORT * p_port)205 void port_release_port(tPORT* p_port) {
206 RFCOMM_TRACE_DEBUG("%s p_port: %p state: %d keep_handle: %d", __func__,
207 p_port, p_port->rfc.state, p_port->keep_port_handle);
208
209 mutex_global_lock();
210 BT_HDR* p_buf;
211 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) !=
212 nullptr) {
213 osi_free(p_buf);
214 }
215 p_port->rx.queue_size = 0;
216
217 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) !=
218 nullptr) {
219 osi_free(p_buf);
220 }
221 p_port->tx.queue_size = 0;
222 mutex_global_unlock();
223
224 alarm_cancel(p_port->rfc.port_timer);
225
226 p_port->state = PORT_STATE_CLOSED;
227
228 if (p_port->rfc.state == RFC_STATE_CLOSED) {
229 if (p_port->rfc.p_mcb) {
230 p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0;
231
232 /* If there are no more ports opened on this MCB release it */
233 rfc_check_mcb_active(p_port->rfc.p_mcb);
234 }
235
236 rfc_port_timer_stop(p_port);
237
238 mutex_global_lock();
239 fixed_queue_free(p_port->tx.queue, nullptr);
240 p_port->tx.queue = nullptr;
241 fixed_queue_free(p_port->rx.queue, nullptr);
242 p_port->rx.queue = nullptr;
243 mutex_global_unlock();
244
245 if (p_port->keep_port_handle) {
246 RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__,
247 p_port->handle);
248
249 /* save event mask and callback */
250 uint32_t mask = p_port->ev_mask;
251 tPORT_CALLBACK* p_port_cb = p_port->p_callback;
252 tPORT_STATE user_port_pars = p_port->user_port_pars;
253
254 port_set_defaults(p_port);
255
256 /* restore */
257 p_port->ev_mask = mask;
258 p_port->p_callback = p_port_cb;
259 p_port->user_port_pars = user_port_pars;
260 p_port->mtu = p_port->keep_mtu;
261
262 p_port->state = PORT_STATE_OPENING;
263 p_port->rfc.p_mcb = nullptr;
264 if (p_port->is_server) p_port->dlci &= 0xfe;
265
266 p_port->local_ctrl.modem_signal = p_port->default_signal_state;
267 p_port->bd_addr = RawAddress::kAny;
268 } else {
269 RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->handle);
270 alarm_free(p_port->rfc.port_timer);
271 memset(p_port, 0, sizeof(tPORT));
272 }
273 }
274 }
275
276 /*******************************************************************************
277 *
278 * Function port_find_mcb
279 *
280 * Description This function checks if connection exists to device with
281 * the address.
282 *
283 ******************************************************************************/
port_find_mcb(const RawAddress & bd_addr)284 tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) {
285 for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) {
286 if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) {
287 /* Multiplexer channel found do not change anything */
288 VLOG(1) << __func__ << ": found bd_addr=" << bd_addr
289 << ", rfc_mcb=" << &mcb << ", lcid=" << loghex(mcb.lcid);
290 return &mcb;
291 }
292 }
293 VLOG(1) << __func__ << ": not found, bd_addr:" << bd_addr;
294 return nullptr;
295 }
296
297 /*******************************************************************************
298 *
299 * Function port_find_mcb_dlci_port
300 *
301 * Description Find port on the multiplexer channel based on DLCI. If
302 * this port with DLCI not found try to use even DLCI. This
303 * is for the case when client is establishing connection on
304 * none-initiator MCB.
305 *
306 * Returns Pointer to the PORT or NULL if not found
307 *
308 ******************************************************************************/
port_find_mcb_dlci_port(tRFC_MCB * p_mcb,uint8_t dlci)309 tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
310 if (!p_mcb) {
311 LOG(ERROR) << __func__ << ": p_mcb is null, dlci=" << std::to_string(dlci);
312 return nullptr;
313 }
314
315 if (dlci > RFCOMM_MAX_DLCI) {
316 LOG(WARNING) << __func__ << ": DLCI " << std::to_string(dlci)
317 << " is too large, bd_addr=" << p_mcb->bd_addr
318 << ", p_mcb=" << p_mcb;
319 return nullptr;
320 }
321
322 uint8_t handle = p_mcb->port_handles[dlci];
323 if (handle == 0) {
324 LOG(INFO) << __func__ << ": Cannot find allocated RFCOMM app port for DLCI "
325 << std::to_string(dlci) << " on " << p_mcb->bd_addr
326 << ", p_mcb=" << p_mcb;
327 return nullptr;
328 }
329 return &rfc_cb.port.port[handle - 1];
330 }
331
332 /*******************************************************************************
333 *
334 * Function port_find_dlci_port
335 *
336 * Description Find port with DLCI not assigned to multiplexer channel
337 *
338 * Returns Pointer to the PORT or NULL if not found
339 *
340 ******************************************************************************/
port_find_dlci_port(uint8_t dlci)341 tPORT* port_find_dlci_port(uint8_t dlci) {
342 for (tPORT& port : rfc_cb.port.port) {
343 if (port.in_use && (port.rfc.p_mcb == nullptr)) {
344 if (port.dlci == dlci) {
345 return &port;
346 } else if ((dlci & 0x01) && (port.dlci == (dlci - 1))) {
347 port.dlci++;
348 return &port;
349 }
350 }
351 }
352 return nullptr;
353 }
354
355 /*******************************************************************************
356 *
357 * Function port_find_port
358 *
359 * Description Find port with DLCI, address
360 *
361 * Returns Pointer to the PORT or NULL if not found
362 *
363 ******************************************************************************/
port_find_port(uint8_t dlci,const RawAddress & bd_addr)364 tPORT* port_find_port(uint8_t dlci, const RawAddress& bd_addr) {
365 for (tPORT& port : rfc_cb.port.port) {
366 if (port.in_use && (port.dlci == dlci) && (port.bd_addr == bd_addr)) {
367 return &port;
368 }
369 }
370 return nullptr;
371 }
372
373 /*******************************************************************************
374 *
375 * Function port_flow_control_user
376 *
377 * Description Check the current user flow control and if necessary return
378 * events to be send to the user based on the user's specified
379 * flow control type.
380 *
381 * Returns event mask to be returned to the application
382 *
383 ******************************************************************************/
port_flow_control_user(tPORT * p_port)384 uint32_t port_flow_control_user(tPORT* p_port) {
385 uint32_t event = 0;
386
387 /* Flow control to the user can be caused by flow controlling by the peer */
388 /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
389 /* tx_queue is full */
390 bool fc = p_port->tx.peer_fc || !p_port->rfc.p_mcb ||
391 !p_port->rfc.p_mcb->peer_ready ||
392 (p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
393 (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
394
395 if (p_port->tx.user_fc == fc) return (0);
396
397 p_port->tx.user_fc = fc;
398
399 if (fc)
400 event = PORT_EV_FC;
401 else
402 event = PORT_EV_FC | PORT_EV_FCS;
403
404 return (event);
405 }
406
407 /*******************************************************************************
408 *
409 * Function port_get_signal_changes
410 *
411 * Description Check modem signals that has been changed
412 *
413 * Returns event mask to be returned to the application
414 *
415 ******************************************************************************/
port_get_signal_changes(tPORT * p_port,uint8_t old_signals,uint8_t signal)416 uint32_t port_get_signal_changes(tPORT* p_port, uint8_t old_signals,
417 uint8_t signal) {
418 uint8_t changed_signals = (signal ^ old_signals);
419 uint32_t events = 0;
420
421 if (changed_signals & PORT_DTRDSR_ON) {
422 events |= PORT_EV_DSR;
423
424 if (signal & PORT_DTRDSR_ON) events |= PORT_EV_DSRS;
425 }
426
427 if (changed_signals & PORT_CTSRTS_ON) {
428 events |= PORT_EV_CTS;
429
430 if (signal & PORT_CTSRTS_ON) events |= PORT_EV_CTSS;
431 }
432
433 if (changed_signals & PORT_RING_ON) events |= PORT_EV_RING;
434
435 if (changed_signals & PORT_DCD_ON) {
436 events |= PORT_EV_RLSD;
437
438 if (signal & PORT_DCD_ON) events |= PORT_EV_RLSDS;
439 }
440
441 return (p_port->ev_mask & events);
442 }
443
444 /*******************************************************************************
445 *
446 * Function port_flow_control_peer
447 *
448 * Description Send flow control messages to the peer for both enabling
449 * and disabling flow control, for both credit-based and
450 * TS 07.10 flow control mechanisms.
451 *
452 * Returns nothing
453 *
454 ******************************************************************************/
port_flow_control_peer(tPORT * p_port,bool enable,uint16_t count)455 void port_flow_control_peer(tPORT* p_port, bool enable, uint16_t count) {
456 if (!p_port->rfc.p_mcb) return;
457
458 /* If using credit based flow control */
459 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
460 /* if want to enable flow from peer */
461 if (enable) {
462 /* update rx credits */
463 if (count > p_port->credit_rx) {
464 p_port->credit_rx = 0;
465 } else {
466 p_port->credit_rx -= count;
467 }
468
469 /* If credit count is less than low credit watermark, and user */
470 /* did not force flow control, send a credit update */
471 /* There might be a special case when we just adjusted rx_max */
472 if ((p_port->credit_rx <= p_port->credit_rx_low) && !p_port->rx.user_fc &&
473 (p_port->credit_rx_max > p_port->credit_rx)) {
474 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
475 (uint8_t)(p_port->credit_rx_max - p_port->credit_rx));
476
477 p_port->credit_rx = p_port->credit_rx_max;
478
479 p_port->rx.peer_fc = false;
480 }
481 }
482 /* else want to disable flow from peer */
483 else {
484 /* if client registered data callback, just do what they want */
485 if (p_port->p_data_callback || p_port->p_data_co_callback) {
486 p_port->rx.peer_fc = true;
487 }
488 /* if queue count reached credit rx max, set peer fc */
489 else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) {
490 p_port->rx.peer_fc = true;
491 }
492 }
493 }
494 /* else using TS 07.10 flow control */
495 else {
496 /* if want to enable flow from peer */
497 if (enable) {
498 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
499 /* check if it can be resumed now */
500 if (p_port->rx.peer_fc && (p_port->rx.queue_size < PORT_RX_LOW_WM) &&
501 (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) {
502 p_port->rx.peer_fc = false;
503
504 /* If user did not force flow control allow traffic now */
505 if (!p_port->rx.user_fc)
506 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, true);
507 }
508 }
509 /* else want to disable flow from peer */
510 else {
511 /* if client registered data callback, just do what they want */
512 if (p_port->p_data_callback || p_port->p_data_co_callback) {
513 p_port->rx.peer_fc = true;
514 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
515 }
516 /* Check the size of the rx queue. If it exceeds certain */
517 /* level and flow control has not been sent to the peer do it now */
518 else if (((p_port->rx.queue_size > PORT_RX_HIGH_WM) ||
519 (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM)) &&
520 !p_port->rx.peer_fc) {
521 RFCOMM_TRACE_EVENT("PORT_DataInd Data reached HW. Sending FC set.");
522
523 p_port->rx.peer_fc = true;
524 RFCOMM_FlowReq(p_port->rfc.p_mcb, p_port->dlci, false);
525 }
526 }
527 }
528 }
529