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