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 *  this file contains the Serial Port API code
226ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
236ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/
24e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
25e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include <string.h>
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 "btm_int.h"
32e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "btm_api.h"
33e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "rfc_int.h"
34e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2c_api.h"
35e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "sdp_api.h"
36e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
37e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* duration of break in 200ms units */
38e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#define PORT_BREAK_DURATION     1
39e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
4066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani#include <cutils/log.h>
41595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define info(fmt, ...)  ALOGI ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
42595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
43595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
44595bced8e7c280e37a75b9bf9c1f36263434041cMatthew Xie#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
4566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
46e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
47e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
48e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         RFCOMM_CreateConnection
49e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
5066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      RFCOMM_CreateConnection function is used from the application
5166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  to establish serial port connection to the peer device,
5266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  or allow RFCOMM to accept a connection from the peer
5366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  application.
54e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
5566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      scn          - Service Channel Number as registered with
5666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                                 the SDP (server) or obtained using SDP from
57e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                                 the peer device (client).
58e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  is_server    - TRUE if requesting application is a server
59e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  mtu          - Maximum frame size the application can accept
60e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  bd_addr      - BD_ADDR of the peer (client)
6166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  mask         - specifies events to be enabled.  A value
62e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                                 of zero disables all events.
63e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_handle     - OUT pointer to the handle.
64e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_mgmt_cb    - pointer to callback function to receive
65e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                                 connection up/down events.
66e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Notes:
67e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
68e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Server can call this function with the same scn parameter multiple times if
69e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** it is ready to accept multiple simulteneous connections.
70e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
71e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** DLCI for the connection is (scn * 2 + 1) if client originates connection on
72e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** existing none initiator multiplexer channel.  Otherwise it is (scn * 2).
73e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** For the server DLCI can be changed later if client will be calling it using
74e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** (scn * 2 + 1) dlci.
75e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
76e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
7766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server,
7866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                             UINT16 mtu, BD_ADDR bd_addr, UINT16 *p_handle,
79e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                             tPORT_CALLBACK *p_mgmt_cb)
80e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
81e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
82e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    int        i;
83e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8      dlci;
84e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tRFC_MCB   *p_mcb = port_find_mcb (bd_addr);
85e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16     rfcomm_mtu;
86e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
8766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    RFCOMM_TRACE_API3 ("RFCOMM_CreateConnection() called SCN: %d is_server:%d mtu:%d",
88e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                       scn, is_server, mtu);
89e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API6 ("RFCOMM_CreateConnection()  BDA: %02x-%02x-%02x-%02x-%02x-%02x",
90e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                       bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
91e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
92e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_handle = 0;
93e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
94e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (( scn == 0 )||(scn >= PORT_MAX_RFC_PORTS ))
95e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
96e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* Server Channel Number(SCN) should be in range 1...30 */
97e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_ERROR0 ("RFCOMM_CreateConnection - invalid SCN");
98e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_INVALID_SCN);
99e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
100e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
101e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* For client that originate connection on the existing none initiator */
102e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* multiplexer channel DLCI should be odd */
103e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_mcb && !p_mcb->is_initiator && !is_server)
104e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        dlci = (scn << 1) + 1;
105e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
106e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        dlci = (scn << 1);
107e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
108e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* For the server side always allocate a new port.  On the client side */
109e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* do not allow the same (dlci, bd_addr) to be opened twice by application */
110e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!is_server && ((p_port = port_find_port (dlci, bd_addr)) != NULL))
111e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
112e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* if existing port is also a client port */
113e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_port->is_server == FALSE)
114e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
11566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            RFCOMM_TRACE_ERROR3 ("RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, MCB state:%d",
116e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_port->state, p_port->rfc.state, p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0);
117e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            return (PORT_ALREADY_OPENED);
118e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
119e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
120e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
121e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_port = port_allocate_port (dlci, bd_addr)) == NULL)
122e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
123e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_WARNING0 ("RFCOMM_CreateConnection - no resources");
124e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NO_RESOURCES);
125e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
126e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
127e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->default_signal_state = (PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
128e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
129e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    switch (uuid)
130e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
131e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case UUID_PROTOCOL_OBEX:
132e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->default_signal_state = PORT_OBEX_DEFAULT_SIGNAL_STATE;
133e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
134e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case UUID_SERVCLASS_SERIAL_PORT:
135e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->default_signal_state = PORT_SPP_DEFAULT_SIGNAL_STATE;
136e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
137e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case UUID_SERVCLASS_LAN_ACCESS_USING_PPP:
138e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->default_signal_state = PORT_PPP_DEFAULT_SIGNAL_STATE;
139e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
140e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case UUID_SERVCLASS_DIALUP_NETWORKING:
141e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case UUID_SERVCLASS_FAX:
142e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->default_signal_state = PORT_DUN_DEFAULT_SIGNAL_STATE;
143e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
144e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
145e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
146e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_EVENT2 ("RFCOMM_CreateConnection dlci:%d signal state:0x%x", dlci, p_port->default_signal_state);
147e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
148e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_handle = p_port->inx;
149e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
150e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->state        = PORT_STATE_OPENING;
151e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->uuid         = uuid;
152e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->is_server    = is_server;
153e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->scn          = scn;
154e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->ev_mask      = 0;
155e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
156e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* If the MTU is not specified (0), keep MTU decision until the
157e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     * PN frame has to be send
158e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     * at that time connection should be established and we
159e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     * will know for sure our prefered MTU
160e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     */
161e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
162e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
163e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
164e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (mtu)
165e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->mtu      = (mtu < rfcomm_mtu) ? mtu : rfcomm_mtu;
166e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
167e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->mtu      = rfcomm_mtu;
168e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
169e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* server doesn't need to release port when closing */
170e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if( is_server )
171e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
172e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->keep_port_handle = TRUE;
173e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
174e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* keep mtu that user asked, p_port->mtu could be updated during param negotiation */
17566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_port->keep_mtu         = p_port->mtu;
176e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
177e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
178e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->local_ctrl.modem_signal = p_port->default_signal_state;
179e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->local_ctrl.fc           = FALSE;
180e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
181e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->p_mgmt_callback = p_mgmt_cb;
182e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
183e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    for (i = 0; i < BD_ADDR_LEN; i++)
184e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->bd_addr[i] = bd_addr[i];
185e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
186e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* If this is not initiator of the connection need to just wait */
187e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->is_server)
188e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
189e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
190e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
191e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
192e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Open will be continued after security checks are passed */
193e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return port_open_continue (p_port);
194e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
195e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
196e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
197e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
198e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
199e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         RFCOMM_RemoveConnection
200e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
201e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is called to close the specified connection.
202e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
20366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
204e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
205e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
206e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint RFCOMM_RemoveConnection (UINT16 handle)
207e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
208e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
209e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
210e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("RFCOMM_RemoveConnection() handle:%d", handle);
211e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
212e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
213e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
214e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
215e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_ERROR1 ("RFCOMM_RemoveConnection() BAD handle:%d", handle);
216e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
217e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
218e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
219e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
220e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
221e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
222e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT1 ("RFCOMM_RemoveConnection() Not opened:%d", handle);
223e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
224e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
225e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
226e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->state = PORT_STATE_CLOSING;
227e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
228e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    port_start_close (p_port);
229e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
230e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
231e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
232e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
233e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
234e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
235e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         RFCOMM_RemoveServer
236e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
237e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is called to close the server port.
238e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
23966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
240e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
241e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
242e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint RFCOMM_RemoveServer (UINT16 handle)
243e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
244e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
245e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
246e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("RFCOMM_RemoveServer() handle:%d", handle);
247e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
248e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
249e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
250e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
251e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_ERROR1 ("RFCOMM_RemoveServer() BAD handle:%d", handle);
252e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
253e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
254e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
255e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
256e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Do not report any events to the client any more. */
257e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->p_mgmt_callback = NULL;
25866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
259e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
260e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
261e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT1 ("RFCOMM_RemoveServer() Not opened:%d", handle);
262e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
263e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
264e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
265e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* this port will be deallocated after closing */
266e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->keep_port_handle = FALSE;
267e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->state = PORT_STATE_CLOSING;
268e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
269e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    port_start_close (p_port);
270e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
271e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
272e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
273e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
274e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
275e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
276e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SetEventCallback
277e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
27866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function is called to provide an address of the
279e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  function which will be called when one of the events
280e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  specified in the mask occures.
281e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
28266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
28366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_callback - address of the callback function which should
28466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                               be called from the RFCOMM when an event
285e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               specified in the mask occures.
286e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
287e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
288e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
289e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_SetEventCallback (UINT16 port_handle, tPORT_CALLBACK *p_port_cb)
290e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
291e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
292e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
293e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
294e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS))
295e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
296e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
297e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
298e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
299e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[port_handle - 1];
300e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
301e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
302e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
303e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
304e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
305e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
306e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_SetEventCallback() handle:%d", port_handle);
307e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
308e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->p_callback = p_port_cb;
309e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
310e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
311e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
312e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
313e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
314e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
315e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
316e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SetDataCallback
317e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
318e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is when a data packet is received
319e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
32066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
32166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_callback - address of the callback function which should
32266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                               be called from the RFCOMM when data packet
323e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               is received.
324e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
325e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
326e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
327e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_SetDataCallback (UINT16 port_handle, tPORT_DATA_CALLBACK *p_port_cb)
328e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
329e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
330e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
331e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_SetDataCallback() handle:%d cb 0x%x", port_handle, p_port_cb);
332e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
333e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
334e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS))
335e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
336e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
337e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
338e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
339e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[port_handle - 1];
340e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
341e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
342e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
343e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
344e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
345e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
346e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->p_data_callback = p_port_cb;
347e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
348e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
349e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
35066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani/*******************************************************************************
35166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
35266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Function         PORT_SetCODataCallback
35366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
35466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function is when a data packet is received
35566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
35666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
35766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_callback - address of the callback function which should
35866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                               be called from the RFCOMM when data packet
35966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                               is received.
36066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
36166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
36266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani*******************************************************************************/
36366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint PORT_SetDataCOCallback (UINT16 port_handle, tPORT_DATA_CO_CALLBACK *p_port_cb)
36466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
36566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    tPORT  *p_port;
36666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
36766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    RFCOMM_TRACE_API2 ("PORT_SetDataCOCallback() handle:%d cb 0x%x", port_handle, p_port_cb);
36866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
36966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* Check if handle is valid to avoid crashing */
37066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS))
37166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
37266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_BAD_HANDLE);
37366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
37466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
37566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    p_port = &rfc_cb.port.port[port_handle - 1];
37666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
37766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
37866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
37966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_NOT_OPENED);
38066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
38166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
38266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    p_port->p_data_co_callback = p_port_cb;
38366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
38466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return (PORT_SUCCESS);
38566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
38666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
387e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
388e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
389e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
390e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
391e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SetEventMask
392e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
393e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is called to close the specified connection.
394e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
39566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
396e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  mask   - Bitmask of the events the host is interested in
397e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
398e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
399e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_SetEventMask (UINT16 port_handle, UINT32 mask)
400e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
401e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
402e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
403e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_SetEventMask() handle:%d mask:0x%x", port_handle, mask);
404e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
405e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
406e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS))
407e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
408e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
409e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
410e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
411e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[port_handle - 1];
412e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
413e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
414e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
415e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
416e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
417e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
418e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->ev_mask = mask;
419e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
420e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
421e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
422e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
423e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
424e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
425e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
426e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_CheckConnection
427e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
428e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function returns PORT_SUCCESS if connection referenced
429e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  by handle is up and running
430e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
43166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
432e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  bd_addr    - OUT bd_addr of the peer
433e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_lcid     - OUT L2CAP's LCID
434e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
435e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
436e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_CheckConnection (UINT16 handle, BD_ADDR bd_addr, UINT16 *p_lcid)
437e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
438e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
439e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
440e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_CheckConnection() handle:%d", handle);
441e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
442e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
443e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
444e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
445e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
446e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
447e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
448e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
449e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
450e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
451e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
452e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
453e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
454e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
45566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (!p_port->rfc.p_mcb
45666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     || !p_port->rfc.p_mcb->peer_ready
457e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     || (p_port->rfc.state != RFC_STATE_OPENED))
458e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
459e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
460e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
461e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
462e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    memcpy (bd_addr, p_port->rfc.p_mcb->bd_addr, BD_ADDR_LEN);
463e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_lcid)
464e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        *p_lcid = p_port->rfc.p_mcb->lcid;
465e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
466e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
467e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
468e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
469e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
470e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
471e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_IsOpening
472e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
473e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function returns TRUE if there is any RFCOMM connection
474e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  opening in process.
475e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
476e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Parameters:      TRUE if any connection opening is found
477e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  bd_addr    - bd_addr of the peer
478e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
479e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
480e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBOOLEAN PORT_IsOpening (BD_ADDR bd_addr)
481e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
482e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8   xx, yy;
483e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tRFC_MCB *p_mcb = NULL;
484e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
485e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BOOLEAN found_port;
486e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
487e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check for any rfc_mcb which is in the middle of opening. */
488e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    for (xx = 0; xx < MAX_BD_CONNECTIONS; xx++)
489e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
490e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if ((rfc_cb.port.rfc_mcb[xx].state > RFC_MX_STATE_IDLE) &&
491e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            (rfc_cb.port.rfc_mcb[xx].state < RFC_MX_STATE_CONNECTED))
492e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
493e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            memcpy (bd_addr, rfc_cb.port.rfc_mcb[xx].bd_addr, BD_ADDR_LEN);
494e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            return TRUE;
495e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
496e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
497e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (rfc_cb.port.rfc_mcb[xx].state == RFC_MX_STATE_CONNECTED)
498e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
499e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            found_port = FALSE;
500e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_mcb = &rfc_cb.port.rfc_mcb[xx];
501e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_port = &rfc_cb.port.port[0];
502e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
503e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            for (yy = 0; yy < MAX_RFC_PORTS; yy++, p_port++)
504e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
505e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                if (p_port->rfc.p_mcb == p_mcb)
506e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                {
507e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                    found_port = TRUE;
508e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                    break;
509e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                }
510e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
511e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
51266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            if ((!found_port) ||
513e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                (found_port && (p_port->rfc.state < RFC_STATE_OPENED)))
514e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
515e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                /* Port is not established yet. */
516e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                memcpy (bd_addr, rfc_cb.port.rfc_mcb[xx].bd_addr, BD_ADDR_LEN);
517e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                return TRUE;
518e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
519e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
520e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
521e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
522e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return FALSE;
523e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
524e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
525e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
526e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
527e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SetState
528e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
52966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function configures connection according to the
530e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  specifications in the tPORT_STATE structure.
531e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
53266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
53366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_settings - Pointer to a tPORT_STATE structure containing
534e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               configuration information for the connection.
535e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
536e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
537e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
538e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_SetState (UINT16 handle, tPORT_STATE *p_settings)
539e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
540e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
541e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       baud_rate;
542e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
543e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_SetState() handle:%d", handle);
544e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
545e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
546e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
547e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
548e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
549e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
550e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
551e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
552e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
553e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
554e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
555e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
556e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
557e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
558e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
559e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
560e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
561e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
562e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
563e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_SetState() handle:%d FC_TYPE:0x%x", handle,
564e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                       p_settings->fc_type);
565e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
566e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    baud_rate = p_port->user_port_pars.baud_rate;
567e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->user_port_pars = *p_settings;
568e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
569e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* for now we've been asked to pass only baud rate */
570e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (baud_rate != p_settings->baud_rate)
571e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
572e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        port_start_par_neg (p_port);
573e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
574e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
575e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
576e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
577e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
578e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
579e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_GetRxQueueCnt
580e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
581e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function return number of buffers on the rx queue.
582e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
58366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
584e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_rx_queue_count - Pointer to return queue count in.
585e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
586e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
587e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_GetRxQueueCnt (UINT16 handle, UINT16 *p_rx_queue_count)
588e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
589e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
590e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
591e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_GetRxQueueCnt() handle:%d", handle);
592e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
593e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
594e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
595e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
596e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
597e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
598e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
599e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
600e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
601e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
602e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
603e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
604e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
605e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
606e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
607e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
608e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
609e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
610e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
611e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_rx_queue_count = p_port->rx.queue_size;
612e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
613e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach	RFCOMM_TRACE_API2 ("PORT_GetRxQueueCnt() p_rx_queue_count:%d, p_port->rx.queue.count = %d",
614e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach		                                     *p_rx_queue_count, p_port->rx.queue_size);
615e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
616e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
617e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
618e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
619e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
620e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
621e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_GetState
622e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
623e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is called to fill tPORT_STATE structure
624e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  with the curremt control settings for the port
625e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
62666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
627e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_settings - Pointer to a tPORT_STATE structure in which
628e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               configuration information is returned.
629e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
630e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
631e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_GetState (UINT16 handle, tPORT_STATE *p_settings)
632e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
633e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
634e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
635e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_GetState() handle:%d", handle);
636e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
637e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
638e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
639e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
640e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
641e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
642e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
643e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
644e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
645e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
646e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
647e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
648e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
649e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
650e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
651e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
652e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
653e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
654e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
655e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_settings = p_port->user_port_pars;
656e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
657e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
658e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
659e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
660e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
661e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
662e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_Control
663e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
66466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function directs a specified connection to pass control
665e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  control information to the peer device.
666e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
66766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
668e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  signal     = specify the function to be passed
669e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
670e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
671e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_Control (UINT16 handle, UINT8 signal)
672e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
673e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
674e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8      old_modem_signal;
675e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
676e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_Control() handle:%d signal:0x%x", handle, signal);
677e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
678e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
679e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
680e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
681e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
682e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
683e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
684e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
685e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
686e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
687e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
688e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
689e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
690e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
691e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    old_modem_signal = p_port->local_ctrl.modem_signal;
692e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->local_ctrl.break_signal = 0;
693e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
694e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    switch (signal)
695e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
696e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_SET_CTSRTS:
697e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal |= PORT_CTSRTS_ON;
698e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
699e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
700e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_CLR_CTSRTS:
701e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal &= ~PORT_CTSRTS_ON;
702e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
703e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
704e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_SET_DTRDSR:
705e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal |= PORT_DTRDSR_ON;
706e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
707e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
708e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_CLR_DTRDSR:
709e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal &= ~PORT_DTRDSR_ON;
710e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
711e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
712e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_SET_RI:
713e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal |= PORT_RING_ON;
714e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
715e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
716e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_CLR_RI:
717e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal &= ~PORT_RING_ON;
718e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
719e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
720e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_SET_DCD:
721e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal |= PORT_DCD_ON;
722e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
723e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
724e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_CLR_DCD:
725e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.modem_signal &= ~PORT_DCD_ON;
726e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
727e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
728e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
729e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (signal == PORT_BREAK)
730e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.break_signal = PORT_BREAK_DURATION;
731e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else if (p_port->local_ctrl.modem_signal == old_modem_signal)
732e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
733e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
734e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    port_start_control (p_port);
735e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
736e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_EVENT4 ("PORT_Control DTR_DSR : %d, RTS_CTS : %d, RI : %d, DCD : %d",
737e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0),
738e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0),
739e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0),
740e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0));
741e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
742e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
743e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
744e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
745e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
746e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
747e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
748e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_FlowControl
749e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
75066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function directs a specified connection to pass
75166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  flow control message to the peer device.  Enable flag passed
752e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  shows if port can accept more data.
753e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
75466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
755e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  enable     - enables data flow
756e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
757e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
758e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_FlowControl (UINT16 handle, BOOLEAN enable)
759e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
760e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
761e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BOOLEAN    old_fc;
762e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT32     events;
763e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
764e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_FlowControl() handle:%d enable: %d", handle, enable);
765e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
766e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
767e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
768e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
769e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
770e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
771e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
772e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
773e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
774e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
775e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
776e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
777e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
778e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
779e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->rfc.p_mcb)
780e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
781e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
782e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
783e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
784e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->rx.user_fc = !enable;
785e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
786e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
787e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
788e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (!p_port->rx.user_fc)
789e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
790e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            port_flow_control_peer(p_port, TRUE, 0);
791e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
792e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
793e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
794e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
795e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        old_fc = p_port->local_ctrl.fc;
796e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
797e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* FC is set if user is set or peer is set */
798e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
799e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
800e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_port->local_ctrl.fc != old_fc)
801e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            port_start_control (p_port);
802e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
803e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
804e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Need to take care of the case when we could not deliver events */
805e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* to the application because we were flow controlled */
806e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (enable && (p_port->rx.queue_size != 0))
807e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
808e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        events = PORT_EV_RXCHAR;
809e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_port->rx_flag_ev_pending)
810e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
811e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_port->rx_flag_ev_pending = FALSE;
812e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            events |= PORT_EV_RXFLAG;
813e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
814e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
815e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        events &= p_port->ev_mask;
816e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_port->p_callback && events)
817e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
818e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_port->p_callback (events, p_port->inx);
819e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
820e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
821e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
822e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
823e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
824e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
825e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
826e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
827e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_GetModemStatus
828e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
82966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function retrieves modem control signals.  Normally
83066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  application will call this function after a callback
83166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  function is called with notification that one of signals
832e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  has been changed.
833e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
83466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
835e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_signal   - specify the pointer to control signals info
836e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
837e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
838e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_GetModemStatus (UINT16 handle, UINT8 *p_signal)
839e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
840e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
841e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
842e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
843e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
844e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
845e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
846e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
847e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
848e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
849e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
850e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
851e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
852e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
853e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
854e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_signal = p_port->peer_ctrl.modem_signal;
855e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
856e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_GetModemStatus() handle:%d signal:%x", handle, *p_signal);
85766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
858e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
859e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
860e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
861e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
862e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
863e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
864e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_ClearError
865e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
866e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function retreives information about a communications
86766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  error and reports current status of a connection.  The
868e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  function should be called when an error occures to clear
869e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  the connection error flag and to enable additional read
870e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  and write operations.
871e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
87266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
873e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_errors   - pointer of the variable to receive error codes
87466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_status   - pointer to the tPORT_STATUS structur to receive
875e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               connection status
876e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
877e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
878e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_ClearError (UINT16 handle, UINT16 *p_errors, tPORT_STATUS *p_status)
879e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
880e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
881e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
882e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_ClearError() handle:%d", handle);
883e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
884e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
885e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
886e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
887e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
888e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
889e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
890e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
891e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
892e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
893e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
894e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
895e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
896e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_errors = p_port->line_status;
897e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
898e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* This is the only call to clear error status.  We can not clear */
899e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* connection failed status.  To clean it port should be closed and reopened */
900e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port->line_status = (p_port->line_status & LINE_STATUS_FAILED);
901e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
902e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    PORT_GetQueueStatus (handle, p_status);
903e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
904e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
905e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
906e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
907e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
908e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
909e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SendError
910e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
911e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function send a communications error to the peer device
912e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
91366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
914e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  errors     - receive error codes
915e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
916e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
917e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_SendError (UINT16 handle, UINT8 errors)
918e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
919e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
920e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
921e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_SendError() handle:%d errors:0x%x", handle, errors);
922e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
923e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
924e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
925e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
926e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
927e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
928e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
929e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
930e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
931e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
932e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
933e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
934e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
935e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->rfc.p_mcb)
936e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
937e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
938e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
939e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
940e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_LineStatusReq (p_port->rfc.p_mcb, p_port->dlci, errors);
941e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
942e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
943e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
944e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
945e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
946e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
947e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_GetQueueStatus
948e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
94966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function reports current status of a connection.
950e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
95166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
95266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_status   - pointer to the tPORT_STATUS structur to receive
953e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                               connection status
954e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
955e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
956e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_GetQueueStatus (UINT16 handle, tPORT_STATUS *p_status)
957e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
958e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
959e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
960e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* RFCOMM_TRACE_API1 ("PORT_GetQueueStatus() handle:%d", handle); */
961e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
962e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
963e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
964e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
965e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
966e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
967e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
968e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
969e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
970e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
971e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
972e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
973e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
974e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_status->in_queue_size  = (UINT16) p_port->rx.queue_size;
975e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_status->out_queue_size = (UINT16) p_port->tx.queue_size;
976e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
977e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_status->mtu_size = (UINT16) p_port->peer_mtu;
978e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
979e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_status->flags = 0;
980e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
981e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!(p_port->peer_ctrl.modem_signal & PORT_CTSRTS_ON))
982e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_status->flags |= PORT_FLAG_CTS_HOLD;
983e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
984e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!(p_port->peer_ctrl.modem_signal & PORT_DTRDSR_ON))
985e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_status->flags |= PORT_FLAG_DSR_HOLD;
986e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
987e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!(p_port->peer_ctrl.modem_signal & PORT_DCD_ON))
988e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_status->flags |= PORT_FLAG_RLSD_HOLD;
989e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
990e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
991e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
992e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
993e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
994e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
995e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
996e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_Purge
997e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
99866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function discards all the data from the output or
999e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  input queues of the specified connection.
1000e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
100166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
100266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  purge_flags - specify the action to take.
1003e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1004e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1005e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_Purge (UINT16 handle, UINT8 purge_flags)
1006e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1007e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
1008e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR     *p_buf;
1009e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16      count;
101066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    UINT32     events;
1011e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1012e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_Purge() handle:%d flags:0x%x", handle, purge_flags);
1013e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1014e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
1015e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1016e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1017e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1018e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1019e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1020e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1021e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1022e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1023e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1024e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1025e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1026e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1027e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (purge_flags & PORT_PURGE_RXCLEAR)
1028e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1029e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_LOCK;  /* to prevent missing credit */
1030e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1031e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        count = p_port->rx.queue.count;
1032e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1033e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL)
1034e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            GKI_freebuf (p_buf);
1035e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1036e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->rx.queue_size = 0;
1037e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1038e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_UNLOCK;
1039e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1040e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* If we flowed controlled peer based on rx_queue size enable data again */
1041e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (count)
1042e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            port_flow_control_peer (p_port, TRUE, count);
1043e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1044e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1045e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (purge_flags & PORT_PURGE_TXCLEAR)
1046e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1047e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_LOCK;  /* to prevent tx.queue_size from being negative */
1048e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1049e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL)
1050e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            GKI_freebuf (p_buf);
1051e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1052e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->tx.queue_size = 0;
105366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1054e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_UNLOCK;
1055e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1056e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        events = PORT_EV_TXEMPTY;
1057e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1058e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        events |= port_flow_control_user (p_port);
1059e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1060e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        events &= p_port->ev_mask;
1061e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1062e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if ((p_port->p_callback != NULL) && events)
1063e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            (p_port->p_callback)(events, p_port->inx);
1064e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1065e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1066e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
1067e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1068e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1069e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1070e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1071e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1072e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_ReadData
1073e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
107466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      Normally not GKI aware application will call this function
1075e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  after receiving PORT_EV_RXCHAR event.
1076e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
107766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
1078e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_data      - Data area
1079e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  max_len     - Byte count requested
1080e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_len       - Byte count received
1081e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1082e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1083e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_ReadData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len)
1084e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1085e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
1086e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR     *p_buf;
1087e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16      count;
1088e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1089e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API2 ("PORT_ReadData() handle:%d max_len:%d", handle, max_len);
1090e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1091e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Initialize this in case of an error */
1092e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_len = 0;
1093e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1094e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
1095e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1096e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1097e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1098e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1099e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1100e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1101e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1102e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1103e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1104e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1105e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1106e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1107e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
1108e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1109e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
1110e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1111e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1112e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_buf = (BT_HDR *)GKI_getfirst (&p_port->rx.queue);
1113e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_buf)
1114e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
1115e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1116e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    count = 0;
1117e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1118e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    while (max_len && p_buf)
1119e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1120e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_buf->len > max_len)
1121e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
1122e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, max_len);
1123e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->offset += max_len;
1124e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len    -= max_len;
1125e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1126e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            *p_len += max_len;
1127e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1128e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            PORT_SCHEDULE_LOCK;
1129e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1130e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_port->rx.queue_size -= max_len;
1131e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1132e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            PORT_SCHEDULE_UNLOCK;
1133e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1134e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
1135e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
1136e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        else
1137e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
1138e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
1139e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1140e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            *p_len  += p_buf->len;
1141e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            max_len -= p_buf->len;
1142e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1143e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            PORT_SCHEDULE_LOCK;
1144e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1145e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_port->rx.queue_size -= p_buf->len;
1146e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1147e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (max_len)
1148e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
1149e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_data  += p_buf->len;
1150e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_buf = (BT_HDR *)GKI_getnext (p_buf);
1151e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
1152e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1153e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            GKI_freebuf (GKI_dequeue (&p_port->rx.queue));
1154e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1155e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            PORT_SCHEDULE_UNLOCK;
1156e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1157e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            count++;
1158e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
1159e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1160e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1161e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (*p_len == 1)
1162e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1163e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT3 ("PORT_ReadData queue:%d returned:%d %x", p_port->rx.queue_size, *p_len, (p_data[0]));
1164e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1165e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
1166e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1167e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT2 ("PORT_ReadData queue:%d returned:%d", p_port->rx.queue_size, *p_len);
1168e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1169e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1170e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
1171e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* check if it can be resumed now */
1172e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    port_flow_control_peer (p_port, TRUE, count);
117366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1174e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
1175e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1176e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1177e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1178e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1179e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1180e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_Read
1181e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1182e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Normally application will call this function after receiving
1183e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  PORT_EV_RXCHAR event.
1184e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
118566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
118666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  pp_buf      - pointer to address of buffer with data,
1187e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1188e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1189e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_Read (UINT16 handle, BT_HDR **pp_buf)
1190e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1191e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
1192e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR     *p_buf;
1193e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1194e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_Read() handle:%d", handle);
1195e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1196e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
1197e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1198e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1199e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1200e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1201e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1202e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1203e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1204e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1205e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1206e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1207e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1208e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
1209e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1210e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
1211e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1212e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1213e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    PORT_SCHEDULE_LOCK;
1214e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1215e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue);
1216e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_buf)
1217e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1218e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->rx.queue_size -= p_buf->len;
1219e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1220e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_UNLOCK;
1221e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1222e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
1223e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* check if it can be resumed now */
1224e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        port_flow_control_peer (p_port, TRUE, 1);
1225e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1226e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
1227e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1228e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_UNLOCK;
1229e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1230e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1231e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *pp_buf = p_buf;
1232e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
1233e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1234e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1235e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1236e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1237e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1238e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         port_write
1239e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
124066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function when a data packet is received from the apper
124166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  layer task.
1242e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
124366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      p_port     - pointer to address of port control block
124466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_buf      - pointer to address of buffer with data,
1245e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1246e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1247e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachstatic int port_write (tPORT *p_port, BT_HDR *p_buf)
1248e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1249e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* We should not allow to write data in to server port when connection is not opened */
125066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED))
1251e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1252e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_freebuf (p_buf);
1253e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_CLOSED);
1254e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1255e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1256e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Keep the data in pending queue if peer does not allow data, or */
1257e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Peer is not ready or Port is not yet opened or initial port control */
1258e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* command has not been sent */
1259e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->tx.peer_fc
126066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     || !p_port->rfc.p_mcb
126166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     || !p_port->rfc.p_mcb->peer_ready
126266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     || (p_port->rfc.state != RFC_STATE_OPENED)
126366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     || ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) !=
1264e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                              (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)))
1265e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1266e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if ((p_port->tx.queue_size  > PORT_TX_CRITICAL_WM)
1267e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach         || (p_port->tx.queue.count > PORT_TX_BUF_CRITICAL_WM))
1268e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
126966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            RFCOMM_TRACE_WARNING1 ("PORT_Write: Queue size: %d",
1270e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                   p_port->tx.queue_size);
1271e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1272e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            GKI_freebuf (p_buf);
1273e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1274e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if ((p_port->p_callback != NULL) && (p_port->ev_mask & PORT_EV_ERR))
1275e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                  p_port->p_callback (PORT_EV_ERR, p_port->inx);
1276e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1277e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            return (PORT_TX_FULL);
1278e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
1279e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
128066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_EVENT4 ("PORT_Write : Data is enqued. flow disabled %d peer_ready %d state %d ctrl_state %x",
128166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                             p_port->tx.peer_fc,
1282e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                             (p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready),
1283e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                             p_port->rfc.state,
1284e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                             p_port->port_ctrl);
1285e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1286e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_enqueue (&p_port->tx.queue, p_buf);
1287e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->tx.queue_size += p_buf->len;
1288e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1289e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_CMD_PENDING);
1290e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1291e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
1292e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1293e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT0 ("PORT_Write : Data is being sent");
1294e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1295e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_DataReq (p_port->rfc.p_mcb, p_port->dlci, p_buf);
1296e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
1297e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1298e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1299e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1300e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1301e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1302e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_Write
1303e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
130466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      This function when a data packet is received from the apper
130566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  layer task.
1306e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
130766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
130866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  pp_buf      - pointer to address of buffer with data,
1309e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1310e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1311e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_Write (UINT16 handle, BT_HDR *p_buf)
1312e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1313e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT  *p_port;
1314e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT32 event = 0;
1315e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    int    rc;
1316e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1317e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_Write() handle:%d", handle);
1318e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1319e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
1320e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1321e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1322e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_freebuf (p_buf);
1323e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1324e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1325e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1326e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1327e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1328e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1329e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1330e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_freebuf (p_buf);
1331e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1332e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1333e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1334e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->line_status)
1335e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
133666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_WARNING1 ("PORT_Write: Data dropped line_status:0x%x",
1337e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                               p_port->line_status);
1338e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_freebuf (p_buf);
1339e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_LINE_ERR);
1340e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1341e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1342e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rc = port_write (p_port, p_buf);
1343e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    event |= port_flow_control_user (p_port);
134466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1345e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    switch (rc)
1346e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1347e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_TX_FULL:
1348e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        event |= PORT_EV_ERR;
1349e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
1350e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1351e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case PORT_SUCCESS:
1352e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        event |= (PORT_EV_TXCHAR | PORT_EV_TXEMPTY);
1353e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
1354e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1355e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Mask out all events that are not of interest to user */
1356e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    event &= p_port->ev_mask;
1357e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1358e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Send event to the application */
1359e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->p_callback && event)
1360e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        (p_port->p_callback)(event, p_port->inx);
1361e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1362e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
1363e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
136466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani/*******************************************************************************
136566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
136666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Function         PORT_WriteDataCO
136766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
136866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      Normally not GKI aware application will call this function
136966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  to send data to the port by callout functions
137066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
137166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
137266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  fd         - socket fd
137366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**                  p_len      - Byte count returned
137466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani**
137566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani*******************************************************************************/
137666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryaniint PORT_WriteDataCO (UINT16 handle, int* p_len)
137766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani{
137866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
137966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    tPORT      *p_port;
138066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    BT_HDR     *p_buf;
138166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    UINT32     event = 0;
138266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int        rc = 0;
138366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    UINT16     length;
138466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
138566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    RFCOMM_TRACE_API1 ("PORT_WriteDataCO() handle:%d", handle);
138666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int written;
138766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    *p_len = 0;
138866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
138966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* Check if handle is valid to avoid crashing */
139066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if ((handle == 0) || (handle > MAX_RFC_PORTS))
139166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
139266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_BAD_HANDLE);
139366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
139466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    p_port = &rfc_cb.port.port[handle - 1];
139566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
139666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
139766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
139866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_WARNING1 ("PORT_WriteDataByFd() no port state:%d", p_port->state);
139966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_NOT_OPENED);
140066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
140166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
140266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (!p_port->peer_mtu)
140366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
140466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_ERROR1 ("PORT_WriteDataByFd() peer_mtu:%d", p_port->peer_mtu);
140566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_UNKNOWN_ERROR);
140666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
140766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    int available = 0;
140866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    //if(ioctl(fd, FIONREAD, &available) < 0)
140966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if(p_port->p_data_co_callback(handle, (UINT8*)&available, sizeof(available),
141066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                                DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE) == FALSE)
141166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
141266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_ERROR1("p_data_co_callback DATA_CO_CALLBACK_TYPE_INCOMING_SIZE failed, available:%d", available);
141366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_UNKNOWN_ERROR);
141466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
141566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */
141666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    length = RFCOMM_DATA_POOL_BUF_SIZE -
141766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
141866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
141966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* If there are buffers scheduled for transmission check if requested */
142066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* data fits into the end of the queue */
142166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    PORT_SCHEDULE_LOCK;
142266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
142366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (((p_buf = (BT_HDR *)p_port->tx.queue.p_last) != NULL)
142466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     && (((int)p_buf->len + available) <= (int)p_port->peer_mtu)
142566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani     && (((int)p_buf->len + available) <= (int)length))
142666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
142766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //if(recv(fd, (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, available, 0) != available)
142866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(p_port->p_data_co_callback(handle, (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len,
142966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                                    available, DATA_CO_CALLBACK_TYPE_OUTGOING) == FALSE)
143066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
143166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
143266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            error("p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, available:%d", available);
143366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return (PORT_UNKNOWN_ERROR);
143466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
143566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, max_len);
143666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_port->tx.queue_size += (UINT16)available;
143766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
143866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        *p_len = available;
143966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf->len += (UINT16)available;
144066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
144166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        PORT_SCHEDULE_UNLOCK;
144266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
144366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        return (PORT_SUCCESS);
144466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
144566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
144666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    PORT_SCHEDULE_UNLOCK;
144766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
144866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    //int max_read = length < p_port->peer_mtu ? length : p_port->peer_mtu;
144966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
145066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    //max_read = available < max_read ? available : max_read;
145166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
145266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    while (available)
145366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    {
145466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        /* if we're over buffer high water mark, we're done */
145566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if ((p_port->tx.queue_size  > PORT_TX_HIGH_WM)
145666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani         || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM))
145766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
145866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
145966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        /* continue with rfcomm data write */
146066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_DATA_POOL_ID);
146166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if (!p_buf)
146266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
146366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
146466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf->offset         = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
146566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf->layer_specific = handle;
146666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
146766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if (p_port->peer_mtu < length)
146866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            length = p_port->peer_mtu;
146966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if (available < (int)length)
147066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            length = (UINT16)available;
147166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf->len = length;
147266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        p_buf->event          = BT_EVT_TO_BTU_SP_DATA;
147366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
147466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, length);
147566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        //if(recv(fd, (UINT8 *)(p_buf + 1) + p_buf->offset, (int)length, 0) != (int)length)
147666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if(p_port->p_data_co_callback(handle, (UINT8 *)(p_buf + 1) + p_buf->offset, length,
147766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani                                      DATA_CO_CALLBACK_TYPE_OUTGOING) == FALSE)
147866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        {
147966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            error("p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, length:%d", length);
148066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            return (PORT_UNKNOWN_ERROR);
148166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        }
148266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
148366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
148466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        RFCOMM_TRACE_EVENT1 ("PORT_WriteData %d bytes", length);
148566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
148666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        rc = port_write (p_port, p_buf);
148766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
148866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        /* If queue went below the threashold need to send flow control */
148966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        event |= port_flow_control_user (p_port);
149066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
149166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if (rc == PORT_SUCCESS)
149266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            event |= PORT_EV_TXCHAR;
149366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
149466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING))
149566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani            break;
149666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
149766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        *p_len  += length;
149866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        available -= (int)length;
149966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    }
150066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (!available && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED))
150166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        event |= PORT_EV_TXEMPTY;
150266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
150366aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* Mask out all events that are not of interest to user */
150466aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    event &= p_port->ev_mask;
150566aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
150666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    /* Send event to the application */
150766aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    if (p_port->p_callback && event)
150866aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani        (p_port->p_callback)(event, p_port->inx);
150966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
151066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    return (PORT_SUCCESS);
151166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani}
151266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1513e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1514e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1515e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1516e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1517e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_WriteData
1518e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
151966aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Description      Normally not GKI aware application will call this function
1520e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  to send data to the port.
1521e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
152266aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani** Parameters:      handle     - Handle returned in the RFCOMM_CreateConnection
1523e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_data      - Data area
1524e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  max_len     - Byte count requested
1525e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_len       - Byte count received
1526e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1527e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1528e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_WriteData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len)
1529e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1530e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT      *p_port;
1531e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR     *p_buf;
1532e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT32     event = 0;
1533e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    int        rc = 0;
1534e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16     length;
1535e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1536e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_WriteData() max_len:%d", max_len);
1537e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1538e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    *p_len = 0;
1539e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1540e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Check if handle is valid to avoid crashing */
1541e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1542e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1543e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1544e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1545e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1546e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1547e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1548e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1549e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_WARNING1 ("PORT_WriteData() no port state:%d", p_port->state);
1550e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1551e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1552e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1553e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!max_len || !p_port->peer_mtu)
1554e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1555e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_ERROR1 ("PORT_WriteData() peer_mtu:%d", p_port->peer_mtu);
1556e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_UNKNOWN_ERROR);
1557e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1558e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1559e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */
156066aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani    length = RFCOMM_DATA_POOL_BUF_SIZE -
1561e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
1562e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1563e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* If there are buffers scheduled for transmission check if requested */
1564e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* data fits into the end of the queue */
1565e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    PORT_SCHEDULE_LOCK;
1566e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1567e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (((p_buf = (BT_HDR *)p_port->tx.queue.p_last) != NULL)
1568e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     && ((p_buf->len + max_len) <= p_port->peer_mtu)
1569e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach     && ((p_buf->len + max_len) <= length))
1570e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1571e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, max_len);
1572e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_port->tx.queue_size += max_len;
1573e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1574e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        *p_len = max_len;
1575e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len += max_len;
1576e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1577e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        PORT_SCHEDULE_UNLOCK;
1578e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1579e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
1580e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1581e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1582e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    PORT_SCHEDULE_UNLOCK;
1583e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1584e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    while (max_len)
1585e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1586e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* if we're over buffer high water mark, we're done */
1587e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if ((p_port->tx.queue_size  > PORT_TX_HIGH_WM)
1588e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach         || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM))
1589e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
1590e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1591e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* continue with rfcomm data write */
1592e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_DATA_POOL_ID);
1593e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (!p_buf)
1594e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
1595e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1596e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset         = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
1597e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->layer_specific = handle;
1598e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1599e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_port->peer_mtu < length)
1600e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            length = p_port->peer_mtu;
1601e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (max_len < length)
1602e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            length = max_len;
1603e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = length;
1604e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->event          = BT_EVT_TO_BTU_SP_DATA;
1605e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1606e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, length);
1607e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1608e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        RFCOMM_TRACE_EVENT1 ("PORT_WriteData %d bytes", length);
1609e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1610e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        rc = port_write (p_port, p_buf);
161166aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1612e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* If queue went below the threashold need to send flow control */
1613e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        event |= port_flow_control_user (p_port);
1614e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1615e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (rc == PORT_SUCCESS)
1616e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            event |= PORT_EV_TXCHAR;
1617e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1618e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING))
1619e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
1620e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1621e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        *p_len  += length;
1622e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        max_len -= length;
1623e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_data  += length;
1624e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1625e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1626e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!max_len && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED))
1627e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        event |= PORT_EV_TXEMPTY;
1628e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1629e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Mask out all events that are not of interest to user */
1630e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    event &= p_port->ev_mask;
1631e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1632e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    /* Send event to the application */
1633e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_port->p_callback && event)
1634e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        (p_port->p_callback)(event, p_port->inx);
1635e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1636e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (PORT_SUCCESS);
1637e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1638e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1639e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1640e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1641e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1642e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_Test
1643e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1644e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Application can call this function to send RFCOMM Test frame
1645e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1646e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Parameters:      handle      - Handle returned in the RFCOMM_CreateConnection
1647e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_data      - Data area
1648e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  max_len     - Byte count requested
1649e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1650e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1651e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachint PORT_Test (UINT16 handle, UINT8 *p_data, UINT16 len)
1652e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1653e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR   *p_buf;
1654e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tPORT    *p_port;
1655e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1656e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    RFCOMM_TRACE_API1 ("PORT_Test() len:%d", len);
1657e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1658e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((handle == 0) || (handle > MAX_RFC_PORTS))
1659e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1660e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_BAD_HANDLE);
1661e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1662e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    p_port = &rfc_cb.port.port[handle - 1];
1663e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1664e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED))
1665e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1666e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NOT_OPENED);
1667e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1668e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1669e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (len > ((p_port->mtu == 0) ? RFCOMM_DEFAULT_MTU : p_port->mtu))
1670e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1671e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_UNKNOWN_ERROR);
1672e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1673e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1674e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) != NULL)
1675e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
167666aa5171e4e7c9f942971a30419c03134e67a4a4Harish Paryani
1677e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset  = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2;
1678e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = len;
1679e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1680e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
1681e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1682e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        rfc_send_test (p_port->rfc.p_mcb, TRUE, p_buf);
1683e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_SUCCESS);
1684e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1685e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
1686e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
1687e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return (PORT_NO_MEM);
1688e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
1689e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1690e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1691e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1692e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1693e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         RFCOMM_Init
1694e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1695e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function is called to initialize RFCOMM layer
1696e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1697e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1698e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid RFCOMM_Init (void)
1699e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1700e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    memset (&rfc_cb, 0, sizeof (tRFC_CB));  /* Init RFCOMM control block */
1701e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1702e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
1703e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1704e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if defined(RFCOMM_INITIAL_TRACE_LEVEL)
1705e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rfc_cb.trace_level = RFCOMM_INITIAL_TRACE_LEVEL;
1706e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#else
1707e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rfc_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
1708e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif
1709e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1710e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    rfcomm_l2cap_if_init ();
1711e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1712e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1713e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
1714e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1715e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         PORT_SetTraceLevel
1716e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1717e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      This function sets the trace level for RFCOMM. If called with
1718e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  a value of 0xFF, it simply reads the current trace level.
1719e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1720e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          the new (current) trace level
1721e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
1722e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
1723e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachUINT8 PORT_SetTraceLevel (UINT8 new_level)
1724e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
1725e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (new_level != 0xFF)
1726e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        rfc_cb.trace_level = new_level;
1727e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1728e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return (rfc_cb.trace_level);
1729e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
1730e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
1731