16ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/****************************************************************************** 26ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 36ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Copyright (C) 1999-2012 Broadcom Corporation 46ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 56ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Licensed under the Apache License, Version 2.0 (the "License"); 66ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * you may not use this file except in compliance with the License. 76ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * You may obtain a copy of the License at: 86ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 96ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * http://www.apache.org/licenses/LICENSE-2.0 106ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Unless required by applicable law or agreed to in writing, software 126ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * distributed under the License is distributed on an "AS IS" BASIS, 136ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * See the License for the specific language governing permissions and 156ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * limitations under the License. 166ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 176ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/ 186ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/****************************************************************************** 206ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 216ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Port Emulation entity utilities 226ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 236ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/ 24e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include <string.h> 25e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 26e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "bt_target.h" 27e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "gki.h" 28e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "rfcdefs.h" 29e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "port_api.h" 30e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "port_int.h" 31e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "rfc_int.h" 32e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2cdefs.h" 33e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "btm_int.h" 34e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "btu.h" 35e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 3666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <cutils/log.h> 37595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define info(fmt, ...) ALOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) 38595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) 39595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) 40595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) 4166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani 42e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 436ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbachstatic const tPORT_STATE default_port_pars = 44e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 45e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_BAUD_RATE_9600, 46e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_8_BITS, 47e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_ONESTOPBIT, 48e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_PARITY_NO, 49e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_ODD_PARITY, 50e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_FC_OFF, 51e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 0, /* No rx_char */ 52e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_XON_DC1, 53e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_XOFF_DC3, 54e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}; 55e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 56e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 57e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 58e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 59e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 60e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_allocate_port 61e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 62e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Look through the Port Control Blocks for a free one. Note 63e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** that one server can open several ports with the same SCN 646ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** if it can support simulteneous requests from different 65e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** clients. 66e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 67e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns Pointer to the PORT or NULL if not found 68e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 69e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 70e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr) 71e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 72e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tPORT *p_port = &rfc_cb.port.port[0]; 73e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 xx, yy; 74e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 75e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++) 76e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 77e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (yy >= MAX_RFC_PORTS) 78e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach yy = 0; 79e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 80e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port = &rfc_cb.port.port[yy]; 81e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_port->in_use) 82e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 83e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (p_port, 0, sizeof (tPORT)); 84e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 85e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->in_use = TRUE; 86e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->inx = yy + 1; 87e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 88e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->dlci = dlci; 89e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN); 90e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 91e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* During the open set default state for the port connection */ 92e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach port_set_defaults (p_port); 93e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 94e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach rfc_cb.rfc.last_port = yy; 9566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani debug("rfc_cb.port.port[%d] allocated, last_port:%d", yy, rfc_cb.rfc.last_port); 96e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (p_port); 97e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 98e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 99e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 100e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If here, no free PORT found */ 101e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 102e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 103e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 104e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 105e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 106e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 107e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_set_defaults 108e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 109e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Set defualt port parameters 110e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 111e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 112e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 113e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid port_set_defaults (tPORT *p_port) 114e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 115e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->ev_mask = 0; 116e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->p_callback = NULL; 117e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->port_ctrl = 0; 118e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->error = 0; 119e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->line_status = 0; 120e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx_flag_ev_pending = FALSE; 121e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->peer_mtu = RFCOMM_DEFAULT_MTU; 122e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 123e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->user_port_pars = default_port_pars; 124e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->peer_port_pars = default_port_pars; 125e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 126e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_tx = 0; 127e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx = 0; 128e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* p_port->credit_rx_max = PORT_CREDIT_RX_MAX; Determined later */ 129e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* p_port->credit_rx_low = PORT_CREDIT_RX_LOW; Determined later */ 130e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 131e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl)); 132e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl)); 133e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&p_port->rx, 0, sizeof (p_port->rx)); 134e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&p_port->tx, 0, sizeof (p_port->tx)); 135e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 136e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 137e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 138e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 139e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_select_mtu 140e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 141e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Select MTU which will best serve connection from our 1426ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** point of view. 143e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** If our device is 1.2 or lower we calculate how many DH5s 144e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** fit into 1 RFCOMM buffer. 145e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 146e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 147e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 148e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid port_select_mtu (tPORT *p_port) 149e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 150e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 packet_size; 151e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 152e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Will select MTU only if application did not setup something */ 153e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->mtu == 0) 154e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 155e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* find packet size which connection supports */ 156e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach packet_size = btm_get_max_packet_size (p_port->bd_addr); 157e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (packet_size == 0) 158e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 159e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* something is very wrong */ 160e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_WARNING0 ("port_select_mtu bad packet size"); 161e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->mtu = RFCOMM_DEFAULT_MTU; 162e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 163e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 164e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 165e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* We try to negotiate MTU that each packet can be split into whole 166e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach number of max packets. For example if link is 1.2 max packet size is 339 bytes. 167e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead. 1686ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 1695, that will be 5 Dh5 packets. Now maximum RFCOMM packet is 169e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691. Minus RFCOMM 6 bytes header overhead 1685 170e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 171e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet 172e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. Minus RFCOMM 6 bytes header overhead 1017 */ 173e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size) 174e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 175e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) - RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD; 176e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG1 ("port_select_mtu selected %d based on connection speed", p_port->mtu); 177e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 178e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 179e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 180e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD; 181e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG1 ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu); 182e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 183e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 184e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 185e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 186e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 187e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG1 ("port_select_mtu application selected %d", p_port->mtu); 188e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 189e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu); 190e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if( p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM ) 191e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM; 192e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu); 193e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if( p_port->credit_rx_low > PORT_RX_BUF_LOW_WM ) 194e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx_low = PORT_RX_BUF_LOW_WM; 195e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu); 196e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if( p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM ) 197e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM; 1986ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach RFCOMM_TRACE_DEBUG3 ("port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d", 199e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical); 200e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 201e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 202e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 203e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 204e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 205e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_release_port 206e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 2076ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** Description Release port infor control block. 208e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 209e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns Pointer to the PORT or NULL if not found 210e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 211e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 212e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid port_release_port (tPORT *p_port) 213e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 214e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach BT_HDR *p_buf; 215e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT32 mask; 216e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tPORT_CALLBACK *p_port_cb; 217e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tPORT_STATE user_port_pars; 218e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 219e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_SCHEDULE_LOCK; 22066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani debug("port_release_port, p_port:%p", p_port); 221e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL) 222e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_buf); 223e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 224e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.queue_size = 0; 225e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 226e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL) 227e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_buf); 228e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 229e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->tx.queue_size = 0; 230e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 231e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach PORT_SCHEDULE_UNLOCK; 232e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 233e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->state = PORT_STATE_CLOSED; 234e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 235e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->rfc.state == RFC_STATE_CLOSED) 236e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 237e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG0 ("rfc_port_closed DONE"); 238e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->rfc.p_mcb) 239e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 240e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0; 241e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 242e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If there are no more ports opened on this MCB release it */ 243e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach rfc_check_mcb_active (p_port->rfc.p_mcb); 244e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 245e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach rfc_port_timer_stop (p_port); 246e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 247e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if( p_port->keep_port_handle ) 248e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 249e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG1 ("port_release_port:Initialize handle:%d", p_port->inx); 250e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* save event mask and callback */ 251e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach mask = p_port->ev_mask; 252e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port_cb = p_port->p_callback; 253e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach user_port_pars = p_port->user_port_pars; 2546ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 255e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach port_set_defaults(p_port); 256e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* restore */ 257e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->ev_mask = mask; 258e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->p_callback = p_port_cb; 259e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->user_port_pars = user_port_pars; 260e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->mtu = p_port->keep_mtu; 261e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 262e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->state = PORT_STATE_OPENING; 263e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rfc.p_mcb = NULL; 264e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if(p_port->is_server) 265e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->dlci &= 0xfe; 266e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 267e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->local_ctrl.modem_signal = p_port->default_signal_state; 268e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN); 269e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 270e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 271e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 272e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_DEBUG1 ("port_release_port:Clean-up handle:%d", p_port->inx); 273e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (p_port, 0, sizeof (tPORT)); 274e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 275e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 276e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 277e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 278e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 279e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 280e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 281e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_find_mcb 282e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 283e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function checks if connection exists to device with 284e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** the BD_ADDR. 285e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 286e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 287e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtRFC_MCB *port_find_mcb (BD_ADDR bd_addr) 288e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 289e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach int i; 290e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 291e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (i = 0; i < MAX_BD_CONNECTIONS; i++) 292e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 293e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE) 294e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN)) 295e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 296e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Multiplexer channel found do not change anything */ 297e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (&rfc_cb.port.rfc_mcb[i]); 298e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 299e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 300e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 301e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 302e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 303e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 304e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 305e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 306e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_find_mcb_dlci_port 307e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 3086ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** Description Find port on the multiplexer channel based on DLCI. If 309e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** this port with DLCI not found try to use even DLCI. This 310e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** is for the case when client is establishing connection on 311e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** none-initiator MCB. 312e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 313e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns Pointer to the PORT or NULL if not found 314e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 315e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 316e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci) 317e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 318e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 inx; 3196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 320e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_mcb) 321e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 322e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 323e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (dlci > RFCOMM_MAX_DLCI) 324e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 325e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 326e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach inx = p_mcb->port_inx[dlci]; 327e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (inx == 0) 328e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 329e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 330e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (&rfc_cb.port.port[inx - 1]); 331e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 332e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 333e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 334e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 335e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 336e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_find_dlci_port 337e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 338e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Find port with DLCI not assigned to multiplexer channel 339e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 340e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns Pointer to the PORT or NULL if not found 341e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 342e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 343e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtPORT *port_find_dlci_port (UINT8 dlci) 344e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 345e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 i; 346e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tPORT *p_port; 347e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 348e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (i = 0; i < MAX_RFC_PORTS; i++) 349e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 350e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port = &rfc_cb.port.port[i]; 351e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->in_use && (p_port->rfc.p_mcb == NULL)) 352e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 353e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->dlci == dlci) 354e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 355e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (p_port); 356e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 357e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1))) 358e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 359e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->dlci++; 360e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (p_port); 361e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 362e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 363e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 364e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 365e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 366e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 367e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 368e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 369e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 370e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_find_port 371e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 372e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Find port with DLCI, BD_ADDR 373e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 374e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns Pointer to the PORT or NULL if not found 375e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 376e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 377e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr) 378e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 379e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 i; 380e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tPORT *p_port; 381e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 382e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (i = 0; i < MAX_RFC_PORTS; i++) 383e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 384e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port = &rfc_cb.port.port[i]; 3856ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach if (p_port->in_use 386e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (p_port->dlci == dlci) 387e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN)) 388e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 389e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (p_port); 390e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 391e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 392e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (NULL); 393e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 394e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 395e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 396e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 397e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 398e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_flow_control_user 399e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 400e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Check the current user flow control and if necessary return 4016ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** events to be send to the user based on the user's specified 402e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** flow control type. 403e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 404e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns event mask to be returned to the application 405e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 406e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 407e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachUINT32 port_flow_control_user (tPORT *p_port) 408e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 409e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT32 event = 0; 410e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 411e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Flow control to the user can be caused by flow controlling by the peer */ 412e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */ 413e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* tx_queue is full */ 4146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach BOOLEAN fc = p_port->tx.peer_fc 415e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach || !p_port->rfc.p_mcb 416e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach || !p_port->rfc.p_mcb->peer_ready 417e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach || (p_port->tx.queue_size > PORT_TX_HIGH_WM) 418e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM); 419e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 420e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->tx.user_fc == fc) 421e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (0); 422e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 423e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->tx.user_fc = fc; 424e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 425e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (fc) 426e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach event = PORT_EV_FC; 427e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 428e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach event = PORT_EV_FC | PORT_EV_FCS; 429e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 430e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (event); 431e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 432e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 433e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 434e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 435e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 436e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_get_signal_changes 437e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 438e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Check modem signals that has been changed 439e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 440e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns event mask to be returned to the application 441e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 442e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 443e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachUINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal) 444e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 445e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 changed_signals = (signal ^ old_signals); 446e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT32 events = 0; 447e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 448e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (changed_signals & PORT_DTRDSR_ON) 449e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 450e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_DSR; 451e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 452e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (signal & PORT_DTRDSR_ON) 453e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_DSRS; 454e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 455e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 456e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (changed_signals & PORT_CTSRTS_ON) 457e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 458e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_CTS; 459e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 460e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (signal & PORT_CTSRTS_ON) 461e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_CTSS; 462e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 463e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 464e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (changed_signals & PORT_RING_ON) 465e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_RING; 466e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 467e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (changed_signals & PORT_DCD_ON) 468e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 469e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_RLSD; 470e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 471e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (signal & PORT_DCD_ON) 472e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach events |= PORT_EV_RLSDS; 473e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 474e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 475e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (p_port->ev_mask & events); 476e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 477e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 478e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 479e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 480e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function port_flow_control_peer 481e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 482e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description Send flow control messages to the peer for both enabling 483e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** and disabling flow control, for both credit-based and 484e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** TS 07.10 flow control mechanisms. 485e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 486e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns nothing 487e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 488e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 489e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count) 490e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 491e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_port->rfc.p_mcb) 492e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 493e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 494e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If using credit based flow control */ 495e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) 496e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 497e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if want to enable flow from peer */ 498e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (enable) 499e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 500e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* update rx credits */ 501e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (count > p_port->credit_rx) 502e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 503e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx = 0; 504e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 505e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 506e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 507e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx -= count; 508e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 509e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 510e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If credit count is less than low credit watermark, and user */ 511e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* did not force flow control, send a credit update */ 512e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* There might be a special case when we just adjusted rx_max */ 5136ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach if ((p_port->credit_rx <= p_port->credit_rx_low) 514e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && !p_port->rx.user_fc 515e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (p_port->credit_rx_max > p_port->credit_rx)) 516e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 517e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci, 518e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach (UINT8) (p_port->credit_rx_max - p_port->credit_rx)); 519e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 520e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->credit_rx = p_port->credit_rx_max; 5216ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 522e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = FALSE; 523e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 524e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 525e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* else want to disable flow from peer */ 526e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 527e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 528e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if client registered data callback, just do what they want */ 52966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani if (p_port->p_data_callback || p_port->p_data_co_callback) 530e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 531e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = TRUE; 532e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 533e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if queue count reached credit rx max, set peer fc */ 534e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (p_port->rx.queue.count >= p_port->credit_rx_max) 535e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 536e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = TRUE; 537e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 538e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 539e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 540e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* else using TS 07.10 flow control */ 5416ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach else 542e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 543e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if want to enable flow from peer */ 544e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (enable) 545e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 546e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If rfcomm suspended traffic from the peer based on the rx_queue_size */ 547e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* check if it can be resumed now */ 5486ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach if (p_port->rx.peer_fc 549e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (p_port->rx.queue_size < PORT_RX_LOW_WM) 550e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (p_port->rx.queue.count < PORT_RX_BUF_LOW_WM)) 551e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 552e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = FALSE; 553e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 554e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If user did not force flow control allow traffic now */ 555e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_port->rx.user_fc) 556e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE); 557e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 558e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 559e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* else want to disable flow from peer */ 560e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 561e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 562e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if client registered data callback, just do what they want */ 56366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani if (p_port->p_data_callback || p_port->p_data_co_callback) 564e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 565e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = TRUE; 566e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE); 567e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 568e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Check the size of the rx queue. If it exceeds certain */ 569e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* level and flow control has not been sent to the peer do it now */ 5706ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM) 571e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach || (p_port->rx.queue.count > PORT_RX_BUF_HIGH_WM)) 572e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && !p_port->rx.peer_fc) 573e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 574e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_TRACE_EVENT0 ("PORT_DataInd Data reached HW. Sending FC set."); 575e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 576e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_port->rx.peer_fc = TRUE; 577e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE); 5786ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach } 579e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 580e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 581e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 582e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 583