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     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