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
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
86    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
87    {
88        PORT_DlcEstablishCnf (p_mcb, dlci, 0, RFCOMM_ERROR);
89        return;
90    }
91
92    rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
93}
94
95
96/*******************************************************************************
97**
98** Function         RFCOMM_DlcEstablishRsp
99**
100** Description      This function is called by the port emulation entity
101**                  acks Establish Indication.
102**
103*******************************************************************************/
104void RFCOMM_DlcEstablishRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result)
105{
106    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
107
108    if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS))
109    {
110        PORT_DlcReleaseInd (p_mcb, dlci);
111        return;
112    }
113
114    rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
115}
116
117
118/*******************************************************************************
119**
120** Function         RFCOMM_ParNegReq
121**
122** Description      This function is called by the user app to start
123**                  DLC parameter negotiation.  Port emulation can send this
124**                  request before actually establishing the DLC.  In this
125**                  case the function will allocate RFCOMM connection control
126**                  block.
127**
128*******************************************************************************/
129void RFCOMM_ParNegReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
130{
131    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
132    UINT8 flow;
133    UINT8 cl;
134    UINT8 k;
135
136    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
137    {
138        p_port->error = PORT_PAR_NEG_FAILED;
139        return;
140    }
141
142    /* Negotiate the flow control mechanism.  If flow control mechanism for */
143    /* mux has not been set yet, use our default value.  If it has been set, */
144    /* use that value. */
145    flow = (p_mcb->flow == PORT_FC_UNDEFINED) ? PORT_FC_DEFAULT : p_mcb->flow;
146
147    /* Set convergence layer and number of credits (k) */
148    if (flow == PORT_FC_CREDIT)
149    {
150        cl = RFCOMM_PN_CONV_LAYER_CBFC_I;
151        k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
152        p_port->credit_rx = k;
153    }
154    else
155    {
156        cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
157        k = 0;
158    }
159
160    /* Send Parameter Negotiation Command UIH frame */
161    p_port->rfc.expected_rsp |= RFC_RSP_PN;
162
163    rfc_send_pn (p_mcb, dlci, TRUE, mtu, cl, k);
164
165    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
166}
167
168
169/*******************************************************************************
170**
171** Function         RFCOMM_ParNegRsp
172**
173** Description      This function is called by the user app to acknowledge
174**                  DLC parameter negotiation.
175**
176*******************************************************************************/
177void RFCOMM_ParNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
178{
179    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
180        return;
181
182    /* Send Parameter Negotiation Response UIH frame */
183    rfc_send_pn (p_mcb, dlci, FALSE, mtu, cl, k);
184}
185
186
187/*******************************************************************************
188**
189** Function         RFCOMM_PortNegReq
190**
191** Description      This function is called by the user app to start
192**                  Remote Port parameter negotiation.  Port emulation can
193**                  send this request before actually establishing the DLC.
194**                  In this case the function will allocate RFCOMM connection
195**                  control block.
196**
197*******************************************************************************/
198void RFCOMM_PortNegReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars)
199{
200    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
201
202    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
203    {
204        PORT_PortNegCnf (p_mcb, dlci, NULL, RFCOMM_ERROR);
205        return;
206    }
207
208    /* Send Parameter Negotiation Command UIH frame */
209    if (!p_pars)
210        p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
211    else
212        p_port->rfc.expected_rsp |= RFC_RSP_RPN;
213
214    rfc_send_rpn (p_mcb, dlci, TRUE, p_pars, RFCOMM_RPN_PM_MASK);
215    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
216
217}
218
219
220/*******************************************************************************
221**
222** Function         RFCOMM_PortNegRsp
223**
224** Description      This function is called by the user app to acknowledge
225**                  Port parameters negotiation.
226**
227*******************************************************************************/
228void RFCOMM_PortNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars,
229                        UINT16 param_mask)
230{
231    if (p_mcb->state != RFC_MX_STATE_CONNECTED)
232        return;
233
234   rfc_send_rpn (p_mcb, dlci, FALSE, p_pars, param_mask);
235}
236
237
238/*******************************************************************************
239**
240** Function         RFCOMM_ControlReq
241**
242** Description      This function is called by the port entity to send control
243**                  parameters to remote port emulation entity.
244**
245*******************************************************************************/
246void RFCOMM_ControlReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars)
247{
248    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
249
250    if ((p_port->state != PORT_STATE_OPENED)
251     || (p_port->rfc.state  != RFC_STATE_OPENED))
252        return;
253
254    p_port->port_ctrl |= PORT_CTRL_REQ_SENT;
255
256    p_port->rfc.expected_rsp |= RFC_RSP_MSC;
257
258    rfc_send_msc (p_mcb, dlci, TRUE, p_pars);
259    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
260
261}
262
263
264/*******************************************************************************
265**
266** Function         RFCOMM_FlowReq
267**
268** Description      This function is called by the port entity when flow
269**                  control state has changed.  Enable flag passed shows if
270**                  port can accept more data.
271**
272*******************************************************************************/
273void RFCOMM_FlowReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 enable)
274{
275    tPORT      *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
276
277    if ((p_port->state != PORT_STATE_OPENED)
278     || (p_port->rfc.state  != RFC_STATE_OPENED))
279        return;
280
281    p_port->local_ctrl.fc = !enable;
282
283    p_port->rfc.expected_rsp |= RFC_RSP_MSC;
284
285    rfc_send_msc (p_mcb, dlci, TRUE, &p_port->local_ctrl);
286    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
287
288}
289
290
291/*******************************************************************************
292**
293** Function         RFCOMM_LineStatusReq
294**
295** Description      This function is called by the port entity when line
296**                  status should be delivered to the peer.
297**
298*******************************************************************************/
299void RFCOMM_LineStatusReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 status)
300{
301    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
302
303    if ((p_port->state != PORT_STATE_OPENED)
304     || (p_port->rfc.state  != RFC_STATE_OPENED))
305        return;
306
307    p_port->rfc.expected_rsp |= RFC_RSP_RLS;
308
309    rfc_send_rls (p_mcb, dlci, TRUE, status);
310    rfc_port_timer_start (p_port, RFC_T2_TIMEOUT);
311}
312
313
314/*******************************************************************************
315**
316** Function         RFCOMM_DlcReleaseReq
317**
318** Description      This function is called by the PORT unit to close DLC
319**
320*******************************************************************************/
321void RFCOMM_DlcReleaseReq (tRFC_MCB *p_mcb, UINT8 dlci)
322{
323    rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_CLOSE, 0);
324}
325
326
327/*******************************************************************************
328**
329** Function         RFCOMM_DataReq
330**
331** Description      This function is called by the user app to send data buffer
332**
333*******************************************************************************/
334void RFCOMM_DataReq (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
335{
336    rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_DATA, p_buf);
337}
338
339
340