1 /******************************************************************************
2 *
3 * Copyright (C) 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 <string.h>
25
26 #include "common/bt_target.h"
27 #include "stack/rfcdefs.h"
28 #include "stack/port_api.h"
29 #include "port_int.h"
30 #include "rfc_int.h"
31 #include "stack/l2cdefs.h"
32 #include "btm_int.h"
33 #include "stack/btu.h"
34 #include "osi/mutex.h"
35 #include "osi/allocator.h"
36 #if (defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
37
38 static const tPORT_STATE default_port_pars = {
39 PORT_BAUD_RATE_9600,
40 PORT_8_BITS,
41 PORT_ONESTOPBIT,
42 PORT_PARITY_NO,
43 PORT_ODD_PARITY,
44 PORT_FC_OFF,
45 0, /* No rx_char */
46 PORT_XON_DC1,
47 PORT_XOFF_DC3,
48 };
49
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 dlci,BD_ADDR bd_addr)64 tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
65 {
66 tPORT *p_port = &rfc_cb.port.port[0];
67 UINT8 xx, yy;
68
69 for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++) {
70 if (yy >= MAX_RFC_PORTS) {
71 yy = 0;
72 }
73
74 p_port = &rfc_cb.port.port[yy];
75 if (!p_port->in_use) {
76 memset (p_port, 0, sizeof (tPORT));
77
78 p_port->in_use = TRUE;
79 p_port->inx = yy + 1;
80
81 p_port->dlci = dlci;
82 memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
83
84 /* During the open set default state for the port connection */
85 port_set_defaults (p_port);
86
87 rfc_cb.rfc.last_port = yy;
88 RFCOMM_TRACE_DEBUG("rfc_cb.port.port[%d]:%p allocated, last_port:%d", yy, p_port, rfc_cb.rfc.last_port);
89 RFCOMM_TRACE_DEBUG("port_allocate_port:bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
90 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
91 return (p_port);
92 }
93 }
94
95 /* If here, no free PORT found */
96 return (NULL);
97 }
98
99
100 /*******************************************************************************
101 **
102 ** Function port_set_defaults
103 **
104 ** Description Set defualt port parameters
105 **
106 **
107 *******************************************************************************/
port_set_defaults(tPORT * p_port)108 void port_set_defaults (tPORT *p_port)
109 {
110 p_port->ev_mask = 0;
111 p_port->p_callback = NULL;
112 p_port->port_ctrl = 0;
113 p_port->error = 0;
114 p_port->line_status = 0;
115 p_port->rx_flag_ev_pending = FALSE;
116 p_port->peer_mtu = RFCOMM_DEFAULT_MTU;
117
118 p_port->user_port_pars = default_port_pars;
119 p_port->peer_port_pars = default_port_pars;
120
121 p_port->credit_tx = 0;
122 p_port->credit_rx = 0;
123 /* p_port->credit_rx_max = PORT_CREDIT_RX_MAX; Determined later */
124 /* p_port->credit_rx_low = PORT_CREDIT_RX_LOW; Determined later */
125
126 memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl));
127 memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl));
128 memset (&p_port->rx, 0, sizeof (p_port->rx));
129 memset (&p_port->tx, 0, sizeof (p_port->tx));
130
131 p_port->tx.queue = fixed_queue_new(QUEUE_SIZE_MAX);
132 p_port->rx.queue = fixed_queue_new(QUEUE_SIZE_MAX);
133 }
134
135 /*******************************************************************************
136 **
137 ** Function port_select_mtu
138 **
139 ** Description Select MTU which will best serve connection from our
140 ** point of view.
141 ** If our device is 1.2 or lower we calculate how many DH5s
142 ** fit into 1 RFCOMM buffer.
143 **
144 **
145 *******************************************************************************/
port_select_mtu(tPORT * p_port)146 void port_select_mtu (tPORT *p_port)
147 {
148 UINT16 packet_size;
149
150 /* Will select MTU only if application did not setup something */
151 if (p_port->mtu == 0) {
152 /* find packet size which connection supports */
153 packet_size = btm_get_max_packet_size (p_port->bd_addr);
154 if (packet_size == 0) {
155 /* something is very wrong */
156 RFCOMM_TRACE_WARNING ("port_select_mtu bad packet size");
157 p_port->mtu = RFCOMM_DEFAULT_MTU;
158 } else {
159 /* We try to negotiate MTU that each packet can be split into whole
160 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
161 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
162 1695, that will be 5 Dh5 packets. Now maximum RFCOMM packet is
163 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691. Minus RFCOMM 6 bytes header overhead 1685
164
165 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
166 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. Minus RFCOMM 6 bytes 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 * packet_size) - RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
169 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on connection speed", p_port->mtu);
170 } else {
171 p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
172 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
173 }
174 }
175 } else {
176 RFCOMM_TRACE_DEBUG ("port_select_mtu application selected %d", p_port->mtu);
177 }
178 p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
179 if ( p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM ) {
180 p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
181 }
182 p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu);
183 if ( p_port->credit_rx_low > PORT_RX_BUF_LOW_WM ) {
184 p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
185 }
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 }
190 RFCOMM_TRACE_DEBUG ("port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d",
191 p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
192 }
193
194
195 /*******************************************************************************
196 **
197 ** Function port_release_port
198 **
199 ** Description Release port infor 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 {
206 BT_HDR *p_buf;
207 UINT32 mask;
208 tPORT_CALLBACK *p_port_cb;
209 tPORT_STATE user_port_pars;
210
211 osi_mutex_global_lock();
212 RFCOMM_TRACE_DEBUG("port_release_port, p_port:%p", p_port);
213 if (p_port->rx.queue != NULL) {
214 while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->rx.queue, 0)) != NULL) {
215 osi_free(p_buf);
216 }
217 }
218 p_port->rx.queue_size = 0;
219
220 if (p_port->tx.queue != NULL) {
221 while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->tx.queue, 0)) != NULL) {
222 osi_free(p_buf);
223 }
224 }
225 p_port->tx.queue_size = 0;
226
227 osi_mutex_global_unlock();
228
229 p_port->state = PORT_STATE_CLOSED;
230
231 if (p_port->rfc.state == RFC_STATE_CLOSED) {
232 RFCOMM_TRACE_DEBUG ("rfc_port_closed DONE");
233 if (p_port->rfc.p_mcb) {
234 p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
235
236 /* If there are no more ports opened on this MCB release it */
237 rfc_check_mcb_active (p_port->rfc.p_mcb);
238 }
239 rfc_port_timer_stop (p_port);
240 fixed_queue_free(p_port->tx.queue, NULL);
241 p_port->tx.queue = NULL;
242 fixed_queue_free(p_port->rx.queue, NULL);
243 p_port->rx.queue = NULL;
244
245 RFCOMM_TRACE_DEBUG ("port_release_port:p_port->keep_port_handle:%d", p_port->keep_port_handle);
246 if ( p_port->keep_port_handle ) {
247 RFCOMM_TRACE_DEBUG ("port_release_port:Initialize handle:%d", p_port->inx);
248 /* save event mask and callback */
249 mask = p_port->ev_mask;
250 p_port_cb = p_port->p_callback;
251 user_port_pars = p_port->user_port_pars;
252
253 port_set_defaults(p_port);
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 = NULL;
262 if (p_port->is_server) {
263 p_port->dlci &= 0xfe;
264 }
265
266 p_port->local_ctrl.modem_signal = p_port->default_signal_state;
267 memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
268 } else {
269 RFCOMM_TRACE_DEBUG ("port_release_port:Clean-up handle:%d", p_port->inx);
270 rfc_port_timer_free (p_port);
271 memset (p_port, 0, sizeof (tPORT));
272 }
273 }
274 }
275
276
277 /*******************************************************************************
278 **
279 ** Function port_find_mcb
280 **
281 ** Description This function checks if connection exists to device with
282 ** the BD_ADDR.
283 **
284 *******************************************************************************/
port_find_mcb(BD_ADDR bd_addr)285 tRFC_MCB *port_find_mcb (BD_ADDR bd_addr)
286 {
287 int i;
288
289 for (i = 0; i < MAX_BD_CONNECTIONS; i++) {
290 if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
291 && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN)) {
292 /* Multiplexer channel found do not change anything */
293 RFCOMM_TRACE_DEBUG("port_find_mcb: found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
294 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
295 RFCOMM_TRACE_DEBUG("port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d",
296 i, &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid);
297 return (&rfc_cb.port.rfc_mcb[i]);
298 }
299 }
300 RFCOMM_TRACE_DEBUG("port_find_mcb: not found, bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
301 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
302 return (NULL);
303 }
304
305
306 /*******************************************************************************
307 **
308 ** Function port_find_mcb_dlci_port
309 **
310 ** Description Find port on the multiplexer channel based on DLCI. If
311 ** this port with DLCI not found try to use even DLCI. This
312 ** is for the case when client is establishing connection on
313 ** none-initiator MCB.
314 **
315 ** Returns Pointer to the PORT or NULL if not found
316 **
317 *******************************************************************************/
port_find_mcb_dlci_port(tRFC_MCB * p_mcb,UINT8 dlci)318 tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
319 {
320 UINT8 inx;
321
322 if (!p_mcb) {
323 return (NULL);
324 }
325
326 if (dlci > RFCOMM_MAX_DLCI) {
327 return (NULL);
328 }
329
330 inx = p_mcb->port_inx[dlci];
331 if (inx == 0) {
332 RFCOMM_TRACE_DEBUG("port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb, dlci);
333 return (NULL);
334 } else {
335 return (&rfc_cb.port.port[inx - 1]);
336 }
337 }
338
339
340 /*******************************************************************************
341 **
342 ** Function port_find_dlci_port
343 **
344 ** Description Find port with DLCI not assigned to multiplexer channel
345 **
346 ** Returns Pointer to the PORT or NULL if not found
347 **
348 *******************************************************************************/
port_find_dlci_port(UINT8 dlci)349 tPORT *port_find_dlci_port (UINT8 dlci)
350 {
351 UINT16 i;
352 tPORT *p_port;
353
354 for (i = 0; i < MAX_RFC_PORTS; i++) {
355 p_port = &rfc_cb.port.port[i];
356
357 if (p_port->in_use && (p_port->rfc.p_mcb == NULL)) {
358 if (p_port->dlci == dlci) {
359 return (p_port);
360 } else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1))) {
361 p_port->dlci++;
362 return (p_port);
363 }
364 }
365 }
366 return (NULL);
367 }
368
369
370 /*******************************************************************************
371 **
372 ** Function port_find_port
373 **
374 ** Description Find port with DLCI, BD_ADDR
375 **
376 ** Returns Pointer to the PORT or NULL if not found
377 **
378 *******************************************************************************/
port_find_port(UINT8 dlci,BD_ADDR bd_addr)379 tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
380 {
381 UINT16 i;
382 tPORT *p_port;
383
384 for (i = 0; i < MAX_RFC_PORTS; i++) {
385 p_port = &rfc_cb.port.port[i];
386 if (p_port->in_use
387 && (p_port->dlci == dlci)
388 && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN)) {
389 return (p_port);
390 }
391 }
392 return (NULL);
393 }
394
395
396 /*******************************************************************************
397 **
398 ** Function port_flow_control_user
399 **
400 ** Description Check the current user flow control and if necessary return
401 ** events to be send to the user based on the user's specified
402 ** flow control type.
403 **
404 ** Returns event mask to be returned to the application
405 **
406 *******************************************************************************/
port_flow_control_user(tPORT * p_port)407 UINT32 port_flow_control_user (tPORT *p_port)
408 {
409 UINT32 event = 0;
410
411 /* Flow control to the user can be caused by flow controlling by the peer */
412 /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
413 /* tx_queue is full */
414 BOOLEAN fc = p_port->tx.peer_fc
415 || !p_port->rfc.p_mcb
416 || !p_port->rfc.p_mcb->peer_ready
417 || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
418 || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
419
420 if (p_port->tx.user_fc == fc) {
421 return (0);
422 }
423
424 p_port->tx.user_fc = fc;
425
426 if (fc) {
427 event = PORT_EV_FC;
428 } else {
429 event = PORT_EV_FC | PORT_EV_FCS;
430 }
431
432 return (event);
433 }
434
435
436 /*******************************************************************************
437 **
438 ** Function port_get_signal_changes
439 **
440 ** Description Check modem signals that has been changed
441 **
442 ** Returns event mask to be returned to the application
443 **
444 *******************************************************************************/
port_get_signal_changes(tPORT * p_port,UINT8 old_signals,UINT8 signal)445 UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
446 {
447 UINT8 changed_signals = (signal ^ old_signals);
448 UINT32 events = 0;
449
450 if (changed_signals & PORT_DTRDSR_ON) {
451 events |= PORT_EV_DSR;
452
453 if (signal & PORT_DTRDSR_ON) {
454 events |= PORT_EV_DSRS;
455 }
456 }
457
458 if (changed_signals & PORT_CTSRTS_ON) {
459 events |= PORT_EV_CTS;
460
461 if (signal & PORT_CTSRTS_ON) {
462 events |= PORT_EV_CTSS;
463 }
464 }
465
466 if (changed_signals & PORT_RING_ON) {
467 events |= PORT_EV_RING;
468 }
469
470 if (changed_signals & PORT_DCD_ON) {
471 events |= PORT_EV_RLSD;
472
473 if (signal & PORT_DCD_ON) {
474 events |= PORT_EV_RLSDS;
475 }
476 }
477
478 return (p_port->ev_mask & events);
479 }
480
481 /*******************************************************************************
482 **
483 ** Function port_flow_control_peer
484 **
485 ** Description Send flow control messages to the peer for both enabling
486 ** and disabling flow control, for both credit-based and
487 ** TS 07.10 flow control mechanisms.
488 **
489 ** Returns nothing
490 **
491 *******************************************************************************/
port_flow_control_peer(tPORT * p_port,BOOLEAN enable,UINT16 count)492 void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
493 {
494 if (!p_port->rfc.p_mcb) {
495 return;
496 }
497
498 /* If using credit based flow control */
499 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
500 /* if want to enable flow from peer */
501 if (enable) {
502 /* update rx credits */
503 if (count > p_port->credit_rx) {
504 p_port->credit_rx = 0;
505 } else {
506 p_port->credit_rx -= count;
507 }
508
509 /* If credit count is less than low credit watermark, and user */
510 /* did not force flow control, send a credit update */
511 /* There might be a special case when we just adjusted rx_max */
512 if ((p_port->credit_rx <= p_port->credit_rx_low)
513 && !p_port->rx.user_fc
514 && (p_port->credit_rx_max > p_port->credit_rx)) {
515 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
516 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
517 RFCOMM_TRACE_DEBUG("send credit: max %d, rx %d, count %d", p_port->credit_rx_max, p_port->credit_rx, count);
518 p_port->credit_rx = p_port->credit_rx_max;
519
520 p_port->rx.peer_fc = FALSE;
521 } else {
522 RFCOMM_TRACE_DEBUG("credit: max %d, rx %d, low %d", p_port->credit_rx_max, p_port->credit_rx, p_port->credit_rx_low);
523 }
524 }
525 /* else want to disable flow from peer */
526 else {
527 /* if client registered data callback, just do what they want */
528 if (p_port->p_data_callback || p_port->p_data_co_callback) {
529 p_port->rx.peer_fc = TRUE;
530 }
531 /* if queue count reached credit rx max, set peer fc */
532 else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) {
533 p_port->rx.peer_fc = TRUE;
534 }
535 }
536 }
537 /* else using TS 07.10 flow control */
538 else {
539 /* if want to enable flow from peer */
540 if (enable) {
541 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
542 /* check if it can be resumed now */
543 if (p_port->rx.peer_fc
544 && (p_port->rx.queue_size < PORT_RX_LOW_WM)
545 && (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) {
546 p_port->rx.peer_fc = FALSE;
547
548 /* If user did not force flow control allow traffic now */
549 if (!p_port->rx.user_fc) {
550 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
551 }
552 }
553 }
554 /* else want to disable flow from peer */
555 else {
556 /* if client registered data callback, just do what they want */
557 if (p_port->p_data_callback || p_port->p_data_co_callback) {
558 p_port->rx.peer_fc = TRUE;
559 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
560 }
561 /* Check the size of the rx queue. If it exceeds certain */
562 /* level and flow control has not been sent to the peer do it now */
563 else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
564 || (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM))
565 && !p_port->rx.peer_fc) {
566 RFCOMM_TRACE_EVENT ("PORT_DataInd Data reached HW. Sending FC set.");
567
568 p_port->rx.peer_fc = TRUE;
569 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
570 }
571 }
572 }
573 }
574
575
576 #endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
577