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 "common/bt_target.h"
28 #include "stack/rfcdefs.h"
29 #include "stack/port_api.h"
30 #include "stack/l2c_api.h"
31 #include "port_int.h"
32 #include "rfc_int.h"
33 #include "common/bt_defs.h"
34
35 #if (defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
36
37 #if RFC_DYNAMIC_MEMORY == FALSE
38 tRFC_CB rfc_cb;
39 #else
40 tRFC_CB *rfc_cb_ptr;
41 #endif
42
43 /*******************************************************************************
44 **
45 ** Function RFCOMM_StartReq
46 **
47 ** Description This function handles Start Request from the upper layer.
48 ** If RFCOMM multiplexer channel can not be allocated
49 ** send start not accepted confirmation. Otherwise dispatch
50 ** start event to the state machine.
51 **
52 *******************************************************************************/
RFCOMM_StartReq(tRFC_MCB * p_mcb)53 void RFCOMM_StartReq (tRFC_MCB *p_mcb)
54 {
55 rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_START_REQ, NULL);
56 }
57
58
59 /*******************************************************************************
60 **
61 ** Function RFCOMM_StartRsp
62 **
63 ** Description This function handles Start Response from the upper layer.
64 ** Save upper layer handle and result of the Start Indication
65 ** in the control block and dispatch event to the FSM.
66 **
67 *******************************************************************************/
RFCOMM_StartRsp(tRFC_MCB * p_mcb,UINT16 result)68 void RFCOMM_StartRsp (tRFC_MCB *p_mcb, UINT16 result)
69 {
70 rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_START_RSP, &result);
71 }
72
73
74 /*******************************************************************************
75 **
76 ** Function RFCOMM_DlcEstablishReq
77 **
78 ** Description This function is called by the user app to establish
79 ** connection with the specific dlci on a specific bd device.
80 ** It will allocate RFCOMM connection control block if not
81 ** allocated before and dispatch open event to the state
82 ** machine.
83 **
84 *******************************************************************************/
RFCOMM_DlcEstablishReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)85 void RFCOMM_DlcEstablishReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
86 {
87 UNUSED(mtu);
88 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
89 PORT_DlcEstablishCnf (p_mcb, dlci, 0, RFCOMM_ERROR);
90 return;
91 }
92
93 tPORT *p_port = port_find_mcb_dlci_port(p_mcb, dlci);
94 if (p_port == NULL) {
95 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
96 dlci);
97 return;
98 }
99
100 rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
101 }
102
103
104 /*******************************************************************************
105 **
106 ** Function RFCOMM_DlcEstablishRsp
107 **
108 ** Description This function is called by the port emulation entity
109 ** acks Establish Indication.
110 **
111 *******************************************************************************/
RFCOMM_DlcEstablishRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT16 result)112 void RFCOMM_DlcEstablishRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result)
113 {
114 UNUSED(mtu);
115 if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS)) {
116 PORT_DlcReleaseInd (p_mcb, dlci);
117 return;
118 }
119
120 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
121 if (p_port == NULL) {
122 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
123 dlci);
124 return;
125 }
126 rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
127 }
128
129
130 /*******************************************************************************
131 **
132 ** Function RFCOMM_ParNegReq
133 **
134 ** Description This function is called by the user app to start
135 ** DLC parameter negotiation. Port emulation can send this
136 ** request before actually establishing the DLC. In this
137 ** case the function will allocate RFCOMM connection control
138 ** block.
139 **
140 *******************************************************************************/
RFCOMM_ParNegReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)141 void RFCOMM_ParNegReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
142 {
143 UINT8 flow;
144 UINT8 cl;
145 UINT8 k;
146
147 tPORT *p_port = port_find_mcb_dlci_port(p_mcb, dlci);
148 if (p_port == NULL) {
149 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
150 dlci);
151 return;
152 }
153
154 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
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 cl = RFCOMM_PN_CONV_LAYER_CBFC_I;
167 k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
168 p_port->credit_rx = k;
169 } else {
170 cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
171 k = 0;
172 }
173
174 /* Send Parameter Negotiation Command UIH frame */
175 p_port->rfc.expected_rsp |= RFC_RSP_PN;
176
177 rfc_send_pn (p_mcb, dlci, TRUE, mtu, cl, k);
178
179 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
180 }
181
182
183 /*******************************************************************************
184 **
185 ** Function RFCOMM_ParNegRsp
186 **
187 ** Description This function is called by the user app to acknowledge
188 ** DLC parameter negotiation.
189 **
190 *******************************************************************************/
RFCOMM_ParNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT8 cl,UINT8 k)191 void RFCOMM_ParNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
192 {
193 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
194 return;
195 }
196
197 /* Send Parameter Negotiation Response UIH frame */
198 rfc_send_pn (p_mcb, dlci, FALSE, mtu, cl, k);
199 }
200
201
202 /*******************************************************************************
203 **
204 ** Function RFCOMM_PortNegReq
205 **
206 ** Description This function is called by the user app to start
207 ** Remote Port parameter negotiation. Port emulation can
208 ** send this request before actually establishing the DLC.
209 ** In this case the function will allocate RFCOMM connection
210 ** control block.
211 **
212 *******************************************************************************/
RFCOMM_PortNegReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars)213 void RFCOMM_PortNegReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars)
214 {
215 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
216 PORT_PortNegCnf (p_mcb, dlci, NULL, RFCOMM_ERROR);
217 return;
218 }
219
220 tPORT *p_port = port_find_mcb_dlci_port(p_mcb, dlci);
221 if (p_port == NULL) {
222 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
223 dlci);
224 return;
225 }
226
227 /* Send Parameter Negotiation Command UIH frame */
228 if (!p_pars) {
229 p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
230 } else {
231 p_port->rfc.expected_rsp |= RFC_RSP_RPN;
232 }
233
234 rfc_send_rpn (p_mcb, dlci, TRUE, p_pars, RFCOMM_RPN_PM_MASK);
235 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
236
237 }
238
239
240 /*******************************************************************************
241 **
242 ** Function RFCOMM_PortNegRsp
243 **
244 ** Description This function is called by the user app to acknowledge
245 ** Port parameters negotiation.
246 **
247 *******************************************************************************/
RFCOMM_PortNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars,UINT16 param_mask)248 void RFCOMM_PortNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars,
249 UINT16 param_mask)
250 {
251 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
252 return;
253 }
254
255 rfc_send_rpn (p_mcb, dlci, FALSE, p_pars, param_mask);
256 }
257
258
259 /*******************************************************************************
260 **
261 ** Function RFCOMM_ControlReq
262 **
263 ** Description This function is called by the port entity to send control
264 ** parameters to remote port emulation entity.
265 **
266 *******************************************************************************/
RFCOMM_ControlReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_CTRL * p_pars)267 void RFCOMM_ControlReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars)
268 {
269 tPORT *p_port = port_find_mcb_dlci_port(p_mcb, dlci);
270 if (p_port == NULL) {
271 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
272 dlci);
273 return;
274 }
275
276 if ((p_port->state != PORT_STATE_OPENED)
277 || (p_port->rfc.state != RFC_STATE_OPENED)) {
278 return;
279 }
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
314 p_port->local_ctrl.fc = !enable;
315
316 p_port->rfc.expected_rsp |= RFC_RSP_MSC;
317
318 rfc_send_msc (p_mcb, dlci, TRUE, &p_port->local_ctrl);
319 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
320
321 }
322
323
324 /*******************************************************************************
325 **
326 ** Function RFCOMM_LineStatusReq
327 **
328 ** Description This function is called by the port entity when line
329 ** status should be delivered to the peer.
330 **
331 *******************************************************************************/
RFCOMM_LineStatusReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 status)332 void RFCOMM_LineStatusReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 status)
333 {
334 tPORT *p_port = port_find_mcb_dlci_port(p_mcb, dlci);
335 if (p_port == NULL) {
336 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__,
337 dlci);
338 return;
339 }
340
341 if ((p_port->state != PORT_STATE_OPENED)
342 || (p_port->rfc.state != RFC_STATE_OPENED)) {
343 return;
344 }
345
346 p_port->rfc.expected_rsp |= RFC_RSP_RLS;
347
348 rfc_send_rls (p_mcb, dlci, TRUE, status);
349 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT);
350 }
351
352
353 /*******************************************************************************
354 **
355 ** Function RFCOMM_DlcReleaseReq
356 **
357 ** Description This function is called by the PORT unit to close DLC
358 **
359 *******************************************************************************/
RFCOMM_DlcReleaseReq(tRFC_MCB * p_mcb,UINT8 dlci)360 void RFCOMM_DlcReleaseReq (tRFC_MCB *p_mcb, UINT8 dlci)
361 {
362 rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_CLOSE, 0);
363 }
364
365
366 /*******************************************************************************
367 **
368 ** Function RFCOMM_DataReq
369 **
370 ** Description This function is called by the user app to send data buffer
371 **
372 *******************************************************************************/
RFCOMM_DataReq(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)373 void RFCOMM_DataReq (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
374 {
375 rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_DATA, p_buf);
376 }
377
378
379 #endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
380