OSDN Git Service

Merge "Don't reject notifications and wait until new addressed player is ready (2...
[android-x86/system-bt.git] / stack / rfcomm / rfc_port_if.cc
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_common.h"
28 #include "bt_target.h"
29 #include "bt_utils.h"
30 #include "l2c_api.h"
31 #include "osi/include/osi.h"
32 #include "port_api.h"
33 #include "port_int.h"
34 #include "rfc_int.h"
35 #include "rfcdefs.h"
36
37 tRFC_CB rfc_cb;
38
39 /*******************************************************************************
40  *
41  * Function         RFCOMM_StartReq
42  *
43  * Description      This function handles Start Request from the upper layer.
44  *                  If RFCOMM multiplexer channel can not be allocated
45  *                  send start not accepted confirmation.  Otherwise dispatch
46  *                  start event to the state machine.
47  *
48  ******************************************************************************/
49 void RFCOMM_StartReq(tRFC_MCB* p_mcb) {
50   rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_REQ, NULL);
51 }
52
53 /*******************************************************************************
54  *
55  * Function         RFCOMM_StartRsp
56  *
57  * Description      This function handles Start Response from the upper layer.
58  *                  Save upper layer handle and result of the Start Indication
59  *                  in the control block and dispatch event to the FSM.
60  *
61  ******************************************************************************/
62 void RFCOMM_StartRsp(tRFC_MCB* p_mcb, uint16_t result) {
63   rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_RSP, &result);
64 }
65
66 /*******************************************************************************
67  *
68  * Function         RFCOMM_DlcEstablishReq
69  *
70  * Description      This function is called by the user app to establish
71  *                  connection with the specific dlci on a specific bd device.
72  *                  It will allocate RFCOMM connection control block if not
73  *                  allocated before and dispatch open event to the state
74  *                  machine.
75  *
76  ******************************************************************************/
77 void RFCOMM_DlcEstablishReq(tRFC_MCB* p_mcb, uint8_t dlci,
78                             UNUSED_ATTR uint16_t mtu) {
79   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
80     PORT_DlcEstablishCnf(p_mcb, dlci, 0, RFCOMM_ERROR);
81     return;
82   }
83
84   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
85   if (p_port == NULL) {
86     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
87     return;
88   }
89
90   rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
91 }
92
93 /*******************************************************************************
94  *
95  * Function         RFCOMM_DlcEstablishRsp
96  *
97  * Description      This function is called by the port emulation entity
98  *                  acks Establish Indication.
99  *
100  ******************************************************************************/
101 void RFCOMM_DlcEstablishRsp(tRFC_MCB* p_mcb, uint8_t dlci,
102                             UNUSED_ATTR uint16_t mtu, uint16_t result) {
103   if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS)) {
104     PORT_DlcReleaseInd(p_mcb, dlci);
105     return;
106   }
107
108   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
109   if (p_port == NULL) {
110     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
111     return;
112   }
113   rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
114 }
115
116 /*******************************************************************************
117  *
118  * Function         RFCOMM_ParNegReq
119  *
120  * Description      This function is called by the user app to start
121  *                  DLC parameter negotiation.  Port emulation can send this
122  *                  request before actually establishing the DLC.  In this
123  *                  case the function will allocate RFCOMM connection control
124  *                  block.
125  *
126  ******************************************************************************/
127 void RFCOMM_ParNegReq(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
128   uint8_t flow;
129   uint8_t cl;
130   uint8_t k;
131
132   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
133   if (p_port == NULL) {
134     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
135     return;
136   }
137
138   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
139     p_port->error = PORT_PAR_NEG_FAILED;
140     return;
141   }
142
143   /* Negotiate the flow control mechanism.  If flow control mechanism for */
144   /* mux has not been set yet, use our default value.  If it has been set, */
145   /* use that value. */
146   flow = (p_mcb->flow == PORT_FC_UNDEFINED) ? PORT_FC_DEFAULT : p_mcb->flow;
147
148   /* Set convergence layer and number of credits (k) */
149   if (flow == PORT_FC_CREDIT) {
150     cl = RFCOMM_PN_CONV_LAYER_CBFC_I;
151     k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max
152                                                : RFCOMM_K_MAX;
153     p_port->credit_rx = k;
154   } else {
155     cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
156     k = 0;
157   }
158
159   /* Send Parameter Negotiation Command UIH frame */
160   p_port->rfc.expected_rsp |= RFC_RSP_PN;
161
162   rfc_send_pn(p_mcb, dlci, true, mtu, cl, k);
163
164   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
165 }
166
167 /*******************************************************************************
168  *
169  * Function         RFCOMM_ParNegRsp
170  *
171  * Description      This function is called by the user app to acknowledge
172  *                  DLC parameter negotiation.
173  *
174  ******************************************************************************/
175 void RFCOMM_ParNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl,
176                       uint8_t k) {
177   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
178
179   /* Send Parameter Negotiation Response UIH frame */
180   rfc_send_pn(p_mcb, dlci, false, mtu, cl, k);
181 }
182
183 /*******************************************************************************
184  *
185  * Function         RFCOMM_PortNegReq
186  *
187  * Description      This function is called by the user app to start
188  *                  Remote Port parameter negotiation.  Port emulation can
189  *                  send this request before actually establishing the DLC.
190  *                  In this case the function will allocate RFCOMM connection
191  *                  control block.
192  *
193  ******************************************************************************/
194 void RFCOMM_PortNegReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars) {
195   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
196     PORT_PortNegCnf(p_mcb, dlci, NULL, RFCOMM_ERROR);
197     return;
198   }
199
200   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
201   if (p_port == NULL) {
202     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
203     return;
204   }
205
206   /* Send Parameter Negotiation Command UIH frame */
207   if (!p_pars)
208     p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
209   else
210     p_port->rfc.expected_rsp |= RFC_RSP_RPN;
211
212   rfc_send_rpn(p_mcb, dlci, true, p_pars, RFCOMM_RPN_PM_MASK);
213   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
214 }
215
216 /*******************************************************************************
217  *
218  * Function         RFCOMM_PortNegRsp
219  *
220  * Description      This function is called by the user app to acknowledge
221  *                  Port parameters negotiation.
222  *
223  ******************************************************************************/
224 void RFCOMM_PortNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars,
225                        uint16_t param_mask) {
226   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
227
228   rfc_send_rpn(p_mcb, dlci, false, p_pars, param_mask);
229 }
230
231 /*******************************************************************************
232  *
233  * Function         RFCOMM_ControlReq
234  *
235  * Description      This function is called by the port entity to send control
236  *                  parameters to remote port emulation entity.
237  *
238  ******************************************************************************/
239 void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) {
240   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
241   if (p_port == NULL) {
242     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
243     return;
244   }
245
246   if ((p_port->state != PORT_STATE_OPENED) ||
247       (p_port->rfc.state != RFC_STATE_OPENED))
248     return;
249
250   p_port->port_ctrl |= PORT_CTRL_REQ_SENT;
251
252   p_port->rfc.expected_rsp |= RFC_RSP_MSC;
253
254   rfc_send_msc(p_mcb, dlci, true, p_pars);
255   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
256 }
257
258 /*******************************************************************************
259  *
260  * Function         RFCOMM_FlowReq
261  *
262  * Description      This function is called by the port entity when flow
263  *                  control state has changed.  Enable flag passed shows if
264  *                  port can accept more data.
265  *
266  ******************************************************************************/
267 void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t enable) {
268   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
269   if (p_port == NULL) {
270     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
271     return;
272   }
273
274   if ((p_port->state != PORT_STATE_OPENED) ||
275       (p_port->rfc.state != RFC_STATE_OPENED))
276     return;
277
278   p_port->local_ctrl.fc = !enable;
279
280   p_port->rfc.expected_rsp |= RFC_RSP_MSC;
281
282   rfc_send_msc(p_mcb, dlci, true, &p_port->local_ctrl);
283   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
284 }
285
286 /*******************************************************************************
287  *
288  * Function         RFCOMM_LineStatusReq
289  *
290  * Description      This function is called by the port entity when line
291  *                  status should be delivered to the peer.
292  *
293  ******************************************************************************/
294 void RFCOMM_LineStatusReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t status) {
295   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
296   if (p_port == NULL) {
297     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
298     return;
299   }
300
301   if ((p_port->state != PORT_STATE_OPENED) ||
302       (p_port->rfc.state != RFC_STATE_OPENED))
303     return;
304
305   p_port->rfc.expected_rsp |= RFC_RSP_RLS;
306
307   rfc_send_rls(p_mcb, dlci, true, status);
308   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
309 }
310
311 /*******************************************************************************
312  *
313  * Function         RFCOMM_DlcReleaseReq
314  *
315  * Description      This function is called by the PORT unit to close DLC
316  *
317  ******************************************************************************/
318 void RFCOMM_DlcReleaseReq(tRFC_MCB* p_mcb, uint8_t dlci) {
319   rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_CLOSE, 0);
320 }
321
322 /*******************************************************************************
323  *
324  * Function         RFCOMM_DataReq
325  *
326  * Description      This function is called by the user app to send data buffer
327  *
328  ******************************************************************************/
329 void RFCOMM_DataReq(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) {
330   rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_DATA,
331                       p_buf);
332 }