1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * Port Emulation entity utilities
23 ******************************************************************************/
26 #include "osi/include/mutex.h"
28 #include "bt_target.h"
29 #include "bt_common.h"
38 static const tPORT_STATE default_port_pars =
53 /*******************************************************************************
55 ** Function port_allocate_port
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
62 ** Returns Pointer to the PORT or NULL if not found
64 *******************************************************************************/
65 tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
67 tPORT *p_port = &rfc_cb.port.port[0];
70 for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++)
72 if (yy >= MAX_RFC_PORTS)
75 p_port = &rfc_cb.port.port[yy];
78 memset(p_port, 0, sizeof (tPORT));
80 p_port->in_use = TRUE;
83 /* During the open set default state for the port connection */
84 port_set_defaults (p_port);
86 p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
87 rfc_cb.rfc.last_port = yy;
90 memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
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]);
99 /* If here, no free PORT found */
104 /*******************************************************************************
106 ** Function port_set_defaults
108 ** Description Set defualt port parameters
111 *******************************************************************************/
112 void port_set_defaults (tPORT *p_port)
115 p_port->p_callback = NULL;
116 p_port->port_ctrl = 0;
118 p_port->line_status = 0;
119 p_port->rx_flag_ev_pending = FALSE;
120 p_port->peer_mtu = RFCOMM_DEFAULT_MTU;
122 p_port->user_port_pars = default_port_pars;
123 p_port->peer_port_pars = default_port_pars;
125 p_port->credit_tx = 0;
126 p_port->credit_rx = 0;
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));
133 p_port->tx.queue = fixed_queue_new(SIZE_MAX);
134 p_port->rx.queue = fixed_queue_new(SIZE_MAX);
137 /*******************************************************************************
139 ** Function port_select_mtu
141 ** Description Select MTU which will best serve connection from our
143 ** If our device is 1.2 or lower we calculate how many DH5s
144 ** fit into 1 RFCOMM buffer.
147 *******************************************************************************/
148 void port_select_mtu (tPORT *p_port)
152 /* Will select MTU only if application did not setup something */
153 if (p_port->mtu == 0)
155 /* find packet size which connection supports */
156 packet_size = btm_get_max_packet_size (p_port->bd_addr);
157 if (packet_size == 0)
159 /* something is very wrong */
160 RFCOMM_TRACE_WARNING ("port_select_mtu bad packet size");
161 p_port->mtu = RFCOMM_DEFAULT_MTU;
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
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)
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);
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);
187 RFCOMM_TRACE_DEBUG ("port_select_mtu application selected %d", p_port->mtu);
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);
202 /*******************************************************************************
204 ** Function port_release_port
206 ** Description Release port control block.
208 ** Returns Pointer to the PORT or NULL if not found
210 *******************************************************************************/
211 void port_release_port(tPORT *p_port)
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);
218 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL)
220 p_port->rx.queue_size = 0;
222 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL)
224 p_port->tx.queue_size = 0;
225 mutex_global_unlock();
227 alarm_cancel(p_port->rfc.port_timer);
229 p_port->state = PORT_STATE_CLOSED;
231 if (p_port->rfc.state == RFC_STATE_CLOSED)
233 if (p_port->rfc.p_mcb)
235 p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
237 /* If there are no more ports opened on this MCB release it */
238 rfc_check_mcb_active(p_port->rfc.p_mcb);
241 rfc_port_timer_stop (p_port);
242 fixed_queue_free(p_port->tx.queue, NULL);
243 fixed_queue_free(p_port->rx.queue, NULL);
245 if (p_port->keep_port_handle)
247 RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__, p_port->inx);
249 /* save event mask and callback */
250 UINT32 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;
254 port_set_defaults(p_port);
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;
262 p_port->state = PORT_STATE_OPENING;
263 p_port->rfc.p_mcb = NULL;
264 if (p_port->is_server)
265 p_port->dlci &= 0xfe;
267 p_port->local_ctrl.modem_signal = p_port->default_signal_state;
268 memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
270 RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx);
271 alarm_free(p_port->rfc.port_timer);
272 memset (p_port, 0, sizeof (tPORT));
277 /*******************************************************************************
279 ** Function port_find_mcb
281 ** Description This function checks if connection exists to device with
284 *******************************************************************************/
285 tRFC_MCB *port_find_mcb (BD_ADDR bd_addr)
289 for (i = 0; i < MAX_BD_CONNECTIONS; i++)
291 if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
292 && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))
294 /* Multiplexer channel found do not change anything */
295 RFCOMM_TRACE_DEBUG("port_find_mcb: found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
296 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
297 RFCOMM_TRACE_DEBUG("port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d",
298 i, &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid);
299 return (&rfc_cb.port.rfc_mcb[i]);
302 RFCOMM_TRACE_DEBUG("port_find_mcb: not found, bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
303 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
308 /*******************************************************************************
310 ** Function port_find_mcb_dlci_port
312 ** Description Find port on the multiplexer channel based on DLCI. If
313 ** this port with DLCI not found try to use even DLCI. This
314 ** is for the case when client is establishing connection on
315 ** none-initiator MCB.
317 ** Returns Pointer to the PORT or NULL if not found
319 *******************************************************************************/
320 tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
327 if (dlci > RFCOMM_MAX_DLCI)
330 inx = p_mcb->port_inx[dlci];
333 RFCOMM_TRACE_DEBUG("port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb, dlci);
337 return (&rfc_cb.port.port[inx - 1]);
341 /*******************************************************************************
343 ** Function port_find_dlci_port
345 ** Description Find port with DLCI not assigned to multiplexer channel
347 ** Returns Pointer to the PORT or NULL if not found
349 *******************************************************************************/
350 tPORT *port_find_dlci_port (UINT8 dlci)
355 for (i = 0; i < MAX_RFC_PORTS; i++)
357 p_port = &rfc_cb.port.port[i];
359 if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
361 if (p_port->dlci == dlci)
365 else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
376 /*******************************************************************************
378 ** Function port_find_port
380 ** Description Find port with DLCI, BD_ADDR
382 ** Returns Pointer to the PORT or NULL if not found
384 *******************************************************************************/
385 tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
390 for (i = 0; i < MAX_RFC_PORTS; i++)
392 p_port = &rfc_cb.port.port[i];
394 && (p_port->dlci == dlci)
395 && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
404 /*******************************************************************************
406 ** Function port_flow_control_user
408 ** Description Check the current user flow control and if necessary return
409 ** events to be send to the user based on the user's specified
410 ** flow control type.
412 ** Returns event mask to be returned to the application
414 *******************************************************************************/
415 UINT32 port_flow_control_user (tPORT *p_port)
419 /* Flow control to the user can be caused by flow controlling by the peer */
420 /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
421 /* tx_queue is full */
422 BOOLEAN fc = p_port->tx.peer_fc
423 || !p_port->rfc.p_mcb
424 || !p_port->rfc.p_mcb->peer_ready
425 || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
426 || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
428 if (p_port->tx.user_fc == fc)
431 p_port->tx.user_fc = fc;
436 event = PORT_EV_FC | PORT_EV_FCS;
442 /*******************************************************************************
444 ** Function port_get_signal_changes
446 ** Description Check modem signals that has been changed
448 ** Returns event mask to be returned to the application
450 *******************************************************************************/
451 UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
453 UINT8 changed_signals = (signal ^ old_signals);
456 if (changed_signals & PORT_DTRDSR_ON)
458 events |= PORT_EV_DSR;
460 if (signal & PORT_DTRDSR_ON)
461 events |= PORT_EV_DSRS;
464 if (changed_signals & PORT_CTSRTS_ON)
466 events |= PORT_EV_CTS;
468 if (signal & PORT_CTSRTS_ON)
469 events |= PORT_EV_CTSS;
472 if (changed_signals & PORT_RING_ON)
473 events |= PORT_EV_RING;
475 if (changed_signals & PORT_DCD_ON)
477 events |= PORT_EV_RLSD;
479 if (signal & PORT_DCD_ON)
480 events |= PORT_EV_RLSDS;
483 return (p_port->ev_mask & events);
486 /*******************************************************************************
488 ** Function port_flow_control_peer
490 ** Description Send flow control messages to the peer for both enabling
491 ** and disabling flow control, for both credit-based and
492 ** TS 07.10 flow control mechanisms.
496 *******************************************************************************/
497 void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
499 if (!p_port->rfc.p_mcb)
502 /* If using credit based flow control */
503 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
505 /* if want to enable flow from peer */
508 /* update rx credits */
509 if (count > p_port->credit_rx)
511 p_port->credit_rx = 0;
515 p_port->credit_rx -= count;
518 /* If credit count is less than low credit watermark, and user */
519 /* did not force flow control, send a credit update */
520 /* There might be a special case when we just adjusted rx_max */
521 if ((p_port->credit_rx <= p_port->credit_rx_low)
522 && !p_port->rx.user_fc
523 && (p_port->credit_rx_max > p_port->credit_rx))
525 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
526 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
528 p_port->credit_rx = p_port->credit_rx_max;
530 p_port->rx.peer_fc = FALSE;
533 /* else want to disable flow from peer */
536 /* if client registered data callback, just do what they want */
537 if (p_port->p_data_callback || p_port->p_data_co_callback)
539 p_port->rx.peer_fc = TRUE;
541 /* if queue count reached credit rx max, set peer fc */
542 else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max)
544 p_port->rx.peer_fc = TRUE;
548 /* else using TS 07.10 flow control */
551 /* if want to enable flow from peer */
554 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
555 /* check if it can be resumed now */
556 if (p_port->rx.peer_fc
557 && (p_port->rx.queue_size < PORT_RX_LOW_WM)
558 && (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM))
560 p_port->rx.peer_fc = FALSE;
562 /* If user did not force flow control allow traffic now */
563 if (!p_port->rx.user_fc)
564 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
567 /* else want to disable flow from peer */
570 /* if client registered data callback, just do what they want */
571 if (p_port->p_data_callback || p_port->p_data_co_callback)
573 p_port->rx.peer_fc = TRUE;
574 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
576 /* Check the size of the rx queue. If it exceeds certain */
577 /* level and flow control has not been sent to the peer do it now */
578 else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
579 || (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM))
580 && !p_port->rx.peer_fc)
582 RFCOMM_TRACE_EVENT ("PORT_DataInd Data reached HW. Sending FC set.");
584 p_port->rx.peer_fc = TRUE;
585 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);