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