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
37 tRFC_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 *******************************************************************************/
RFCOMM_StartReq(tRFC_MCB * p_mcb)50 void 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 *******************************************************************************/
RFCOMM_StartRsp(tRFC_MCB * p_mcb,UINT16 result)65 void 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 *******************************************************************************/
RFCOMM_DlcEstablishReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)82 void 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 *******************************************************************************/
RFCOMM_DlcEstablishRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT16 result)104 void 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 *******************************************************************************/
RFCOMM_ParNegReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)129 void 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 *******************************************************************************/
RFCOMM_ParNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT8 cl,UINT8 k)177 void 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 *******************************************************************************/
RFCOMM_PortNegReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars)198 void 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 *******************************************************************************/
RFCOMM_PortNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars,UINT16 param_mask)228 void 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 *******************************************************************************/
RFCOMM_ControlReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_CTRL * p_pars)246 void 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 *******************************************************************************/
RFCOMM_FlowReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 enable)273 void 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 *******************************************************************************/
RFCOMM_LineStatusReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 status)299 void 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 *******************************************************************************/
RFCOMM_DlcReleaseReq(tRFC_MCB * p_mcb,UINT8 dlci)321 void 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 *******************************************************************************/
RFCOMM_DataReq(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)334 void 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