1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /*****************************************************************************
21 * This file contains functions callable by an application
22 * running on top of RFCOMM
24 *****************************************************************************/
27 #include "bt_common.h"
28 #include "bt_target.h"
31 #include "osi/include/osi.h"
39 /*******************************************************************************
41 * Function RFCOMM_StartReq
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.
48 ******************************************************************************/
49 void RFCOMM_StartReq(tRFC_MCB* p_mcb) {
50 rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_REQ, NULL);
53 /*******************************************************************************
55 * Function RFCOMM_StartRsp
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.
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);
66 /*******************************************************************************
68 * Function RFCOMM_DlcEstablishReq
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
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);
84 tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
86 RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
90 rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL);
93 /*******************************************************************************
95 * Function RFCOMM_DlcEstablishRsp
97 * Description This function is called by the port emulation entity
98 * acks Establish Indication.
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);
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);
113 rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
116 /*******************************************************************************
118 * Function RFCOMM_ParNegReq
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
126 ******************************************************************************/
127 void RFCOMM_ParNegReq(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
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);
138 if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
139 p_port->error = PORT_PAR_NEG_FAILED;
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;
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
153 p_port->credit_rx = k;
155 cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
159 /* Send Parameter Negotiation Command UIH frame */
160 p_port->rfc.expected_rsp |= RFC_RSP_PN;
162 rfc_send_pn(p_mcb, dlci, true, mtu, cl, k);
164 rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
167 /*******************************************************************************
169 * Function RFCOMM_ParNegRsp
171 * Description This function is called by the user app to acknowledge
172 * DLC parameter negotiation.
174 ******************************************************************************/
175 void RFCOMM_ParNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl,
177 if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
179 /* Send Parameter Negotiation Response UIH frame */
180 rfc_send_pn(p_mcb, dlci, false, mtu, cl, k);
183 /*******************************************************************************
185 * Function RFCOMM_PortNegReq
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
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);
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);
206 /* Send Parameter Negotiation Command UIH frame */
208 p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
210 p_port->rfc.expected_rsp |= RFC_RSP_RPN;
212 rfc_send_rpn(p_mcb, dlci, true, p_pars, RFCOMM_RPN_PM_MASK);
213 rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
216 /*******************************************************************************
218 * Function RFCOMM_PortNegRsp
220 * Description This function is called by the user app to acknowledge
221 * Port parameters negotiation.
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;
228 rfc_send_rpn(p_mcb, dlci, false, p_pars, param_mask);
231 /*******************************************************************************
233 * Function RFCOMM_ControlReq
235 * Description This function is called by the port entity to send control
236 * parameters to remote port emulation entity.
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);
246 if ((p_port->state != PORT_STATE_OPENED) ||
247 (p_port->rfc.state != RFC_STATE_OPENED))
250 p_port->port_ctrl |= PORT_CTRL_REQ_SENT;
252 p_port->rfc.expected_rsp |= RFC_RSP_MSC;
254 rfc_send_msc(p_mcb, dlci, true, p_pars);
255 rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
258 /*******************************************************************************
260 * Function RFCOMM_FlowReq
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.
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);
274 if ((p_port->state != PORT_STATE_OPENED) ||
275 (p_port->rfc.state != RFC_STATE_OPENED))
278 p_port->local_ctrl.fc = !enable;
280 p_port->rfc.expected_rsp |= RFC_RSP_MSC;
282 rfc_send_msc(p_mcb, dlci, true, &p_port->local_ctrl);
283 rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
286 /*******************************************************************************
288 * Function RFCOMM_LineStatusReq
290 * Description This function is called by the port entity when line
291 * status should be delivered to the peer.
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);
301 if ((p_port->state != PORT_STATE_OPENED) ||
302 (p_port->rfc.state != RFC_STATE_OPENED))
305 p_port->rfc.expected_rsp |= RFC_RSP_RLS;
307 rfc_send_rls(p_mcb, dlci, true, status);
308 rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
311 /*******************************************************************************
313 * Function RFCOMM_DlcReleaseReq
315 * Description This function is called by the PORT unit to close DLC
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);
322 /*******************************************************************************
324 * Function RFCOMM_DataReq
326 * Description This function is called by the user app to send data buffer
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,