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 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 85 UNUSED(mtu); 86 87 if (p_mcb->state != RFC_MX_STATE_CONNECTED) 88 { 89 PORT_DlcEstablishCnf (p_mcb, dlci, 0, RFCOMM_ERROR); 90 return; 91 } 92 93 rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, NULL); 94 } 95 96 97 /******************************************************************************* 98 ** 99 ** Function RFCOMM_DlcEstablishRsp 100 ** 101 ** Description This function is called by the port emulation entity 102 ** acks Establish Indication. 103 ** 104 *******************************************************************************/ 105 void RFCOMM_DlcEstablishRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result) 106 { 107 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 108 UNUSED(mtu); 109 110 if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS)) 111 { 112 PORT_DlcReleaseInd (p_mcb, dlci); 113 return; 114 } 115 116 rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result); 117 } 118 119 120 /******************************************************************************* 121 ** 122 ** Function RFCOMM_ParNegReq 123 ** 124 ** Description This function is called by the user app to start 125 ** DLC parameter negotiation. Port emulation can send this 126 ** request before actually establishing the DLC. In this 127 ** case the function will allocate RFCOMM connection control 128 ** block. 129 ** 130 *******************************************************************************/ 131 void RFCOMM_ParNegReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu) 132 { 133 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 134 UINT8 flow; 135 UINT8 cl; 136 UINT8 k; 137 138 if (p_mcb->state != RFC_MX_STATE_CONNECTED) 139 { 140 p_port->error = PORT_PAR_NEG_FAILED; 141 return; 142 } 143 144 /* Negotiate the flow control mechanism. If flow control mechanism for */ 145 /* mux has not been set yet, use our default value. If it has been set, */ 146 /* use that value. */ 147 flow = (p_mcb->flow == PORT_FC_UNDEFINED) ? PORT_FC_DEFAULT : p_mcb->flow; 148 149 /* Set convergence layer and number of credits (k) */ 150 if (flow == PORT_FC_CREDIT) 151 { 152 cl = RFCOMM_PN_CONV_LAYER_CBFC_I; 153 k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX; 154 p_port->credit_rx = k; 155 } 156 else 157 { 158 cl = RFCOMM_PN_CONV_LAYER_TYPE_1; 159 k = 0; 160 } 161 162 /* Send Parameter Negotiation Command UIH frame */ 163 p_port->rfc.expected_rsp |= RFC_RSP_PN; 164 165 rfc_send_pn (p_mcb, dlci, TRUE, mtu, cl, k); 166 167 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ; 168 } 169 170 171 /******************************************************************************* 172 ** 173 ** Function RFCOMM_ParNegRsp 174 ** 175 ** Description This function is called by the user app to acknowledge 176 ** DLC parameter negotiation. 177 ** 178 *******************************************************************************/ 179 void RFCOMM_ParNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k) 180 { 181 if (p_mcb->state != RFC_MX_STATE_CONNECTED) 182 return; 183 184 /* Send Parameter Negotiation Response UIH frame */ 185 rfc_send_pn (p_mcb, dlci, FALSE, mtu, cl, k); 186 } 187 188 189 /******************************************************************************* 190 ** 191 ** Function RFCOMM_PortNegReq 192 ** 193 ** Description This function is called by the user app to start 194 ** Remote Port parameter negotiation. Port emulation can 195 ** send this request before actually establishing the DLC. 196 ** In this case the function will allocate RFCOMM connection 197 ** control block. 198 ** 199 *******************************************************************************/ 200 void RFCOMM_PortNegReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars) 201 { 202 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 203 204 if (p_mcb->state != RFC_MX_STATE_CONNECTED) 205 { 206 PORT_PortNegCnf (p_mcb, dlci, NULL, RFCOMM_ERROR); 207 return; 208 } 209 210 /* Send Parameter Negotiation Command UIH frame */ 211 if (!p_pars) 212 p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY; 213 else 214 p_port->rfc.expected_rsp |= RFC_RSP_RPN; 215 216 rfc_send_rpn (p_mcb, dlci, TRUE, p_pars, RFCOMM_RPN_PM_MASK); 217 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ; 218 219 } 220 221 222 /******************************************************************************* 223 ** 224 ** Function RFCOMM_PortNegRsp 225 ** 226 ** Description This function is called by the user app to acknowledge 227 ** Port parameters negotiation. 228 ** 229 *******************************************************************************/ 230 void RFCOMM_PortNegRsp (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars, 231 UINT16 param_mask) 232 { 233 if (p_mcb->state != RFC_MX_STATE_CONNECTED) 234 return; 235 236 rfc_send_rpn (p_mcb, dlci, FALSE, p_pars, param_mask); 237 } 238 239 240 /******************************************************************************* 241 ** 242 ** Function RFCOMM_ControlReq 243 ** 244 ** Description This function is called by the port entity to send control 245 ** parameters to remote port emulation entity. 246 ** 247 *******************************************************************************/ 248 void RFCOMM_ControlReq (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars) 249 { 250 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 251 252 if ((p_port->state != PORT_STATE_OPENED) 253 || (p_port->rfc.state != RFC_STATE_OPENED)) 254 return; 255 256 p_port->port_ctrl |= PORT_CTRL_REQ_SENT; 257 258 p_port->rfc.expected_rsp |= RFC_RSP_MSC; 259 260 rfc_send_msc (p_mcb, dlci, TRUE, p_pars); 261 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ; 262 263 } 264 265 266 /******************************************************************************* 267 ** 268 ** Function RFCOMM_FlowReq 269 ** 270 ** Description This function is called by the port entity when flow 271 ** control state has changed. Enable flag passed shows if 272 ** port can accept more data. 273 ** 274 *******************************************************************************/ 275 void RFCOMM_FlowReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 enable) 276 { 277 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 278 279 if ((p_port->state != PORT_STATE_OPENED) 280 || (p_port->rfc.state != RFC_STATE_OPENED)) 281 return; 282 283 p_port->local_ctrl.fc = !enable; 284 285 p_port->rfc.expected_rsp |= RFC_RSP_MSC; 286 287 rfc_send_msc (p_mcb, dlci, TRUE, &p_port->local_ctrl); 288 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ; 289 290 } 291 292 293 /******************************************************************************* 294 ** 295 ** Function RFCOMM_LineStatusReq 296 ** 297 ** Description This function is called by the port entity when line 298 ** status should be delivered to the peer. 299 ** 300 *******************************************************************************/ 301 void RFCOMM_LineStatusReq (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 status) 302 { 303 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); 304 305 if ((p_port->state != PORT_STATE_OPENED) 306 || (p_port->rfc.state != RFC_STATE_OPENED)) 307 return; 308 309 p_port->rfc.expected_rsp |= RFC_RSP_RLS; 310 311 rfc_send_rls (p_mcb, dlci, TRUE, status); 312 rfc_port_timer_start (p_port, RFC_T2_TIMEOUT); 313 } 314 315 316 /******************************************************************************* 317 ** 318 ** Function RFCOMM_DlcReleaseReq 319 ** 320 ** Description This function is called by the PORT unit to close DLC 321 ** 322 *******************************************************************************/ 323 void RFCOMM_DlcReleaseReq (tRFC_MCB *p_mcb, UINT8 dlci) 324 { 325 rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_CLOSE, 0); 326 } 327 328 329 /******************************************************************************* 330 ** 331 ** Function RFCOMM_DataReq 332 ** 333 ** Description This function is called by the user app to send data buffer 334 ** 335 *******************************************************************************/ 336 void RFCOMM_DataReq (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf) 337 { 338 rfc_port_sm_execute(port_find_mcb_dlci_port (p_mcb, dlci), RFC_EVENT_DATA, p_buf); 339 } 340 341 342