1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/*****************************************************************************
20 *
21 * This file contains functions callable by an application
22 * running on top of RFCOMM
23 *
24 *****************************************************************************/
25
26#include <string.h>
27#include "bt_target.h"
28#include "gki.h"
29#include "rfcdefs.h"
30#include "port_api.h"
31#include "l2c_api.h"
32#include "port_int.h"
33#include "rfc_int.h"
34#include "bt_utils.h"
35
36#if RFC_DYNAMIC_MEMORY == FALSE
37tRFC_CB rfc_cb;
38#endif
39
40/*******************************************************************************
41**
42** Function         RFCOMM_StartReq
43**
44** Description      This function handles Start Request from the upper layer.
45**                  If RFCOMM multiplexer channel can not be allocated
46**                  send start not accepted confirmation.  Otherwise dispatch
47**                  start event to the state machine.
48**
49*******************************************************************************/
50void RFCOMM_StartReq (tRFC_MCB *p_mcb)
51{
52    rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_START_REQ, NULL);
53}
54
55
56/*******************************************************************************
57**
58** Function         RFCOMM_StartRsp
59**
60** Description      This function handles Start Response from the upper layer.
61**                  Save upper layer handle and result of the Start Indication
62**                  in the control block and dispatch event to the FSM.
63**
64*******************************************************************************/
65void RFCOMM_StartRsp (tRFC_MCB *p_mcb, UINT16 result)
66{
67    rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_START_RSP, &result);
68}
69
70
71/*******************************************************************************
72**
73** Function         RFCOMM_DlcEstablishReq
74**
75** Description      This function is called by the user app to establish
76**                  connection with the specific dlci on a specific bd device.
77**                  It will allocate RFCOMM connection control block if not
78**                  allocated before and dispatch open event to the state
79**                  machine.
80**
81*******************************************************************************/
82void RFCOMM_DlcEstablishReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
83{
84    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
85    UNUSED(mtu);
86
87    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
88    {
89        PORT_DlcEstablishCnf (p_mcb, dlci, 0, RFCOMM_ERROR);
90        return;
91    }
92
93    rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
94}
95
96
97/*******************************************************************************
98**
99** Function         RFCOMM_DlcEstablishRsp
100**
101** Description      This function is called by the port emulation entity
102**                  acks Establish Indication.
103**
104*******************************************************************************/
105void RFCOMM_DlcEstablishRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result)
106{
107    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
108    UNUSED(mtu);
109
110    if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS))
111    {
112        PORT_DlcReleaseInd (p_mcb, dlci);
113        return;
114    }
115
116    rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
117}
118
119
120/*******************************************************************************
121**
122** Function         RFCOMM_ParNegReq
123**
124** Description      This function is called by the user app to start
125**                  DLC parameter negotiation.  Port emulation can send this
126**                  request before actually establishing the DLC.  In this
127**                  case the function will allocate RFCOMM connection control
128**                  block.
129**
130*******************************************************************************/
131void RFCOMM_ParNegReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
132{
133    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
134    UINT8 flow;
135    UINT8 cl;
136    UINT8 k;
137
138    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
139    {
140        p_port->error = PORT_PAR_NEG_FAILED;
141        return;
142    }
143
144    /* Negotiate the flow control mechanism.  If flow control mechanism for */
145    /* mux has not been set yet, use our default value.  If it has been set, */
146    /* use that value. */
147    flow = (p_mcb->flow == PORT_FC_UNDEFINED) ? PORT_FC_DEFAULT : p_mcb->flow;
148
149    /* Set convergence layer and number of credits (k) */
150    if (flow == PORT_FC_CREDIT)
151    {
152        cl = RFCOMM_PN_CONV_LAYER_CBFC_I;
153        k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
154        p_port->credit_rx = k;
155    }
156    else
157    {
158        cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
159        k = 0;
160    }
161
162    /* Send Parameter Negotiation Command UIH frame */
163    p_port->rfc.expected_rsp |= RFC_RSP_PN;
164
165    rfc_send_pn (p_mcb, dlci, TRUE, mtu, cl, k);
166
167    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
168}
169
170
171/*******************************************************************************
172**
173** Function         RFCOMM_ParNegRsp
174**
175** Description      This function is called by the user app to acknowledge
176**                  DLC parameter negotiation.
177**
178*******************************************************************************/
179void RFCOMM_ParNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
180{
181    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
182        return;
183
184    /* Send Parameter Negotiation Response UIH frame */
185    rfc_send_pn (p_mcb, dlci, FALSE, mtu, cl, k);
186}
187
188
189/*******************************************************************************
190**
191** Function         RFCOMM_PortNegReq
192**
193** Description      This function is called by the user app to start
194**                  Remote Port parameter negotiation.  Port emulation can
195**                  send this request before actually establishing the DLC.
196**                  In this case the function will allocate RFCOMM connection
197**                  control block.
198**
199*******************************************************************************/
200void RFCOMM_PortNegReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars)
201{
202    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
203
204    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
205    {
206        PORT_PortNegCnf (p_mcb, dlci, NULL, RFCOMM_ERROR);
207        return;
208    }
209
210    /* Send Parameter Negotiation Command UIH frame */
211    if (!p_pars)
212        p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
213    else
214        p_port->rfc.expected_rsp |= RFC_RSP_RPN;
215
216    rfc_send_rpn (p_mcb, dlci, TRUE, p_pars, RFCOMM_RPN_PM_MASK);
217    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
218
219}
220
221
222/*******************************************************************************
223**
224** Function         RFCOMM_PortNegRsp
225**
226** Description      This function is called by the user app to acknowledge
227**                  Port parameters negotiation.
228**
229*******************************************************************************/
230void RFCOMM_PortNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars,
231                        UINT16 param_mask)
232{
233    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
234        return;
235
236   rfc_send_rpn (p_mcb, dlci, FALSE, p_pars, param_mask);
237}
238
239
240/*******************************************************************************
241**
242** Function         RFCOMM_ControlReq
243**
244** Description      This function is called by the port entity to send control
245**                  parameters to remote port emulation entity.
246**
247*******************************************************************************/
248void RFCOMM_ControlReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars)
249{
250    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
251
252    if ((p_port->state != PORT_STATE_OPENED)
253     || (p_port->rfc.state  != RFC_STATE_OPENED))
254        return;
255
256    p_port->port_ctrl |= PORT_CTRL_REQ_SENT;
257
258    p_port->rfc.expected_rsp |= RFC_RSP_MSC;
259
260    rfc_send_msc (p_mcb, dlci, TRUE, p_pars);
261    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
262
263}
264
265
266/*******************************************************************************
267**
268** Function         RFCOMM_FlowReq
269**
270** Description      This function is called by the port entity when flow
271**                  control state has changed.  Enable flag passed shows if
272**                  port can accept more data.
273**
274*******************************************************************************/
275void RFCOMM_FlowReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 enable)
276{
277    tPORT      *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
278
279    if ((p_port->state != PORT_STATE_OPENED)
280     || (p_port->rfc.state  != RFC_STATE_OPENED))
281        return;
282
283    p_port->local_ctrl.fc = !enable;
284
285    p_port->rfc.expected_rsp |= RFC_RSP_MSC;
286
287    rfc_send_msc (p_mcb, dlci, TRUE, &p_port->local_ctrl);
288    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
289
290}
291
292
293/*******************************************************************************
294**
295** Function         RFCOMM_LineStatusReq
296**
297** Description      This function is called by the port entity when line
298**                  status should be delivered to the peer.
299**
300*******************************************************************************/
301void RFCOMM_LineStatusReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 status)
302{
303    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
304
305    if ((p_port->state != PORT_STATE_OPENED)
306     || (p_port->rfc.state  != RFC_STATE_OPENED))
307        return;
308
309    p_port->rfc.expected_rsp |= RFC_RSP_RLS;
310
311    rfc_send_rls (p_mcb, dlci, TRUE, status);
312    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT);
313}
314
315
316/*******************************************************************************
317**
318** Function         RFCOMM_DlcReleaseReq
319**
320** Description      This function is called by the PORT unit to close DLC
321**
322*******************************************************************************/
323void RFCOMM_DlcReleaseReq (tRFC_MCB *p_mcb, UINT8 dlci)
324{
325    rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_CLOSE, 0);
326}
327
328
329/*******************************************************************************
330**
331** Function         RFCOMM_DataReq
332**
333** Description      This function is called by the user app to send data buffer
334**
335*******************************************************************************/
336void RFCOMM_DataReq (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
337{
338    rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_DATA, p_buf);
339}
340
341
342