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
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 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 *******************************************************************************/
RFCOMM_DlcEstablishRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT16 result)105 void 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 *******************************************************************************/
RFCOMM_ParNegReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)131 void 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 *******************************************************************************/
RFCOMM_ParNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT8 cl,UINT8 k)179 void 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 *******************************************************************************/
RFCOMM_PortNegReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars)200 void 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 *******************************************************************************/
RFCOMM_PortNegRsp(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars,UINT16 param_mask)230 void 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 *******************************************************************************/
RFCOMM_ControlReq(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_CTRL * p_pars)248 void 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 *******************************************************************************/
RFCOMM_FlowReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 enable)275 void 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 *******************************************************************************/
RFCOMM_LineStatusReq(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 status)301 void 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 *******************************************************************************/
RFCOMM_DlcReleaseReq(tRFC_MCB * p_mcb,UINT8 dlci)323 void 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 *******************************************************************************/
RFCOMM_DataReq(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)336 void 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