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