15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 1999-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Port Emulation entity utilities
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "gki.h"
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "rfcdefs.h"
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "port_api.h"
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "port_int.h"
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "rfc_int.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2cdefs.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btu.h"
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const tPORT_STATE default_port_pars =
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_BAUD_RATE_9600,
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_8_BITS,
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_ONESTOPBIT,
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_PARITY_NO,
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_ODD_PARITY,
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_FC_OFF,
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0,                      /* No rx_char */
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_XON_DC1,
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_XOFF_DC3,
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_allocate_port
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Look through the Port Control Blocks for a free one.  Note
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  that one server can open several ports with the same SCN
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  if it can support simulteneous requests from different
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  clients.
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          Pointer to the PORT or NULL if not found
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tPORT  *p_port = &rfc_cb.port.port[0];
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8  xx, yy;
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++)
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (yy >= MAX_RFC_PORTS)
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            yy = 0;
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port = &rfc_cb.port.port[yy];
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!p_port->in_use)
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memset (p_port, 0, sizeof (tPORT));
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->in_use = TRUE;
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->inx    = yy + 1;
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->dlci   = dlci;
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* During the open set default state for the port connection */
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            port_set_defaults (p_port);
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            rfc_cb.rfc.last_port = yy;
88689d66b6559dcb3a0ad7f6cc33b6129e50910253The Android Open Source Project            RFCOMM_TRACE_DEBUG2("rfc_cb.port.port[%d] allocated, last_port:%d", yy, rfc_cb.rfc.last_port);
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (p_port);
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If here, no free PORT found */
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (NULL);
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_set_defaults
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Set defualt port parameters
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid port_set_defaults (tPORT *p_port)
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->ev_mask        = 0;
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->p_callback     = NULL;
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->port_ctrl      = 0;
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->error          = 0;
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->line_status    = 0;
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->rx_flag_ev_pending = FALSE;
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->peer_mtu       = RFCOMM_DEFAULT_MTU;
1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->user_port_pars = default_port_pars;
1175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->peer_port_pars = default_port_pars;
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->credit_tx      = 0;
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->credit_rx      = 0;
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*  p_port->credit_rx_max  = PORT_CREDIT_RX_MAX;            Determined later */
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*  p_port->credit_rx_low  = PORT_CREDIT_RX_LOW;            Determined later */
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl));
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl));
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset (&p_port->rx, 0, sizeof (p_port->rx));
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset (&p_port->tx, 0, sizeof (p_port->tx));
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_select_mtu
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Select MTU which will best serve connection from our
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  point of view.
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  If our device is 1.2 or lower we calculate how many DH5s
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  fit into 1 RFCOMM buffer.
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid port_select_mtu (tPORT *p_port)
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16 packet_size;
1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Will select MTU only if application did not setup something */
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_port->mtu == 0)
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* find packet size which connection supports */
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        packet_size = btm_get_max_packet_size (p_port->bd_addr);
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (packet_size == 0)
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* something is very wrong */
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            RFCOMM_TRACE_WARNING0 ("port_select_mtu bad packet size");
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->mtu = RFCOMM_DEFAULT_MTU;
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We try to negotiate MTU that each packet can be split into whole
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            number of max packets.  For example if link is 1.2 max packet size is 339 bytes.
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4 overhead.
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            1695, that will be 5 Dh5 packets.  Now maximum RFCOMM packet is
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.  Minus RFCOMM 6 bytes header overhead 1685
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5 packet
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  Minus RFCOMM 6 bytes header overhead 1017 */
1665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size)
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) - RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                RFCOMM_TRACE_DEBUG1 ("port_select_mtu selected %d based on connection speed", p_port->mtu);
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
1745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                RFCOMM_TRACE_DEBUG1 ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        RFCOMM_TRACE_DEBUG1 ("port_select_mtu application selected %d", p_port->mtu);
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->credit_rx_max  = (PORT_RX_HIGH_WM / p_port->mtu);
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if( p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM )
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->credit_rx_low  = (PORT_RX_LOW_WM / p_port->mtu);
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if( p_port->credit_rx_low > PORT_RX_BUF_LOW_WM )
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if( p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM )
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    RFCOMM_TRACE_DEBUG3 ("port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d",
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                          p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_release_port
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Release port infor control block.
2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          Pointer to the PORT or NULL if not found
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid port_release_port (tPORT *p_port)
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR *p_buf;
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32 mask;
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tPORT_CALLBACK *p_port_cb;
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tPORT_STATE user_port_pars;
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_SCHEDULE_LOCK;
213689d66b6559dcb3a0ad7f6cc33b6129e50910253The Android Open Source Project    RFCOMM_TRACE_DEBUG1("port_release_port, p_port:%p", p_port);
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL)
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->rx.queue_size = 0;
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL)
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->tx.queue_size = 0;
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    PORT_SCHEDULE_UNLOCK;
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->state = PORT_STATE_CLOSED;
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_port->rfc.state == RFC_STATE_CLOSED)
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        RFCOMM_TRACE_DEBUG0 ("rfc_port_closed DONE");
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_port->rfc.p_mcb)
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If there are no more ports opened on this MCB release it */
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            rfc_check_mcb_active (p_port->rfc.p_mcb);
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        rfc_port_timer_stop (p_port);
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if( p_port->keep_port_handle )
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            RFCOMM_TRACE_DEBUG1 ("port_release_port:Initialize handle:%d", p_port->inx);
2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* save event mask and callback */
2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            mask = p_port->ev_mask;
2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port_cb = p_port->p_callback;
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            user_port_pars = p_port->user_port_pars;
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            port_set_defaults(p_port);
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* restore */
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->ev_mask         = mask;
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->p_callback      = p_port_cb;
2525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->user_port_pars  = user_port_pars;
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->mtu             = p_port->keep_mtu;
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->state           = PORT_STATE_OPENING;
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->rfc.p_mcb       = NULL;
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if(p_port->is_server)
2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->dlci       &= 0xfe;
2595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_port->local_ctrl.modem_signal = p_port->default_signal_state;
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
2645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            RFCOMM_TRACE_DEBUG1 ("port_release_port:Clean-up handle:%d", p_port->inx);
2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memset (p_port, 0, sizeof (tPORT));
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_find_mcb
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function checks if connection exists to device with
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  the BD_ADDR.
2785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttRFC_MCB *port_find_mcb (BD_ADDR bd_addr)
2815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int      i;
2835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    for (i = 0; i < MAX_BD_CONNECTIONS; i++)
2855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
2875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Multiplexer channel found do not change anything */
2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (&rfc_cb.port.rfc_mcb[i]);
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (NULL);
2945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_find_mcb_dlci_port
3005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Find port on the multiplexer channel based on DLCI.  If
3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  this port with DLCI not found try to use even DLCI.  This
3035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  is for the case when client is establishing connection on
3045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  none-initiator MCB.
3055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          Pointer to the PORT or NULL if not found
3075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8 inx;
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_mcb)
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (NULL);
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (dlci > RFCOMM_MAX_DLCI)
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (NULL);
3185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    inx = p_mcb->port_inx[dlci];
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (inx == 0)
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (NULL);
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (&rfc_cb.port.port[inx - 1]);
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_find_dlci_port
3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Find port with DLCI not assigned to multiplexer channel
3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          Pointer to the PORT or NULL if not found
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttPORT *port_find_dlci_port (UINT8 dlci)
3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16 i;
3395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tPORT  *p_port;
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    for (i = 0; i < MAX_RFC_PORTS; i++)
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port = &rfc_cb.port.port[i];
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_port->dlci == dlci)
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (p_port);
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->dlci++;
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (p_port);
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (NULL);
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_find_port
3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Find port with DLCI, BD_ADDR
3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          Pointer to the PORT or NULL if not found
3685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16 i;
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tPORT  *p_port;
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    for (i = 0; i < MAX_RFC_PORTS; i++)
3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_port = &rfc_cb.port.port[i];
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_port->in_use
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         && (p_port->dlci == dlci)
3805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (p_port);
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (NULL);
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_flow_control_user
3925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Check the current user flow control and if necessary return
3945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  events to be send to the user based on the user's specified
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  flow control type.
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          event mask to be returned to the application
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT32 port_flow_control_user (tPORT *p_port)
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32 event = 0;
4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Flow control to the user can be caused by flow controlling by the peer */
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* tx_queue is full */
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN fc = p_port->tx.peer_fc
4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project              || !p_port->rfc.p_mcb
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project              || !p_port->rfc.p_mcb->peer_ready
4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project              || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project              || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM);
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_port->tx.user_fc == fc)
4145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (0);
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_port->tx.user_fc = fc;
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (fc)
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        event = PORT_EV_FC;
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        event = PORT_EV_FC | PORT_EV_FCS;
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (event);
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_get_signal_changes
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Check modem signals that has been changed
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          event mask to be returned to the application
4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8  changed_signals = (signal ^ old_signals);
4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32 events = 0;
4405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (changed_signals & PORT_DTRDSR_ON)
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        events |= PORT_EV_DSR;
4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (signal & PORT_DTRDSR_ON)
4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            events |= PORT_EV_DSRS;
4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (changed_signals & PORT_CTSRTS_ON)
4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        events |= PORT_EV_CTS;
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (signal & PORT_CTSRTS_ON)
4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            events |= PORT_EV_CTSS;
4555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (changed_signals & PORT_RING_ON)
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        events |= PORT_EV_RING;
4595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (changed_signals & PORT_DCD_ON)
4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        events |= PORT_EV_RLSD;
4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (signal & PORT_DCD_ON)
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            events |= PORT_EV_RLSDS;
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (p_port->ev_mask & events);
4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         port_flow_control_peer
4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Send flow control messages to the peer for both enabling
4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  and disabling flow control, for both credit-based and
4775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  TS 07.10 flow control mechanisms.
4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          nothing
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_port->rfc.p_mcb)
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If using credit based flow control */
4885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* if want to enable flow from peer */
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (enable)
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* update rx credits */
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (count > p_port->credit_rx)
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
4965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->credit_rx = 0;
4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
4995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->credit_rx -= count;
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If credit count is less than low credit watermark, and user */
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* did not force flow control, send a credit update */
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* There might be a special case when we just adjusted rx_max */
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((p_port->credit_rx <= p_port->credit_rx_low)
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             && !p_port->rx.user_fc
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             && (p_port->credit_rx_max > p_port->credit_rx))
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->credit_rx = p_port->credit_rx_max;
5145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = FALSE;
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* else want to disable flow from peer */
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* if client registered data callback, just do what they want */
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_port->p_data_callback || p_port->p_data_co_callback)
5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = TRUE;
5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* if queue count reached credit rx max, set peer fc */
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (p_port->rx.queue.count >= p_port->credit_rx_max)
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = TRUE;
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* else using TS 07.10 flow control */
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
5355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* if want to enable flow from peer */
5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (enable)
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* check if it can be resumed now */
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_port->rx.peer_fc
5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             && (p_port->rx.queue_size < PORT_RX_LOW_WM)
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             && (p_port->rx.queue.count < PORT_RX_BUF_LOW_WM))
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = FALSE;
5465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* If user did not force flow control allow traffic now */
5485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (!p_port->rx.user_fc)
5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
5505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* else want to disable flow from peer */
5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
5545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* if client registered data callback, just do what they want */
5565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_port->p_data_callback || p_port->p_data_co_callback)
5575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = TRUE;
5595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Check the size of the rx queue.  If it exceeds certain */
5625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* level and flow control has not been sent to the peer do it now */
5635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
5645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     || (p_port->rx.queue.count > PORT_RX_BUF_HIGH_WM))
5655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     && !p_port->rx.peer_fc)
5665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
5675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                RFCOMM_TRACE_EVENT0 ("PORT_DataInd Data reached HW. Sending FC set.");
5685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_port->rx.peer_fc = TRUE;
5705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
5715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
5725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
576