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