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 37tRFC_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 ******************************************************************************/ 49void 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 ******************************************************************************/ 62void 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 ******************************************************************************/ 77void 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 ******************************************************************************/ 101void 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 ******************************************************************************/ 127void 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 ******************************************************************************/ 175void 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 ******************************************************************************/ 194void 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 ******************************************************************************/ 224void 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 ******************************************************************************/ 239void 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 ******************************************************************************/ 267void 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 ******************************************************************************/ 294void 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 ******************************************************************************/ 318void 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 ******************************************************************************/ 329void 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} 333