1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-2016 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 * Name: avct_bcb_act.cc 22 * 23 * Description: This module contains action functions of the browsing control 24 * state machine. 25 * 26 *****************************************************************************/ 27 28 #include <string.h> 29 #include "avct_api.h" 30 #include "avct_int.h" 31 #include "bt_target.h" 32 #include "bt_utils.h" 33 #include "btm_api.h" 34 #include "osi/include/osi.h" 35 36 /* action function list */ 37 const tAVCT_BCB_ACTION avct_bcb_action[] = { 38 avct_bcb_chnl_open, /* AVCT_LCB_CHNL_OPEN */ 39 avct_bcb_chnl_disc, /* AVCT_LCB_CHNL_DISC */ 40 avct_bcb_send_msg, /* AVCT_LCB_SEND_MSG */ 41 avct_bcb_open_ind, /* AVCT_LCB_OPEN_IND */ 42 avct_bcb_open_fail, /* AVCT_LCB_OPEN_FAIL */ 43 avct_bcb_close_ind, /* AVCT_LCB_CLOSE_IND */ 44 avct_bcb_close_cfm, /* AVCT_LCB_CLOSE_CFM */ 45 avct_bcb_msg_ind, /* AVCT_LCB_MSG_IND */ 46 avct_bcb_cong_ind, /* AVCT_LCB_CONG_IND */ 47 avct_bcb_bind_conn, /* AVCT_LCB_BIND_CONN */ 48 avct_bcb_bind_fail, /* AVCT_LCB_BIND_FAIL */ 49 avct_bcb_unbind_disc, /* AVCT_LCB_UNBIND_DISC */ 50 avct_bcb_chk_disc, /* AVCT_LCB_CHK_DISC */ 51 avct_bcb_discard_msg, /* AVCT_LCB_DISCARD_MSG */ 52 avct_bcb_dealloc, /* AVCT_LCB_DEALLOC */ 53 avct_bcb_free_msg_ind /* AVCT_LCB_FREE_MSG_IND */ 54 }; 55 56 /******************************************************************************* 57 * 58 * Function avct_bcb_msg_asmbl 59 * 60 * Description Reassemble incoming message. 61 * 62 * 63 * Returns Pointer to reassembled message; NULL if no message 64 * available. 65 * 66 ******************************************************************************/ 67 static BT_HDR* avct_bcb_msg_asmbl(UNUSED_ATTR tAVCT_BCB* p_bcb, BT_HDR* p_buf) { 68 uint8_t* p; 69 uint8_t pkt_type; 70 71 /* parse the message header */ 72 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 73 pkt_type = AVCT_PKT_TYPE(p); 74 75 /* must be single packet - can not fragment */ 76 if (pkt_type != AVCT_PKT_TYPE_SINGLE) { 77 osi_free_and_reset((void**)&p_buf); 78 AVCT_TRACE_WARNING("Pkt type=%d - fragmentation not allowed. drop it", 79 pkt_type); 80 } 81 return p_buf; 82 } 83 84 /******************************************************************************* 85 * 86 * Function avct_bcb_chnl_open 87 * 88 * Description Open L2CAP channel to peer 89 * 90 * 91 * Returns Nothing. 92 * 93 ******************************************************************************/ 94 void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 95 uint16_t result = AVCT_RESULT_FAIL; 96 tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); 97 tL2CAP_ERTM_INFO ertm_info; 98 99 BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP_BROWSE, 0); 100 101 /* Set the FCR options: Browsing channel mandates ERTM */ 102 ertm_info.preferred_mode = avct_l2c_br_fcr_opts_def.mode; 103 ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM; 104 ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE; 105 ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE; 106 ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE; 107 ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE; 108 109 /* call l2cap connect req */ 110 p_bcb->ch_state = AVCT_CH_CONN; 111 p_bcb->ch_lcid = 112 L2CA_ErtmConnectReq(AVCT_BR_PSM, p_lcb->peer_addr, &ertm_info); 113 if (p_bcb->ch_lcid == 0) { 114 /* if connect req failed, send ourselves close event */ 115 avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result); 116 } 117 } 118 119 /******************************************************************************* 120 * 121 * Function avct_bcb_unbind_disc 122 * 123 * Description call callback with disconnect event. 124 * 125 * 126 * Returns Nothing. 127 * 128 ******************************************************************************/ 129 void avct_bcb_unbind_disc(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 130 p_data->p_ccb->p_bcb = NULL; 131 (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb), 132 AVCT_BROWSE_DISCONN_CFM_EVT, 0, NULL); 133 } 134 135 /******************************************************************************* 136 * 137 * Function avct_bcb_open_ind 138 * 139 * Description Handle an LL_OPEN event. 140 * For the allocated ccb already bound to the bcb, send a 141 * connect event. For the unbound ccb with a new PID, bind that 142 * ccb to the bcb with the same bd_addr and send a connect 143 * event. 144 * 145 * 146 * Returns Nothing. 147 * 148 ******************************************************************************/ 149 void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 150 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 151 tAVCT_CCB* p_ccb_bind = NULL; 152 bool bind = false; 153 tAVCT_UL_MSG ul_msg; 154 155 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 156 /* if ccb allocated and */ 157 if (p_ccb->allocated) { 158 /* if bound to this bcb send connect confirm event */ 159 if (p_ccb->p_bcb == p_bcb) { 160 bind = true; 161 p_ccb_bind = p_ccb; 162 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT, 163 0, p_ccb->p_lcb->peer_addr); 164 } 165 /* if unbound acceptor and lcb allocated and bd_addr are the same for bcb 166 and lcb */ 167 else if ((p_ccb->p_bcb == NULL) && (p_ccb->cc.role == AVCT_ACP) && 168 (p_ccb->p_lcb != NULL) && 169 (!memcmp(p_bcb->peer_addr, p_ccb->p_lcb->peer_addr, 170 BD_ADDR_LEN))) { 171 /* bind bcb to ccb and send connect ind event */ 172 bind = true; 173 p_ccb_bind = p_ccb; 174 p_ccb->p_bcb = p_bcb; 175 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_IND_EVT, 176 0, p_ccb->p_lcb->peer_addr); 177 } 178 } 179 } 180 181 /* if no ccbs bound to this lcb, disconnect */ 182 if (bind == false) { 183 avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data); 184 return; 185 } 186 187 if (!p_bcb->p_tx_msg || !p_ccb_bind) { 188 return; 189 } 190 191 ul_msg.p_buf = p_bcb->p_tx_msg; 192 ul_msg.p_ccb = p_ccb_bind; 193 ul_msg.label = (uint8_t)(p_bcb->p_tx_msg->layer_specific & 0xFF); 194 ul_msg.cr = (uint8_t)((p_bcb->p_tx_msg->layer_specific & 0xFF00) >> 8); 195 p_bcb->p_tx_msg->layer_specific = AVCT_DATA_BROWSE; 196 p_bcb->p_tx_msg = NULL; 197 198 /* send msg event to bcb */ 199 avct_bcb_event(p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT*)&ul_msg); 200 } 201 202 /******************************************************************************* 203 * 204 * Function avct_bcb_open_fail 205 * 206 * Description L2CAP channel open attempt failed. Mark the ccbs 207 * as NULL bcb. 208 * 209 * 210 * Returns Nothing. 211 * 212 ******************************************************************************/ 213 void avct_bcb_open_fail(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 214 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 215 216 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 217 if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { 218 p_ccb->p_bcb = NULL; 219 } 220 } 221 } 222 223 /******************************************************************************* 224 * 225 * Function avct_bcb_close_ind 226 * 227 * Description L2CAP channel closed by peer. Deallocate any initiator 228 * ccbs on this lcb and send disconnect ind event. 229 * 230 * 231 * Returns Nothing. 232 * 233 ******************************************************************************/ 234 void avct_bcb_close_ind(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 235 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 236 tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); 237 238 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 239 if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { 240 if (p_ccb->cc.role == AVCT_INT) { 241 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), 242 AVCT_BROWSE_DISCONN_CFM_EVT, 0, 243 p_lcb->peer_addr); 244 } else { 245 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), 246 AVCT_BROWSE_DISCONN_IND_EVT, 0, NULL); 247 } 248 p_ccb->p_bcb = NULL; 249 } 250 } 251 } 252 253 /******************************************************************************* 254 * 255 * Function avct_bcb_close_cfm 256 * 257 * Description L2CAP channel closed by us. Deallocate any initiator 258 * ccbs on this lcb and send disconnect ind or cfm event. 259 * 260 * 261 * Returns Nothing. 262 * 263 ******************************************************************************/ 264 void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 265 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 266 uint8_t event = 0; 267 /* Whether BCB initiated channel close */ 268 bool ch_close = p_bcb->ch_close; 269 tAVCT_CTRL_CBACK* p_cback; 270 271 p_bcb->ch_close = false; 272 p_bcb->allocated = 0; 273 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 274 if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { 275 /* if this ccb initiated close send disconnect cfm otherwise ind */ 276 if (ch_close) { 277 event = AVCT_BROWSE_DISCONN_CFM_EVT; 278 } else { 279 event = AVCT_BROWSE_DISCONN_IND_EVT; 280 } 281 282 p_cback = p_ccb->cc.p_ctrl_cback; 283 p_ccb->p_bcb = NULL; 284 if (p_ccb->p_lcb == NULL) avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL); 285 (*p_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result, 286 p_bcb->peer_addr); 287 } 288 } 289 } 290 291 /******************************************************************************* 292 * 293 * Function avct_bcb_bind_conn 294 * 295 * Description Bind ccb to lcb and send connect cfm event. 296 * 297 * 298 * Returns Nothing. 299 * 300 ******************************************************************************/ 301 void avct_bcb_bind_conn(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 302 tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); 303 p_data->p_ccb->p_bcb = p_bcb; 304 (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb), 305 AVCT_BROWSE_CONN_CFM_EVT, 0, 306 p_lcb->peer_addr); 307 } 308 309 /******************************************************************************* 310 * 311 * Function avct_bcb_chk_disc 312 * 313 * Description A ccb wants to close; if it is the last ccb on this lcb, 314 * close channel. Otherwise just deallocate and call 315 * callback. 316 * 317 * 318 * Returns Nothing. 319 * 320 ******************************************************************************/ 321 void avct_bcb_chk_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 322 p_bcb->ch_close = avct_bcb_get_last_ccb_index(p_bcb, p_data->p_ccb); 323 if (p_bcb->ch_close) { 324 avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data); 325 return; 326 } 327 328 avct_bcb_unbind_disc(p_bcb, p_data); 329 } 330 331 /******************************************************************************* 332 * 333 * Function avct_bcb_chnl_disc 334 * 335 * Description Disconnect L2CAP channel. 336 * 337 * 338 * Returns Nothing. 339 * 340 ******************************************************************************/ 341 void avct_bcb_chnl_disc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 342 L2CA_DisconnectReq(p_bcb->ch_lcid); 343 } 344 345 /******************************************************************************* 346 * 347 * Function avct_bcb_bind_fail 348 * 349 * Description Deallocate ccb and call callback with connect event 350 * with failure result. 351 * 352 * 353 * Returns Nothing. 354 * 355 ******************************************************************************/ 356 void avct_bcb_bind_fail(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 357 p_data->p_ccb->p_bcb = NULL; 358 (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb), 359 AVCT_BROWSE_CONN_CFM_EVT, AVCT_RESULT_FAIL, 360 NULL); 361 } 362 363 /******************************************************************************* 364 * 365 * Function avct_bcb_cong_ind 366 * 367 * Description Handle congestion indication from L2CAP. 368 * 369 * 370 * Returns Nothing. 371 * 372 ******************************************************************************/ 373 void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 374 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 375 uint8_t event; 376 tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); 377 378 /* set event */ 379 event = 380 (p_data->cong) ? AVCT_BROWSE_CONG_IND_EVT : AVCT_BROWSE_UNCONG_IND_EVT; 381 382 /* send event to all ccbs on this lcb */ 383 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 384 if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { 385 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, 386 p_lcb->peer_addr); 387 } 388 } 389 } 390 391 /******************************************************************************* 392 * 393 * Function avct_bcb_discard_msg 394 * 395 * Description Discard a message sent in from the API. 396 * 397 * 398 * Returns Nothing. 399 * 400 ******************************************************************************/ 401 void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 402 osi_free_and_reset((void**)&p_bcb->p_tx_msg); 403 404 /* if control channel is up, save the message and open the browsing channel */ 405 if (p_data->ul_msg.p_ccb->p_lcb == NULL) { 406 osi_free_and_reset((void**)&p_data->ul_msg.p_buf); 407 return; 408 } 409 p_bcb->p_tx_msg = p_data->ul_msg.p_buf; 410 411 if (p_bcb->p_tx_msg) { 412 p_bcb->p_tx_msg->layer_specific = 413 (p_data->ul_msg.cr << 8) + p_data->ul_msg.label; 414 415 /* the channel is closed, opening or closing - open it again */ 416 AVCT_TRACE_DEBUG("ch_state: %d, allocated:%d->%d", p_bcb->ch_state, 417 p_bcb->allocated, p_data->ul_msg.p_ccb->p_lcb->allocated); 418 p_bcb->allocated = p_data->ul_msg.p_ccb->p_lcb->allocated; 419 avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, 420 (tAVCT_LCB_EVT*)p_data->ul_msg.p_ccb); 421 } 422 } 423 424 /******************************************************************************* 425 * 426 * Function avct_bcb_send_msg 427 * 428 * Description Build and send an AVCTP message. 429 * 430 * 431 * Returns Nothing. 432 * 433 ******************************************************************************/ 434 void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 435 uint16_t curr_msg_len; 436 uint8_t pkt_type = AVCT_PKT_TYPE_SINGLE; 437 uint8_t hdr_len; 438 BT_HDR* p_buf; 439 uint8_t* p; 440 441 /* store msg len */ 442 curr_msg_len = p_data->ul_msg.p_buf->len; 443 444 /* initialize packet type and other stuff */ 445 if (curr_msg_len > (p_bcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) { 446 AVCT_TRACE_ERROR("%s msg len (%d) exceeds peer mtu(%d-%d)!!", __func__, 447 curr_msg_len, p_bcb->peer_mtu, AVCT_HDR_LEN_SINGLE); 448 osi_free_and_reset((void**)&p_data->ul_msg.p_buf); 449 return; 450 } 451 452 /* set header len */ 453 hdr_len = avct_lcb_pkt_type_len[pkt_type]; 454 p_buf = p_data->ul_msg.p_buf; 455 456 /* set up to build header */ 457 p_buf->len += hdr_len; 458 p_buf->offset -= hdr_len; 459 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 460 461 /* build header */ 462 AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr); 463 UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid); 464 465 p_buf->layer_specific = AVCT_DATA_BROWSE; 466 467 /* send message to L2CAP */ 468 L2CA_DataWrite(p_bcb->ch_lcid, p_buf); 469 } 470 471 /******************************************************************************* 472 * 473 * Function avct_bcb_free_msg_ind 474 * 475 * Description Discard an incoming AVCTP message. 476 * 477 * 478 * Returns Nothing. 479 * 480 ******************************************************************************/ 481 void avct_bcb_free_msg_ind(UNUSED_ATTR tAVCT_BCB* p_bcb, 482 tAVCT_LCB_EVT* p_data) { 483 if (p_data) osi_free_and_reset((void**)&p_data->p_buf); 484 } 485 486 /******************************************************************************* 487 * 488 * Function avct_bcb_msg_ind 489 * 490 * Description Handle an incoming AVCTP message. 491 * 492 * 493 * Returns Nothing. 494 * 495 ******************************************************************************/ 496 void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { 497 uint8_t* p; 498 uint8_t label, type, cr_ipid; 499 uint16_t pid; 500 tAVCT_CCB* p_ccb; 501 tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); 502 503 if ((p_data == NULL) || (p_data->p_buf == NULL)) { 504 AVCT_TRACE_WARNING("%s p_data is NULL, returning!", __func__); 505 return; 506 } 507 508 /* this p_buf is to be reported through p_msg_cback. The layer_specific 509 * needs to be set properly to indicate that it is received through 510 * browsing channel */ 511 p_data->p_buf->layer_specific = AVCT_DATA_BROWSE; 512 513 /* reassemble message; if no message available (we received a fragment) return 514 */ 515 p_data->p_buf = avct_bcb_msg_asmbl(p_bcb, p_data->p_buf); 516 if (p_data->p_buf == NULL) { 517 return; 518 } 519 520 p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset; 521 522 /* parse header byte */ 523 AVCT_PARSE_HDR(p, label, type, cr_ipid); 524 525 /* check for invalid cr_ipid */ 526 if (cr_ipid == AVCT_CR_IPID_INVALID) { 527 AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid); 528 osi_free_and_reset((void**)&p_data->p_buf); 529 return; 530 } 531 532 /* parse and lookup PID */ 533 BE_STREAM_TO_UINT16(pid, p); 534 p_ccb = avct_lcb_has_pid(p_lcb, pid); 535 if (p_ccb) { 536 /* PID found; send msg up, adjust bt hdr and call msg callback */ 537 p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE; 538 p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE; 539 (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, 540 p_data->p_buf); 541 return; 542 } 543 544 /* PID not found; drop message */ 545 AVCT_TRACE_WARNING("No ccb for PID=%x", pid); 546 osi_free_and_reset((void**)&p_data->p_buf); 547 548 /* if command send reject */ 549 if (cr_ipid == AVCT_CMD) { 550 BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVRC_CMD_BUF_SIZE); 551 p_buf->len = AVCT_HDR_LEN_SINGLE; 552 p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE; 553 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 554 AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ); 555 UINT16_TO_BE_STREAM(p, pid); 556 p_buf->layer_specific = AVCT_DATA_BROWSE; 557 L2CA_DataWrite(p_bcb->ch_lcid, p_buf); 558 } 559 } 560 561 /******************************************************************************* 562 * 563 * Function avct_bcb_dealloc 564 * 565 * Description Deallocate a browse control block. 566 * 567 * 568 * Returns void. 569 * 570 ******************************************************************************/ 571 void avct_bcb_dealloc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 572 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 573 574 AVCT_TRACE_DEBUG("%s %d", __func__, p_bcb->allocated); 575 576 for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { 577 /* if ccb allocated and */ 578 if ((p_ccb->allocated) && (p_ccb->p_bcb == p_bcb)) { 579 p_ccb->p_bcb = NULL; 580 AVCT_TRACE_DEBUG("%s used by ccb: %d", __func__, idx); 581 break; 582 } 583 } 584 585 /* the browsing channel is down. Check if we have pending messages */ 586 osi_free_and_reset((void**)&p_bcb->p_tx_msg); 587 memset(p_bcb, 0, sizeof(tAVCT_BCB)); 588 } 589 590 /******************************************************************************* 591 * 592 * Function avct_close_bcb 593 * 594 * Description this function is called right before LCB disconnects. 595 * 596 * 597 * Returns Nothing. 598 * 599 ******************************************************************************/ 600 void avct_close_bcb(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 601 tAVCT_BCB* p_bcb = avct_bcb_by_lcb(p_lcb); 602 if (p_bcb->allocated) { 603 avct_bcb_event(p_bcb, AVCT_LCB_UL_UNBIND_EVT, p_data); 604 } 605 } 606 607 /******************************************************************************* 608 * 609 * Function avct_lcb_by_bcb 610 * 611 * Description This lookup function finds the lcb for a bcb. 612 * 613 * Returns pointer to the lcb. 614 * 615 ******************************************************************************/ 616 tAVCT_LCB* avct_lcb_by_bcb(tAVCT_BCB* p_bcb) { 617 return &avct_cb.lcb[p_bcb->allocated - 1]; 618 } 619 620 /******************************************************************************* 621 * 622 * Function avct_bcb_by_lcb 623 * 624 * Description This lookup function finds the bcb for a lcb. 625 * 626 * Returns pointer to the lcb. 627 * 628 ******************************************************************************/ 629 tAVCT_BCB* avct_bcb_by_lcb(tAVCT_LCB* p_lcb) { 630 return &avct_cb.bcb[p_lcb->allocated - 1]; 631 } 632 633 /******************************************************************************* 634 * 635 * Function avct_bcb_get_last_ccb_index 636 * 637 * Description See if given ccb is only one on the bcb. 638 * 639 * 640 * Returns 0, if ccb is last, (ccb index + 1) otherwise. 641 * 642 ******************************************************************************/ 643 uint8_t avct_bcb_get_last_ccb_index(tAVCT_BCB* p_bcb, tAVCT_CCB* p_ccb_last) { 644 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 645 uint8_t idx = 0; 646 647 for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 648 if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { 649 if (p_ccb != p_ccb_last) return 0; 650 idx = (uint8_t)(i + 1); 651 } 652 } 653 return idx; 654 } 655 656 /******************************************************************************* 657 * 658 * Function avct_bcb_by_lcid 659 * 660 * Description Find the BCB associated with the L2CAP LCID 661 * 662 * 663 * Returns pointer to the lcb, or NULL if none found. 664 * 665 ******************************************************************************/ 666 tAVCT_BCB* avct_bcb_by_lcid(uint16_t lcid) { 667 tAVCT_BCB* p_bcb = &avct_cb.bcb[0]; 668 int idx; 669 670 for (idx = 0; idx < AVCT_NUM_LINKS; idx++, p_bcb++) { 671 if (p_bcb->allocated && (p_bcb->ch_lcid == lcid)) { 672 return p_bcb; 673 } 674 } 675 676 /* out of lcbs */ 677 AVCT_TRACE_WARNING("No bcb for lcid %x", lcid); 678 return NULL; 679 } 680