Home | History | Annotate | Download | only in mcap
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2009-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 is the implementation file for the MCAP Control Channel Action
     22  *  Functions.
     23  *
     24  ******************************************************************************/
     25 #include <string.h>
     26 #include "bt_target.h"
     27 #include "bt_utils.h"
     28 #include "gki.h"
     29 #include "btm_api.h"
     30 #include "mca_api.h"
     31 #include "mca_defs.h"
     32 #include "mca_int.h"
     33 
     34 
     35 #include  "btu.h"
     36 /*****************************************************************************
     37 ** constants
     38 *****************************************************************************/
     39 /*******************************************************************************
     40 **
     41 ** Function         mca_ccb_rsp_tout
     42 **
     43 ** Description      This function processes the response timeout.
     44 **
     45 ** Returns          void.
     46 **
     47 *******************************************************************************/
     48 void mca_ccb_rsp_tout(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
     49 {
     50    tMCA_CTRL   evt_data;
     51    UNUSED(p_data);
     52 
     53    mca_ccb_report_event(p_ccb, MCA_RSP_TOUT_IND_EVT, &evt_data);
     54 }
     55 
     56 /*******************************************************************************
     57 **
     58 ** Function         mca_ccb_report_event
     59 **
     60 ** Description      This function reports the given event.
     61 **
     62 ** Returns          void.
     63 **
     64 *******************************************************************************/
     65 void mca_ccb_report_event(tMCA_CCB *p_ccb, UINT8 event, tMCA_CTRL *p_data)
     66 {
     67     if (p_ccb && p_ccb->p_rcb && p_ccb->p_rcb->p_cback)
     68         (*p_ccb->p_rcb->p_cback)(mca_rcb_to_handle(p_ccb->p_rcb), mca_ccb_to_hdl(p_ccb), event, p_data);
     69 }
     70 
     71 /*******************************************************************************
     72 **
     73 ** Function         mca_ccb_free_msg
     74 **
     75 ** Description      This function frees the received message.
     76 **
     77 ** Returns          void.
     78 **
     79 *******************************************************************************/
     80 void mca_ccb_free_msg(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
     81 {
     82     UNUSED(p_ccb);
     83 
     84     GKI_freebuf (p_data);
     85 }
     86 
     87 /*******************************************************************************
     88 **
     89 ** Function         mca_ccb_snd_req
     90 **
     91 ** Description      This function builds a request and sends it to the peer.
     92 **
     93 ** Returns          void.
     94 **
     95 *******************************************************************************/
     96 void mca_ccb_snd_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
     97 {
     98     tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data;
     99     BT_HDR  *p_pkt;
    100     UINT8   *p, *p_start;
    101     BOOLEAN is_abort = FALSE;
    102     tMCA_DCB *p_dcb;
    103 
    104     MCA_TRACE_DEBUG ("mca_ccb_snd_req cong=%d req=%d", p_ccb->cong, p_msg->op_code);
    105     /* check for abort request */
    106     if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (p_msg->op_code == MCA_OP_MDL_ABORT_REQ))
    107     {
    108         p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
    109         /* the Abort API does not have the associated mdl_id.
    110          * Get the mdl_id in dcb to compose the request */
    111         p_msg->mdl_id = p_dcb->mdl_id;
    112         mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
    113         mca_free_buf ((void **)&p_ccb->p_tx_req);
    114         p_ccb->status = MCA_CCB_STAT_NORM;
    115         is_abort = TRUE;
    116     }
    117 
    118     /* no pending outgoing messages or it's an abort request for a pending data channel */
    119     if ((!p_ccb->p_tx_req) || is_abort)
    120     {
    121         p_ccb->p_tx_req = p_msg;
    122         if (!p_ccb->cong)
    123         {
    124             p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
    125             if (p_pkt)
    126             {
    127                 p_pkt->offset = L2CAP_MIN_OFFSET;
    128                 p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
    129                 *p++ = p_msg->op_code;
    130                 UINT16_TO_BE_STREAM (p, p_msg->mdl_id);
    131                 if (p_msg->op_code == MCA_OP_MDL_CREATE_REQ)
    132                 {
    133                     *p++ = p_msg->mdep_id;
    134                     *p++ = p_msg->param;
    135                 }
    136                 p_msg->hdr.layer_specific = TRUE;   /* mark this message as sent */
    137                 p_pkt->len = p - p_start;
    138                 L2CA_DataWrite (p_ccb->lcid, p_pkt);
    139                 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE) p_ccb;
    140                 btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_MCA_CCB_RSP, p_ccb->p_rcb->reg.rsp_tout);
    141             }
    142         }
    143         /* else the L2CAP channel is congested. keep the message to be sent later */
    144     }
    145     else
    146     {
    147         MCA_TRACE_WARNING ("dropping api req");
    148         GKI_freebuf (p_data);
    149     }
    150 }
    151 
    152 /*******************************************************************************
    153 **
    154 ** Function         mca_ccb_snd_rsp
    155 **
    156 ** Description      This function builds a response and sends it to
    157 **                  the peer.
    158 **
    159 ** Returns          void.
    160 **
    161 *******************************************************************************/
    162 void mca_ccb_snd_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    163 {
    164     tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data;
    165     BT_HDR  *p_pkt;
    166     UINT8   *p, *p_start;
    167     BOOLEAN chk_mdl = FALSE;
    168 
    169     MCA_TRACE_DEBUG ("mca_ccb_snd_rsp cong=%d req=%d", p_ccb->cong, p_msg->op_code);
    170     /* assume that API functions verified the parameters */
    171     p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
    172     if (p_pkt)
    173     {
    174         p_pkt->offset = L2CAP_MIN_OFFSET;
    175         p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
    176         *p++ = p_msg->op_code;
    177         *p++ = p_msg->rsp_code;
    178         UINT16_TO_BE_STREAM (p, p_msg->mdl_id);
    179         if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP)
    180         {
    181             *p++ = p_msg->param;
    182             chk_mdl = TRUE;
    183         }
    184         else if (p_msg->op_code == MCA_OP_MDL_RECONNECT_RSP)
    185                 chk_mdl = TRUE;
    186 
    187         if (chk_mdl && p_msg->rsp_code == MCA_RSP_SUCCESS)
    188         {
    189             mca_dcb_by_hdl(p_msg->dcb_idx);
    190             BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask,
    191                 p_ccb->p_rcb->reg.data_psm, BTM_SEC_PROTO_MCA, p_msg->dcb_idx);
    192             p_ccb->status = MCA_CCB_STAT_PENDING;
    193             /* set p_tx_req to block API_REQ/API_RSP before DL is up */
    194             mca_free_buf ((void **)&p_ccb->p_tx_req);
    195             p_ccb->p_tx_req = p_ccb->p_rx_msg;
    196             p_ccb->p_rx_msg = NULL;
    197             p_ccb->p_tx_req->dcb_idx = p_msg->dcb_idx;
    198         }
    199         mca_free_buf ((void **)&p_ccb->p_rx_msg);
    200         p_pkt->len = p - p_start;
    201         L2CA_DataWrite (p_ccb->lcid, p_pkt);
    202     }
    203 
    204 }
    205 
    206 /*******************************************************************************
    207 **
    208 ** Function         mca_ccb_do_disconn
    209 **
    210 ** Description      This function closes a control channel.
    211 **
    212 ** Returns          void.
    213 **
    214 *******************************************************************************/
    215 void mca_ccb_do_disconn (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    216 {
    217     UNUSED(p_data);
    218 
    219     mca_dcb_close_by_mdl_id (p_ccb, MCA_ALL_MDL_ID);
    220     L2CA_DisconnectReq(p_ccb->lcid);
    221 }
    222 
    223 /*******************************************************************************
    224 **
    225 ** Function         mca_ccb_cong
    226 **
    227 ** Description      This function sets the congestion state for the CCB.
    228 **
    229 ** Returns          void.
    230 **
    231 *******************************************************************************/
    232 void mca_ccb_cong(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    233 {
    234     MCA_TRACE_DEBUG ("mca_ccb_cong cong=%d/%d", p_ccb->cong, p_data->llcong);
    235     p_ccb->cong = p_data->llcong;
    236     if (!p_ccb->cong)
    237     {
    238         /* if there's a held packet, send it now */
    239         if (p_ccb->p_tx_req && !p_ccb->p_tx_req->hdr.layer_specific)
    240         {
    241             p_data = (tMCA_CCB_EVT *)p_ccb->p_tx_req;
    242             p_ccb->p_tx_req = NULL;
    243             mca_ccb_snd_req (p_ccb, p_data);
    244         }
    245     }
    246 }
    247 
    248 /*******************************************************************************
    249 **
    250 ** Function         mca_ccb_hdl_req
    251 **
    252 ** Description      This function is called when a MCAP request is received from
    253 **                  the peer. It calls the application callback function to
    254 **                  report the event.
    255 **
    256 ** Returns          void.
    257 **
    258 *******************************************************************************/
    259 void mca_ccb_hdl_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    260 {
    261     BT_HDR  *p_pkt = &p_data->hdr;
    262     BT_HDR  *p_buf;
    263     UINT8   *p, *p_start;
    264     tMCA_DCB    *p_dcb;
    265     tMCA_CTRL       evt_data;
    266     tMCA_CCB_MSG    *p_rx_msg = NULL;
    267     UINT8           reject_code = MCA_RSP_NO_RESOURCE;
    268     BOOLEAN         send_rsp = FALSE;
    269     BOOLEAN         check_req = FALSE;
    270     UINT8           reject_opcode;
    271 
    272     MCA_TRACE_DEBUG ("mca_ccb_hdl_req status:%d", p_ccb->status);
    273     p_rx_msg = (tMCA_CCB_MSG *)p_pkt;
    274     p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    275     evt_data.hdr.op_code = *p++;
    276     BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p);
    277     reject_opcode = evt_data.hdr.op_code+1;
    278 
    279     MCA_TRACE_DEBUG ("received mdl id: %d ", evt_data.hdr.mdl_id);
    280     if (p_ccb->status == MCA_CCB_STAT_PENDING)
    281     {
    282         MCA_TRACE_DEBUG ("received req inpending state");
    283         /* allow abort in pending state */
    284         if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (evt_data.hdr.op_code == MCA_OP_MDL_ABORT_REQ))
    285         {
    286             reject_code = MCA_RSP_SUCCESS;
    287             send_rsp = TRUE;
    288             /* clear the pending status */
    289             p_ccb->status = MCA_CCB_STAT_NORM;
    290             if (p_ccb->p_tx_req && ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx))!= NULL))
    291             {
    292                 mca_dcb_dealloc (p_dcb, NULL);
    293                 mca_free_buf ((void **)&p_ccb->p_tx_req);
    294             }
    295         }
    296         else
    297             reject_code = MCA_RSP_BAD_OP;
    298     }
    299     else if (p_ccb->p_rx_msg)
    300     {
    301         MCA_TRACE_DEBUG ("still handling prev req");
    302         /* still holding previous message, reject this new one ?? */
    303 
    304     }
    305     else if (p_ccb->p_tx_req)
    306     {
    307         MCA_TRACE_DEBUG ("still waiting for a response ctrl_vpsm:0x%x", p_ccb->ctrl_vpsm);
    308         /* sent a request; waiting for response */
    309         if (p_ccb->ctrl_vpsm == 0)
    310         {
    311             MCA_TRACE_DEBUG ("local is ACP. accept the cmd from INT");
    312             /* local is acceptor, need to handle the request */
    313             check_req = TRUE;
    314             reject_code = MCA_RSP_SUCCESS;
    315             /* drop the previous request */
    316             if ((p_ccb->p_tx_req->op_code == MCA_OP_MDL_CREATE_REQ) &&
    317                 ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL))
    318             {
    319                 mca_dcb_dealloc(p_dcb, NULL);
    320             }
    321             mca_free_buf ((void **)&p_ccb->p_tx_req);
    322             mca_stop_timer(p_ccb);
    323         }
    324         else
    325         {
    326             /*  local is initiator, ignore the req */
    327             GKI_freebuf (p_pkt);
    328             return;
    329         }
    330     }
    331     else if (p_pkt->layer_specific != MCA_RSP_SUCCESS)
    332     {
    333 
    334         reject_code = (UINT8)p_pkt->layer_specific;
    335         if (((evt_data.hdr.op_code >= MCA_NUM_STANDARD_OPCODE) &&
    336             (evt_data.hdr.op_code < MCA_FIRST_SYNC_OP)) ||
    337             (evt_data.hdr.op_code > MCA_LAST_SYNC_OP))
    338         {
    339             /* invalid op code */
    340             reject_opcode = MCA_OP_ERROR_RSP;
    341             evt_data.hdr.mdl_id = 0;
    342         }
    343     }
    344     else
    345     {
    346         check_req = TRUE;
    347         reject_code = MCA_RSP_SUCCESS;
    348     }
    349 
    350     if (check_req)
    351     {
    352         if (reject_code == MCA_RSP_SUCCESS)
    353         {
    354             reject_code = MCA_RSP_BAD_MDL;
    355             if (MCA_IS_VALID_MDL_ID(evt_data.hdr.mdl_id) ||
    356                 ((evt_data.hdr.mdl_id == MCA_ALL_MDL_ID) && (evt_data.hdr.op_code == MCA_OP_MDL_DELETE_REQ)))
    357             {
    358                 reject_code = MCA_RSP_SUCCESS;
    359                 /* mdl_id is valid according to the spec */
    360                 switch (evt_data.hdr.op_code)
    361                 {
    362                 case MCA_OP_MDL_CREATE_REQ:
    363                     evt_data.create_ind.dep_id = *p++;
    364                     evt_data.create_ind.cfg = *p++;
    365                     p_rx_msg->mdep_id = evt_data.create_ind.dep_id;
    366                     if (!mca_is_valid_dep_id(p_ccb->p_rcb, p_rx_msg->mdep_id))
    367                     {
    368                         MCA_TRACE_ERROR ("not a valid local mdep id");
    369                         reject_code = MCA_RSP_BAD_MDEP;
    370                     }
    371                     else if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id))
    372                     {
    373                         MCA_TRACE_DEBUG ("the mdl_id is currently used in the CL(create)");
    374                         mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id);
    375                     }
    376                     else
    377                     {
    378                         /* check if this dep still have MDL available */
    379                         if (mca_dep_free_mdl(p_ccb, evt_data.create_ind.dep_id) == 0)
    380                         {
    381                             MCA_TRACE_ERROR ("the mdep is currently using max_mdl");
    382                             reject_code = MCA_RSP_MDEP_BUSY;
    383                         }
    384                     }
    385                     break;
    386 
    387                 case MCA_OP_MDL_RECONNECT_REQ:
    388                     if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id))
    389                     {
    390                         MCA_TRACE_ERROR ("the mdl_id is currently used in the CL(reconn)");
    391                         reject_code = MCA_RSP_MDL_BUSY;
    392                     }
    393                     break;
    394 
    395                 case MCA_OP_MDL_ABORT_REQ:
    396                     reject_code = MCA_RSP_BAD_OP;
    397                     break;
    398 
    399                 case MCA_OP_MDL_DELETE_REQ:
    400                     /* delete the associated mdl */
    401                     mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id);
    402                     send_rsp = TRUE;
    403                     break;
    404                 }
    405             }
    406         }
    407     }
    408 
    409     if (((reject_code != MCA_RSP_SUCCESS) && (evt_data.hdr.op_code != MCA_OP_SYNC_INFO_IND))
    410         || send_rsp)
    411     {
    412         p_buf = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
    413         if (p_buf)
    414         {
    415             p_buf->offset = L2CAP_MIN_OFFSET;
    416             p = p_start = (UINT8*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    417             *p++ = reject_opcode;
    418             *p++ = reject_code;
    419             UINT16_TO_BE_STREAM (p, evt_data.hdr.mdl_id);
    420             /*
    421             if (((*p_start) == MCA_OP_MDL_CREATE_RSP) && (reject_code == MCA_RSP_SUCCESS))
    422             {
    423                 *p++ = evt_data.create_ind.cfg;
    424             }
    425             */
    426 
    427             p_buf->len = p - p_start;
    428             L2CA_DataWrite (p_ccb->lcid, p_buf);
    429         }
    430     }
    431 
    432     if (reject_code == MCA_RSP_SUCCESS)
    433     {
    434         /* use the received GKI buffer to store information to double check response API */
    435         p_rx_msg->op_code = evt_data.hdr.op_code;
    436         p_rx_msg->mdl_id = evt_data.hdr.mdl_id;
    437         p_ccb->p_rx_msg = p_rx_msg;
    438         if (send_rsp)
    439         {
    440             GKI_freebuf (p_pkt);
    441             p_ccb->p_rx_msg = NULL;
    442         }
    443         mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data);
    444     }
    445     else
    446         GKI_freebuf (p_pkt);
    447 }
    448 
    449 /*******************************************************************************
    450 **
    451 ** Function         mca_ccb_hdl_rsp
    452 **
    453 ** Description      This function is called when a MCAP response is received from
    454 **                  the peer.  It calls the application callback function with
    455 **                  the results.
    456 **
    457 ** Returns          void.
    458 **
    459 *******************************************************************************/
    460 void mca_ccb_hdl_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    461 {
    462     BT_HDR  *p_pkt = &p_data->hdr;
    463     UINT8   *p;
    464     tMCA_CTRL   evt_data;
    465     BOOLEAN     chk_mdl = FALSE;
    466     tMCA_DCB    *p_dcb;
    467     tMCA_RESULT result = MCA_BAD_HANDLE;
    468     tMCA_TC_TBL *p_tbl;
    469 
    470     if (p_ccb->p_tx_req)
    471     {
    472         /* verify that the received response matches the sent request */
    473         p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    474         evt_data.hdr.op_code = *p++;
    475         if ((evt_data.hdr.op_code == 0) ||
    476             ((p_ccb->p_tx_req->op_code + 1) == evt_data.hdr.op_code))
    477         {
    478             evt_data.rsp.rsp_code = *p++;
    479             mca_stop_timer(p_ccb);
    480             BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p);
    481             if (evt_data.hdr.op_code == MCA_OP_MDL_CREATE_RSP)
    482             {
    483                 evt_data.create_cfm.cfg = *p++;
    484                 chk_mdl = TRUE;
    485             }
    486             else if (evt_data.hdr.op_code == MCA_OP_MDL_RECONNECT_RSP)
    487                     chk_mdl = TRUE;
    488 
    489             if (chk_mdl)
    490             {
    491                 p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
    492                 if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
    493                 {
    494                     if (evt_data.hdr.mdl_id != p_dcb->mdl_id)
    495                     {
    496                         MCA_TRACE_ERROR ("peer's mdl_id=%d != our mdl_id=%d", evt_data.hdr.mdl_id, p_dcb->mdl_id);
    497                         /* change the response code to be an error */
    498                         if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
    499                         {
    500                             evt_data.rsp.rsp_code = MCA_RSP_BAD_MDL;
    501                             /* send Abort */
    502                             p_ccb->status = MCA_CCB_STAT_PENDING;
    503                             MCA_Abort(mca_ccb_to_hdl(p_ccb));
    504                         }
    505                     }
    506                     else if (p_dcb->p_chnl_cfg)
    507                     {
    508                         /* the data channel configuration is known. Proceed with data channel initiation */
    509                         BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask,
    510                             p_ccb->data_vpsm, BTM_SEC_PROTO_MCA, p_ccb->p_tx_req->dcb_idx);
    511                         p_dcb->lcid = mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm, p_dcb->p_chnl_cfg);
    512                         if (p_dcb->lcid)
    513                         {
    514                             p_tbl = mca_tc_tbl_dalloc(p_dcb);
    515                             if (p_tbl)
    516                             {
    517                                 p_tbl->state = MCA_TC_ST_CONN;
    518                                 p_ccb->status = MCA_CCB_STAT_PENDING;
    519                                 result = MCA_SUCCESS;
    520                             }
    521                         }
    522                     }
    523                     else
    524                     {
    525                         /* mark this MCL as pending and wait for MCA_DataChnlCfg */
    526                         p_ccb->status = MCA_CCB_STAT_PENDING;
    527                         result = MCA_SUCCESS;
    528                     }
    529                 }
    530 
    531                 if (result != MCA_SUCCESS && p_dcb)
    532                 {
    533                     mca_dcb_dealloc(p_dcb, NULL);
    534                 }
    535             } /* end of chk_mdl */
    536 
    537             if (p_ccb->status != MCA_CCB_STAT_PENDING)
    538                 mca_free_buf ((void **)&p_ccb->p_tx_req);
    539             mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data);
    540         }
    541         /* else a bad response is received */
    542     }
    543     else
    544     {
    545         /* not expecting any response. drop it */
    546         MCA_TRACE_WARNING ("dropping received rsp (not expecting a response)");
    547     }
    548     GKI_freebuf (p_data);
    549 }
    550 
    551 /*******************************************************************************
    552 **
    553 ** Function         mca_ccb_ll_open
    554 **
    555 ** Description      This function is called to report MCA_CONNECT_IND_EVT event.
    556 **                  It also clears the congestion flag (ccb.cong).
    557 **
    558 ** Returns          void.
    559 **
    560 *******************************************************************************/
    561 void mca_ccb_ll_open (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    562 {
    563     tMCA_CTRL    evt_data;
    564     p_ccb->cong  = FALSE;
    565     evt_data.connect_ind.mtu = p_data->open.peer_mtu;
    566     memcpy (evt_data.connect_ind.bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
    567     mca_ccb_report_event (p_ccb, MCA_CONNECT_IND_EVT, &evt_data);
    568 }
    569 
    570 /*******************************************************************************
    571 **
    572 ** Function         mca_ccb_dl_open
    573 **
    574 ** Description      This function is called when data channel is open.
    575 **                  It clears p_tx_req to allow other message exchage on this CL.
    576 **
    577 ** Returns          void.
    578 **
    579 *******************************************************************************/
    580 void mca_ccb_dl_open (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    581 {
    582     UNUSED(p_data);
    583 
    584     mca_free_buf ((void **)&p_ccb->p_tx_req);
    585     mca_free_buf ((void **)&p_ccb->p_rx_msg);
    586     p_ccb->status = MCA_CCB_STAT_NORM;
    587 }
    588 
    589