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     tMCA_DCB    *p_dcb;
    169 
    170     MCA_TRACE_DEBUG ("mca_ccb_snd_rsp cong=%d req=%d", p_ccb->cong, p_msg->op_code);
    171     /* assume that API functions verified the parameters */
    172     p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
    173     if (p_pkt)
    174     {
    175         p_pkt->offset = L2CAP_MIN_OFFSET;
    176         p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
    177         *p++ = p_msg->op_code;
    178         *p++ = p_msg->rsp_code;
    179         UINT16_TO_BE_STREAM (p, p_msg->mdl_id);
    180         if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP)
    181         {
    182             *p++ = p_msg->param;
    183             chk_mdl = TRUE;
    184         }
    185         else if (p_msg->op_code == MCA_OP_MDL_RECONNECT_RSP)
    186                 chk_mdl = TRUE;
    187 
    188         if (chk_mdl && p_msg->rsp_code == MCA_RSP_SUCCESS)
    189         {
    190             p_dcb = mca_dcb_by_hdl(p_msg->dcb_idx);
    191             BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask,
    192                 p_ccb->p_rcb->reg.data_psm, BTM_SEC_PROTO_MCA, p_msg->dcb_idx);
    193             p_ccb->status = MCA_CCB_STAT_PENDING;
    194             /* set p_tx_req to block API_REQ/API_RSP before DL is up */
    195             mca_free_buf ((void **)&p_ccb->p_tx_req);
    196             p_ccb->p_tx_req = p_ccb->p_rx_msg;
    197             p_ccb->p_rx_msg = NULL;
    198             p_ccb->p_tx_req->dcb_idx = p_msg->dcb_idx;
    199         }
    200         mca_free_buf ((void **)&p_ccb->p_rx_msg);
    201         p_pkt->len = p - p_start;
    202         L2CA_DataWrite (p_ccb->lcid, p_pkt);
    203     }
    204 
    205 }
    206 
    207 /*******************************************************************************
    208 **
    209 ** Function         mca_ccb_do_disconn
    210 **
    211 ** Description      This function closes a control channel.
    212 **
    213 ** Returns          void.
    214 **
    215 *******************************************************************************/
    216 void mca_ccb_do_disconn (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    217 {
    218     UNUSED(p_data);
    219 
    220     mca_dcb_close_by_mdl_id (p_ccb, MCA_ALL_MDL_ID);
    221     L2CA_DisconnectReq(p_ccb->lcid);
    222 }
    223 
    224 /*******************************************************************************
    225 **
    226 ** Function         mca_ccb_cong
    227 **
    228 ** Description      This function sets the congestion state for the CCB.
    229 **
    230 ** Returns          void.
    231 **
    232 *******************************************************************************/
    233 void mca_ccb_cong(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    234 {
    235     MCA_TRACE_DEBUG ("mca_ccb_cong cong=%d/%d", p_ccb->cong, p_data->llcong);
    236     p_ccb->cong = p_data->llcong;
    237     if (!p_ccb->cong)
    238     {
    239         /* if there's a held packet, send it now */
    240         if (p_ccb->p_tx_req && !p_ccb->p_tx_req->hdr.layer_specific)
    241         {
    242             p_data = (tMCA_CCB_EVT *)p_ccb->p_tx_req;
    243             p_ccb->p_tx_req = NULL;
    244             mca_ccb_snd_req (p_ccb, p_data);
    245         }
    246     }
    247 }
    248 
    249 /*******************************************************************************
    250 **
    251 ** Function         mca_ccb_hdl_req
    252 **
    253 ** Description      This function is called when a MCAP request is received from
    254 **                  the peer. It calls the application callback function to
    255 **                  report the event.
    256 **
    257 ** Returns          void.
    258 **
    259 *******************************************************************************/
    260 void mca_ccb_hdl_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    261 {
    262     BT_HDR  *p_pkt = &p_data->hdr;
    263     BT_HDR  *p_buf;
    264     UINT8   *p, *p_start;
    265     tMCA_DCB    *p_dcb;
    266     tMCA_CTRL       evt_data;
    267     tMCA_CCB_MSG    *p_rx_msg = NULL;
    268     UINT8           reject_code = MCA_RSP_NO_RESOURCE;
    269     BOOLEAN         send_rsp = FALSE;
    270     BOOLEAN         check_req = FALSE;
    271     UINT8           reject_opcode;
    272 
    273     MCA_TRACE_DEBUG ("mca_ccb_hdl_req status:%d", p_ccb->status);
    274     p_rx_msg = (tMCA_CCB_MSG *)p_pkt;
    275     p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    276     evt_data.hdr.op_code = *p++;
    277     BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p);
    278     reject_opcode = evt_data.hdr.op_code+1;
    279 
    280     MCA_TRACE_DEBUG ("received mdl id: %d ", evt_data.hdr.mdl_id);
    281     if (p_ccb->status == MCA_CCB_STAT_PENDING)
    282     {
    283         MCA_TRACE_DEBUG ("received req inpending state");
    284         /* allow abort in pending state */
    285         if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (evt_data.hdr.op_code == MCA_OP_MDL_ABORT_REQ))
    286         {
    287             reject_code = MCA_RSP_SUCCESS;
    288             send_rsp = TRUE;
    289             /* clear the pending status */
    290             p_ccb->status = MCA_CCB_STAT_NORM;
    291             if (p_ccb->p_tx_req && ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx))!= NULL))
    292             {
    293                 mca_dcb_dealloc (p_dcb, NULL);
    294                 mca_free_buf ((void **)&p_ccb->p_tx_req);
    295             }
    296         }
    297         else
    298             reject_code = MCA_RSP_BAD_OP;
    299     }
    300     else if (p_ccb->p_rx_msg)
    301     {
    302         MCA_TRACE_DEBUG ("still handling prev req");
    303         /* still holding previous message, reject this new one ?? */
    304 
    305     }
    306     else if (p_ccb->p_tx_req)
    307     {
    308         MCA_TRACE_DEBUG ("still waiting for a response ctrl_vpsm:0x%x", p_ccb->ctrl_vpsm);
    309         /* sent a request; waiting for response */
    310         if (p_ccb->ctrl_vpsm == 0)
    311         {
    312             MCA_TRACE_DEBUG ("local is ACP. accept the cmd from INT");
    313             /* local is acceptor, need to handle the request */
    314             check_req = TRUE;
    315             reject_code = MCA_RSP_SUCCESS;
    316             /* drop the previous request */
    317             if ((p_ccb->p_tx_req->op_code == MCA_OP_MDL_CREATE_REQ) &&
    318                 ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL))
    319             {
    320                 mca_dcb_dealloc(p_dcb, NULL);
    321             }
    322             mca_free_buf ((void **)&p_ccb->p_tx_req);
    323             mca_stop_timer(p_ccb);
    324         }
    325         else
    326         {
    327             /*  local is initiator, ignore the req */
    328             GKI_freebuf (p_pkt);
    329             return;
    330         }
    331     }
    332     else if (p_pkt->layer_specific != MCA_RSP_SUCCESS)
    333     {
    334 
    335         reject_code = (UINT8)p_pkt->layer_specific;
    336         if (((evt_data.hdr.op_code >= MCA_NUM_STANDARD_OPCODE) &&
    337             (evt_data.hdr.op_code < MCA_FIRST_SYNC_OP)) ||
    338             (evt_data.hdr.op_code > MCA_LAST_SYNC_OP))
    339         {
    340             /* invalid op code */
    341             reject_opcode = MCA_OP_ERROR_RSP;
    342             evt_data.hdr.mdl_id = 0;
    343         }
    344     }
    345     else
    346     {
    347         check_req = TRUE;
    348         reject_code = MCA_RSP_SUCCESS;
    349     }
    350 
    351     if (check_req)
    352     {
    353         if (reject_code == MCA_RSP_SUCCESS)
    354         {
    355             reject_code = MCA_RSP_BAD_MDL;
    356             if (MCA_IS_VALID_MDL_ID(evt_data.hdr.mdl_id) ||
    357                 ((evt_data.hdr.mdl_id == MCA_ALL_MDL_ID) && (evt_data.hdr.op_code == MCA_OP_MDL_DELETE_REQ)))
    358             {
    359                 reject_code = MCA_RSP_SUCCESS;
    360                 /* mdl_id is valid according to the spec */
    361                 switch (evt_data.hdr.op_code)
    362                 {
    363                 case MCA_OP_MDL_CREATE_REQ:
    364                     evt_data.create_ind.dep_id = *p++;
    365                     evt_data.create_ind.cfg = *p++;
    366                     p_rx_msg->mdep_id = evt_data.create_ind.dep_id;
    367                     if (!mca_is_valid_dep_id(p_ccb->p_rcb, p_rx_msg->mdep_id))
    368                     {
    369                         MCA_TRACE_ERROR ("not a valid local mdep id");
    370                         reject_code = MCA_RSP_BAD_MDEP;
    371                     }
    372                     else if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id))
    373                     {
    374                         MCA_TRACE_DEBUG ("the mdl_id is currently used in the CL(create)");
    375                         mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id);
    376                     }
    377                     else
    378                     {
    379                         /* check if this dep still have MDL available */
    380                         if (mca_dep_free_mdl(p_ccb, evt_data.create_ind.dep_id) == 0)
    381                         {
    382                             MCA_TRACE_ERROR ("the mdep is currently using max_mdl");
    383                             reject_code = MCA_RSP_MDEP_BUSY;
    384                         }
    385                     }
    386                     break;
    387 
    388                 case MCA_OP_MDL_RECONNECT_REQ:
    389                     if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id))
    390                     {
    391                         MCA_TRACE_ERROR ("the mdl_id is currently used in the CL(reconn)");
    392                         reject_code = MCA_RSP_MDL_BUSY;
    393                     }
    394                     break;
    395 
    396                 case MCA_OP_MDL_ABORT_REQ:
    397                     reject_code = MCA_RSP_BAD_OP;
    398                     break;
    399 
    400                 case MCA_OP_MDL_DELETE_REQ:
    401                     /* delete the associated mdl */
    402                     mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id);
    403                     send_rsp = TRUE;
    404                     break;
    405                 }
    406             }
    407         }
    408     }
    409 
    410     if (((reject_code != MCA_RSP_SUCCESS) && (evt_data.hdr.op_code != MCA_OP_SYNC_INFO_IND))
    411         || send_rsp)
    412     {
    413         p_buf = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU);
    414         if (p_buf)
    415         {
    416             p_buf->offset = L2CAP_MIN_OFFSET;
    417             p = p_start = (UINT8*)(p_buf + 1) + L2CAP_MIN_OFFSET;
    418             *p++ = reject_opcode;
    419             *p++ = reject_code;
    420             UINT16_TO_BE_STREAM (p, evt_data.hdr.mdl_id);
    421             /*
    422             if (((*p_start) == MCA_OP_MDL_CREATE_RSP) && (reject_code == MCA_RSP_SUCCESS))
    423             {
    424                 *p++ = evt_data.create_ind.cfg;
    425             }
    426             */
    427 
    428             p_buf->len = p - p_start;
    429             L2CA_DataWrite (p_ccb->lcid, p_buf);
    430         }
    431     }
    432 
    433     if (reject_code == MCA_RSP_SUCCESS)
    434     {
    435         /* use the received GKI buffer to store information to double check response API */
    436         p_rx_msg->op_code = evt_data.hdr.op_code;
    437         p_rx_msg->mdl_id = evt_data.hdr.mdl_id;
    438         p_ccb->p_rx_msg = p_rx_msg;
    439         if (send_rsp)
    440         {
    441             GKI_freebuf (p_pkt);
    442             p_ccb->p_rx_msg = NULL;
    443         }
    444         mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data);
    445     }
    446     else
    447         GKI_freebuf (p_pkt);
    448 }
    449 
    450 /*******************************************************************************
    451 **
    452 ** Function         mca_ccb_hdl_rsp
    453 **
    454 ** Description      This function is called when a MCAP response is received from
    455 **                  the peer.  It calls the application callback function with
    456 **                  the results.
    457 **
    458 ** Returns          void.
    459 **
    460 *******************************************************************************/
    461 void mca_ccb_hdl_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    462 {
    463     BT_HDR  *p_pkt = &p_data->hdr;
    464     UINT8   *p;
    465     tMCA_CTRL   evt_data;
    466     BOOLEAN     chk_mdl = FALSE;
    467     tMCA_DCB    *p_dcb;
    468     tMCA_RESULT result = MCA_BAD_HANDLE;
    469     tMCA_TC_TBL *p_tbl;
    470 
    471     if (p_ccb->p_tx_req)
    472     {
    473         /* verify that the received response matches the sent request */
    474         p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    475         evt_data.hdr.op_code = *p++;
    476         if ((evt_data.hdr.op_code == 0) ||
    477             ((p_ccb->p_tx_req->op_code + 1) == evt_data.hdr.op_code))
    478         {
    479             evt_data.rsp.rsp_code = *p++;
    480             mca_stop_timer(p_ccb);
    481             BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p);
    482             if (evt_data.hdr.op_code == MCA_OP_MDL_CREATE_RSP)
    483             {
    484                 evt_data.create_cfm.cfg = *p++;
    485                 chk_mdl = TRUE;
    486             }
    487             else if (evt_data.hdr.op_code == MCA_OP_MDL_RECONNECT_RSP)
    488                     chk_mdl = TRUE;
    489 
    490             if (chk_mdl)
    491             {
    492                 p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx);
    493                 if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
    494                 {
    495                     if (evt_data.hdr.mdl_id != p_dcb->mdl_id)
    496                     {
    497                         MCA_TRACE_ERROR ("peer's mdl_id=%d != our mdl_id=%d", evt_data.hdr.mdl_id, p_dcb->mdl_id);
    498                         /* change the response code to be an error */
    499                         if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS)
    500                         {
    501                             evt_data.rsp.rsp_code = MCA_RSP_BAD_MDL;
    502                             /* send Abort */
    503                             p_ccb->status = MCA_CCB_STAT_PENDING;
    504                             MCA_Abort(mca_ccb_to_hdl(p_ccb));
    505                         }
    506                     }
    507                     else if (p_dcb->p_chnl_cfg)
    508                     {
    509                         /* the data channel configuration is known. Proceed with data channel initiation */
    510                         BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask,
    511                             p_ccb->data_vpsm, BTM_SEC_PROTO_MCA, p_ccb->p_tx_req->dcb_idx);
    512                         p_dcb->lcid = mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm, p_dcb->p_chnl_cfg);
    513                         if (p_dcb->lcid)
    514                         {
    515                             p_tbl = mca_tc_tbl_dalloc(p_dcb);
    516                             if (p_tbl)
    517                             {
    518                                 p_tbl->state = MCA_TC_ST_CONN;
    519                                 p_ccb->status = MCA_CCB_STAT_PENDING;
    520                                 result = MCA_SUCCESS;
    521                             }
    522                         }
    523                     }
    524                     else
    525                     {
    526                         /* mark this MCL as pending and wait for MCA_DataChnlCfg */
    527                         p_ccb->status = MCA_CCB_STAT_PENDING;
    528                         result = MCA_SUCCESS;
    529                     }
    530                 }
    531 
    532                 if (result != MCA_SUCCESS && p_dcb)
    533                 {
    534                     mca_dcb_dealloc(p_dcb, NULL);
    535                 }
    536             } /* end of chk_mdl */
    537 
    538             if (p_ccb->status != MCA_CCB_STAT_PENDING)
    539                 mca_free_buf ((void **)&p_ccb->p_tx_req);
    540             mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data);
    541         }
    542         /* else a bad response is received */
    543     }
    544     else
    545     {
    546         /* not expecting any response. drop it */
    547         MCA_TRACE_WARNING ("dropping received rsp (not expecting a response)");
    548     }
    549     GKI_freebuf (p_data);
    550 }
    551 
    552 /*******************************************************************************
    553 **
    554 ** Function         mca_ccb_ll_open
    555 **
    556 ** Description      This function is called to report MCA_CONNECT_IND_EVT event.
    557 **                  It also clears the congestion flag (ccb.cong).
    558 **
    559 ** Returns          void.
    560 **
    561 *******************************************************************************/
    562 void mca_ccb_ll_open (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    563 {
    564     tMCA_CTRL    evt_data;
    565     p_ccb->cong  = FALSE;
    566     evt_data.connect_ind.mtu = p_data->open.peer_mtu;
    567     memcpy (evt_data.connect_ind.bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
    568     mca_ccb_report_event (p_ccb, MCA_CONNECT_IND_EVT, &evt_data);
    569 }
    570 
    571 /*******************************************************************************
    572 **
    573 ** Function         mca_ccb_dl_open
    574 **
    575 ** Description      This function is called when data channel is open.
    576 **                  It clears p_tx_req to allow other message exchage on this CL.
    577 **
    578 ** Returns          void.
    579 **
    580 *******************************************************************************/
    581 void mca_ccb_dl_open (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data)
    582 {
    583     UNUSED(p_data);
    584 
    585     mca_free_buf ((void **)&p_ccb->p_tx_req);
    586     mca_free_buf ((void **)&p_ccb->p_rx_msg);
    587     p_ccb->status = MCA_CCB_STAT_NORM;
    588 }
    589 
    590