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#include <cutils/log.h>
37#define info(fmt, ...)  ALOGI ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
38#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
39#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
40#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
41
42
43static const tPORT_STATE default_port_pars =
44{
45    PORT_BAUD_RATE_9600,
46    PORT_8_BITS,
47    PORT_ONESTOPBIT,
48    PORT_PARITY_NO,
49    PORT_ODD_PARITY,
50    PORT_FC_OFF,
51    0,                      /* No rx_char */
52    PORT_XON_DC1,
53    PORT_XOFF_DC3,
54};
55
56
57
58/*******************************************************************************
59**
60** Function         port_allocate_port
61**
62** Description      Look through the Port Control Blocks for a free one.  Note
63**                  that one server can open several ports with the same SCN
64**                  if it can support simulteneous requests from different
65**                  clients.
66**
67** Returns          Pointer to the PORT or NULL if not found
68**
69*******************************************************************************/
70tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
71{
72    tPORT  *p_port = &rfc_cb.port.port[0];
73    UINT8  xx, yy;
74
75    for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++)
76    {
77        if (yy >= MAX_RFC_PORTS)
78            yy = 0;
79
80        p_port = &rfc_cb.port.port[yy];
81        if (!p_port->in_use)
82        {
83            memset (p_port, 0, sizeof (tPORT));
84
85            p_port->in_use = TRUE;
86            p_port->inx    = yy + 1;
87
88            p_port->dlci   = dlci;
89            memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
90
91            /* During the open set default state for the port connection */
92            port_set_defaults (p_port);
93
94            rfc_cb.rfc.last_port = yy;
95            debug("rfc_cb.port.port[%d] allocated, last_port:%d", yy, rfc_cb.rfc.last_port);
96            return (p_port);
97        }
98    }
99
100    /* If here, no free PORT found */
101    return (NULL);
102}
103
104
105/*******************************************************************************
106**
107** Function         port_set_defaults
108**
109** Description      Set defualt port parameters
110**
111**
112*******************************************************************************/
113void port_set_defaults (tPORT *p_port)
114{
115    p_port->ev_mask        = 0;
116    p_port->p_callback     = NULL;
117    p_port->port_ctrl      = 0;
118    p_port->error          = 0;
119    p_port->line_status    = 0;
120    p_port->rx_flag_ev_pending = FALSE;
121    p_port->peer_mtu       = RFCOMM_DEFAULT_MTU;
122
123    p_port->user_port_pars = default_port_pars;
124    p_port->peer_port_pars = default_port_pars;
125
126    p_port->credit_tx      = 0;
127    p_port->credit_rx      = 0;
128/*  p_port->credit_rx_max  = PORT_CREDIT_RX_MAX;            Determined later */
129/*  p_port->credit_rx_low  = PORT_CREDIT_RX_LOW;            Determined later */
130
131    memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl));
132    memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl));
133    memset (&p_port->rx, 0, sizeof (p_port->rx));
134    memset (&p_port->tx, 0, sizeof (p_port->tx));
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_WARNING0 ("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_DEBUG1 ("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_DEBUG1 ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
182            }
183        }
184    }
185    else
186    {
187        RFCOMM_TRACE_DEBUG1 ("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_DEBUG3 ("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**
205** Function         port_release_port
206**
207** Description      Release port infor control block.
208**
209** Returns          Pointer to the PORT or NULL if not found
210**
211*******************************************************************************/
212void port_release_port (tPORT *p_port)
213{
214    BT_HDR *p_buf;
215    UINT32 mask;
216    tPORT_CALLBACK *p_port_cb;
217    tPORT_STATE user_port_pars;
218
219    PORT_SCHEDULE_LOCK;
220    debug("port_release_port, p_port:%p", p_port);
221    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL)
222        GKI_freebuf (p_buf);
223
224    p_port->rx.queue_size = 0;
225
226    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL)
227        GKI_freebuf (p_buf);
228
229    p_port->tx.queue_size = 0;
230
231    PORT_SCHEDULE_UNLOCK;
232
233    p_port->state = PORT_STATE_CLOSED;
234
235    if (p_port->rfc.state == RFC_STATE_CLOSED)
236    {
237        RFCOMM_TRACE_DEBUG0 ("rfc_port_closed DONE");
238        if (p_port->rfc.p_mcb)
239        {
240            p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
241
242            /* If there are no more ports opened on this MCB release it */
243            rfc_check_mcb_active (p_port->rfc.p_mcb);
244        }
245        rfc_port_timer_stop (p_port);
246
247        if( p_port->keep_port_handle )
248        {
249            RFCOMM_TRACE_DEBUG1 ("port_release_port:Initialize handle:%d", p_port->inx);
250            /* save event mask and callback */
251            mask = p_port->ev_mask;
252            p_port_cb = p_port->p_callback;
253            user_port_pars = p_port->user_port_pars;
254
255            port_set_defaults(p_port);
256            /* restore */
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;
261
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;
266
267            p_port->local_ctrl.modem_signal = p_port->default_signal_state;
268            memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
269        }
270        else
271        {
272            RFCOMM_TRACE_DEBUG1 ("port_release_port:Clean-up handle:%d", p_port->inx);
273            memset (p_port, 0, sizeof (tPORT));
274        }
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            return (&rfc_cb.port.rfc_mcb[i]);
298        }
299    }
300    return (NULL);
301}
302
303
304/*******************************************************************************
305**
306** Function         port_find_mcb_dlci_port
307**
308** Description      Find port on the multiplexer channel based on DLCI.  If
309**                  this port with DLCI not found try to use even DLCI.  This
310**                  is for the case when client is establishing connection on
311**                  none-initiator MCB.
312**
313** Returns          Pointer to the PORT or NULL if not found
314**
315*******************************************************************************/
316tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
317{
318    UINT8 inx;
319
320    if (!p_mcb)
321        return (NULL);
322
323    if (dlci > RFCOMM_MAX_DLCI)
324        return (NULL);
325
326    inx = p_mcb->port_inx[dlci];
327    if (inx == 0)
328        return (NULL);
329    else
330        return (&rfc_cb.port.port[inx - 1]);
331}
332
333
334/*******************************************************************************
335**
336** Function         port_find_dlci_port
337**
338** Description      Find port with DLCI not assigned to multiplexer channel
339**
340** Returns          Pointer to the PORT or NULL if not found
341**
342*******************************************************************************/
343tPORT *port_find_dlci_port (UINT8 dlci)
344{
345    UINT16 i;
346    tPORT  *p_port;
347
348    for (i = 0; i < MAX_RFC_PORTS; i++)
349    {
350        p_port = &rfc_cb.port.port[i];
351        if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
352        {
353            if (p_port->dlci == dlci)
354            {
355                return (p_port);
356            }
357            else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
358            {
359                p_port->dlci++;
360                return (p_port);
361            }
362        }
363    }
364    return (NULL);
365}
366
367
368/*******************************************************************************
369**
370** Function         port_find_port
371**
372** Description      Find port with DLCI, BD_ADDR
373**
374** Returns          Pointer to the PORT or NULL if not found
375**
376*******************************************************************************/
377tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
378{
379    UINT16 i;
380    tPORT  *p_port;
381
382    for (i = 0; i < MAX_RFC_PORTS; i++)
383    {
384        p_port = &rfc_cb.port.port[i];
385        if (p_port->in_use
386         && (p_port->dlci == dlci)
387         && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
388        {
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*******************************************************************************/
407UINT32 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              || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM);
419
420    if (p_port->tx.user_fc == fc)
421        return (0);
422
423    p_port->tx.user_fc = fc;
424
425    if (fc)
426        event = PORT_EV_FC;
427    else
428        event = PORT_EV_FC | PORT_EV_FCS;
429
430    return (event);
431}
432
433
434/*******************************************************************************
435**
436** Function         port_get_signal_changes
437**
438** Description      Check modem signals that has been changed
439**
440** Returns          event mask to be returned to the application
441**
442*******************************************************************************/
443UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
444{
445    UINT8  changed_signals = (signal ^ old_signals);
446    UINT32 events = 0;
447
448    if (changed_signals & PORT_DTRDSR_ON)
449    {
450        events |= PORT_EV_DSR;
451
452        if (signal & PORT_DTRDSR_ON)
453            events |= PORT_EV_DSRS;
454    }
455
456    if (changed_signals & PORT_CTSRTS_ON)
457    {
458        events |= PORT_EV_CTS;
459
460        if (signal & PORT_CTSRTS_ON)
461            events |= PORT_EV_CTSS;
462    }
463
464    if (changed_signals & PORT_RING_ON)
465        events |= PORT_EV_RING;
466
467    if (changed_signals & PORT_DCD_ON)
468    {
469        events |= PORT_EV_RLSD;
470
471        if (signal & PORT_DCD_ON)
472            events |= PORT_EV_RLSDS;
473    }
474
475    return (p_port->ev_mask & events);
476}
477
478/*******************************************************************************
479**
480** Function         port_flow_control_peer
481**
482** Description      Send flow control messages to the peer for both enabling
483**                  and disabling flow control, for both credit-based and
484**                  TS 07.10 flow control mechanisms.
485**
486** Returns          nothing
487**
488*******************************************************************************/
489void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
490{
491    if (!p_port->rfc.p_mcb)
492        return;
493
494    /* If using credit based flow control */
495    if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
496    {
497        /* if want to enable flow from peer */
498        if (enable)
499        {
500            /* update rx credits */
501            if (count > p_port->credit_rx)
502            {
503                p_port->credit_rx = 0;
504            }
505            else
506            {
507                p_port->credit_rx -= count;
508            }
509
510            /* If credit count is less than low credit watermark, and user */
511            /* did not force flow control, send a credit update */
512            /* There might be a special case when we just adjusted rx_max */
513            if ((p_port->credit_rx <= p_port->credit_rx_low)
514             && !p_port->rx.user_fc
515             && (p_port->credit_rx_max > p_port->credit_rx))
516            {
517                rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
518                                (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
519
520                p_port->credit_rx = p_port->credit_rx_max;
521
522                p_port->rx.peer_fc = FALSE;
523            }
524        }
525        /* else want to disable flow from peer */
526        else
527        {
528            /* if client registered data callback, just do what they want */
529            if (p_port->p_data_callback || p_port->p_data_co_callback)
530            {
531                p_port->rx.peer_fc = TRUE;
532            }
533            /* if queue count reached credit rx max, set peer fc */
534            else if (p_port->rx.queue.count >= p_port->credit_rx_max)
535            {
536                p_port->rx.peer_fc = TRUE;
537            }
538        }
539    }
540    /* else using TS 07.10 flow control */
541    else
542    {
543        /* if want to enable flow from peer */
544        if (enable)
545        {
546            /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
547            /* check if it can be resumed now */
548            if (p_port->rx.peer_fc
549             && (p_port->rx.queue_size < PORT_RX_LOW_WM)
550             && (p_port->rx.queue.count < PORT_RX_BUF_LOW_WM))
551            {
552                p_port->rx.peer_fc = FALSE;
553
554                /* If user did not force flow control allow traffic now */
555                if (!p_port->rx.user_fc)
556                    RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
557            }
558        }
559        /* else want to disable flow from peer */
560        else
561        {
562            /* if client registered data callback, just do what they want */
563            if (p_port->p_data_callback || p_port->p_data_co_callback)
564            {
565                p_port->rx.peer_fc = TRUE;
566                RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
567            }
568            /* Check the size of the rx queue.  If it exceeds certain */
569            /* level and flow control has not been sent to the peer do it now */
570            else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
571                     || (p_port->rx.queue.count > PORT_RX_BUF_HIGH_WM))
572                     && !p_port->rx.peer_fc)
573            {
574                RFCOMM_TRACE_EVENT0 ("PORT_DataInd Data reached HW. Sending FC set.");
575
576                p_port->rx.peer_fc = TRUE;
577                RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
578            }
579        }
580    }
581}
582
583