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