OSDN Git Service

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