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