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
38static 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*******************************************************************************/
65tPORT *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*******************************************************************************/
112void 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*******************************************************************************/
148void 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*******************************************************************************/
211void 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*******************************************************************************/
287tRFC_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*******************************************************************************/
322tPORT *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*******************************************************************************/
352tPORT *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*******************************************************************************/
387tPORT *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*******************************************************************************/
417UINT32 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*******************************************************************************/
453UINT32 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*******************************************************************************/
499void 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