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