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