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