Home | History | Annotate | Download | only in rfcomm
      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