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