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