1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-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 module contains action functions of the link control state machine. 22 * 23 ******************************************************************************/ 24 25 #include <string.h> 26 #include "avct_api.h" 27 #include "avct_int.h" 28 #include "bt_common.h" 29 #include "bt_target.h" 30 #include "bt_types.h" 31 #include "bt_utils.h" 32 #include "btm_api.h" 33 #include "osi/include/osi.h" 34 35 /* packet header length lookup table */ 36 const uint8_t avct_lcb_pkt_type_len[] = {AVCT_HDR_LEN_SINGLE, 37 AVCT_HDR_LEN_START, AVCT_HDR_LEN_CONT, 38 AVCT_HDR_LEN_END}; 39 40 /******************************************************************************* 41 * 42 * Function avct_lcb_msg_asmbl 43 * 44 * Description Reassemble incoming message. 45 * 46 * 47 * Returns Pointer to reassembled message; NULL if no message 48 * available. 49 * 50 ******************************************************************************/ 51 static BT_HDR* avct_lcb_msg_asmbl(tAVCT_LCB* p_lcb, BT_HDR* p_buf) { 52 uint8_t* p; 53 uint8_t pkt_type; 54 BT_HDR* p_ret; 55 56 /* parse the message header */ 57 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 58 pkt_type = AVCT_PKT_TYPE(p); 59 60 /* quick sanity check on length */ 61 if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) { 62 osi_free(p_buf); 63 AVCT_TRACE_WARNING("Bad length during reassembly"); 64 p_ret = NULL; 65 } 66 /* single packet */ 67 else if (pkt_type == AVCT_PKT_TYPE_SINGLE) { 68 /* if reassembly in progress drop message and process new single */ 69 if (p_lcb->p_rx_msg != NULL) 70 AVCT_TRACE_WARNING("Got single during reassembly"); 71 72 osi_free_and_reset((void**)&p_lcb->p_rx_msg); 73 74 p_ret = p_buf; 75 } 76 /* start packet */ 77 else if (pkt_type == AVCT_PKT_TYPE_START) { 78 /* if reassembly in progress drop message and process new start */ 79 if (p_lcb->p_rx_msg != NULL) 80 AVCT_TRACE_WARNING("Got start during reassembly"); 81 82 osi_free(p_lcb->p_rx_msg); 83 84 /* 85 * Allocate bigger buffer for reassembly. As lower layers are 86 * not aware of possible packet size after reassembly, they 87 * would have allocated smaller buffer. 88 */ 89 p_lcb->p_rx_msg = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); 90 memcpy(p_lcb->p_rx_msg, p_buf, sizeof(BT_HDR) + p_buf->offset + p_buf->len); 91 92 /* Free original buffer */ 93 osi_free(p_buf); 94 95 /* update p to point to new buffer */ 96 p = (uint8_t*)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset; 97 98 /* copy first header byte over nosp */ 99 *(p + 1) = *p; 100 101 /* set offset to point to where to copy next */ 102 p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len; 103 104 /* adjust length for packet header */ 105 p_lcb->p_rx_msg->len -= 1; 106 107 p_ret = NULL; 108 } 109 /* continue or end */ 110 else { 111 /* if no reassembly in progress drop message */ 112 if (p_lcb->p_rx_msg == NULL) { 113 osi_free(p_buf); 114 AVCT_TRACE_WARNING("Pkt type=%d out of order", pkt_type); 115 p_ret = NULL; 116 } else { 117 /* get size of buffer holding assembled message */ 118 /* 119 * NOTE: The buffer is allocated above at the beginning of the 120 * reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE. 121 */ 122 uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR); 123 124 /* adjust offset and len of fragment for header byte */ 125 p_buf->offset += AVCT_HDR_LEN_CONT; 126 p_buf->len -= AVCT_HDR_LEN_CONT; 127 128 /* verify length */ 129 if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len) { 130 /* won't fit; free everything */ 131 AVCT_TRACE_WARNING("%s: Fragmented message too big!", __func__); 132 osi_free_and_reset((void**)&p_lcb->p_rx_msg); 133 osi_free(p_buf); 134 p_ret = NULL; 135 } else { 136 /* copy contents of p_buf to p_rx_msg */ 137 memcpy((uint8_t*)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset, 138 (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len); 139 140 if (pkt_type == AVCT_PKT_TYPE_END) { 141 p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len; 142 p_lcb->p_rx_msg->len += p_buf->len; 143 p_ret = p_lcb->p_rx_msg; 144 p_lcb->p_rx_msg = NULL; 145 } else { 146 p_lcb->p_rx_msg->offset += p_buf->len; 147 p_lcb->p_rx_msg->len += p_buf->len; 148 p_ret = NULL; 149 } 150 osi_free(p_buf); 151 } 152 } 153 } 154 return p_ret; 155 } 156 157 /******************************************************************************* 158 * 159 * Function avct_lcb_chnl_open 160 * 161 * Description Open L2CAP channel to peer 162 * 163 * 164 * Returns Nothing. 165 * 166 ******************************************************************************/ 167 void avct_lcb_chnl_open(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 168 uint16_t result = AVCT_RESULT_FAIL; 169 170 BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0); 171 /* call l2cap connect req */ 172 p_lcb->ch_state = AVCT_CH_CONN; 173 p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr); 174 if (p_lcb->ch_lcid == 0) { 175 /* if connect req failed, send ourselves close event */ 176 avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result); 177 } 178 } 179 180 /******************************************************************************* 181 * 182 * Function avct_lcb_unbind_disc 183 * 184 * Description Deallocate ccb and call callback with disconnect event. 185 * 186 * 187 * Returns Nothing. 188 * 189 ******************************************************************************/ 190 void avct_lcb_unbind_disc(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 191 avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL); 192 } 193 194 /******************************************************************************* 195 * 196 * Function avct_lcb_open_ind 197 * 198 * Description Handle an LL_OPEN event. For each allocated ccb already 199 * bound to this lcb, send a connect event. For each 200 * unbound ccb with a new PID, bind that ccb to this lcb and 201 * send a connect event. 202 * 203 * 204 * Returns Nothing. 205 * 206 ******************************************************************************/ 207 void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 208 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 209 int i; 210 bool bind = false; 211 212 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 213 /* if ccb allocated and */ 214 if (p_ccb->allocated) { 215 /* if bound to this lcb send connect confirm event */ 216 if (p_ccb->p_lcb == p_lcb) { 217 bind = true; 218 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH); 219 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0, 220 p_lcb->peer_addr); 221 } 222 /* if unbound acceptor and lcb doesn't already have a ccb for this PID */ 223 else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) && 224 (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) { 225 /* bind ccb to lcb and send connect ind event */ 226 bind = true; 227 p_ccb->p_lcb = p_lcb; 228 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH); 229 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0, 230 p_lcb->peer_addr); 231 } 232 } 233 } 234 235 /* if no ccbs bound to this lcb, disconnect */ 236 if (bind == false) { 237 avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data); 238 } 239 } 240 241 /******************************************************************************* 242 * 243 * Function avct_lcb_open_fail 244 * 245 * Description L2CAP channel open attempt failed. Deallocate any ccbs 246 * on this lcb and send connect confirm event with failure. 247 * 248 * 249 * Returns Nothing. 250 * 251 ******************************************************************************/ 252 void avct_lcb_open_fail(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 253 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 254 int i; 255 256 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 257 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { 258 avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT, p_data->result, 259 p_lcb->peer_addr); 260 } 261 } 262 } 263 264 /******************************************************************************* 265 * 266 * Function avct_lcb_close_ind 267 * 268 * Description L2CAP channel closed by peer. Deallocate any initiator 269 * ccbs on this lcb and send disconnect ind event. 270 * 271 * 272 * Returns Nothing. 273 * 274 ******************************************************************************/ 275 void avct_lcb_close_ind(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 276 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 277 int i; 278 279 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 280 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { 281 if (p_ccb->cc.role == AVCT_INT) { 282 avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr); 283 } else { 284 p_ccb->p_lcb = NULL; 285 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), 286 AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr); 287 } 288 } 289 } 290 } 291 292 /******************************************************************************* 293 * 294 * Function avct_lcb_close_cfm 295 * 296 * Description L2CAP channel closed by us. Deallocate any initiator 297 * ccbs on this lcb and send disconnect ind or cfm event. 298 * 299 * 300 * Returns Nothing. 301 * 302 ******************************************************************************/ 303 void avct_lcb_close_cfm(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 304 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 305 int i; 306 uint8_t event; 307 308 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 309 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { 310 /* if this ccb initiated close send disconnect cfm otherwise ind */ 311 if (p_ccb->ch_close) { 312 p_ccb->ch_close = false; 313 event = AVCT_DISCONNECT_CFM_EVT; 314 } else { 315 event = AVCT_DISCONNECT_IND_EVT; 316 } 317 318 if (p_ccb->cc.role == AVCT_INT) { 319 avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr); 320 } else { 321 p_ccb->p_lcb = NULL; 322 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result, 323 p_lcb->peer_addr); 324 } 325 } 326 } 327 } 328 329 /******************************************************************************* 330 * 331 * Function avct_lcb_bind_conn 332 * 333 * Description Bind ccb to lcb and send connect cfm event. 334 * 335 * 336 * Returns Nothing. 337 * 338 ******************************************************************************/ 339 void avct_lcb_bind_conn(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 340 p_data->p_ccb->p_lcb = p_lcb; 341 (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb), 342 AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr); 343 } 344 345 /******************************************************************************* 346 * 347 * Function avct_lcb_chk_disc 348 * 349 * Description A ccb wants to close; if it is the last ccb on this lcb, 350 * close channel. Otherwise just deallocate and call 351 * callback. 352 * 353 * 354 * Returns Nothing. 355 * 356 ******************************************************************************/ 357 void avct_lcb_chk_disc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 358 AVCT_TRACE_WARNING("%s", __func__); 359 360 avct_close_bcb(p_lcb, p_data); 361 if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb)) { 362 AVCT_TRACE_WARNING("%s: closing", __func__); 363 p_data->p_ccb->ch_close = true; 364 avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data); 365 } else { 366 AVCT_TRACE_WARNING("%s: dealloc ccb", __func__); 367 avct_lcb_unbind_disc(p_lcb, p_data); 368 } 369 } 370 371 /******************************************************************************* 372 * 373 * Function avct_lcb_chnl_disc 374 * 375 * Description Disconnect L2CAP channel. 376 * 377 * 378 * Returns Nothing. 379 * 380 ******************************************************************************/ 381 void avct_lcb_chnl_disc(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { 382 L2CA_DisconnectReq(p_lcb->ch_lcid); 383 } 384 385 /******************************************************************************* 386 * 387 * Function avct_lcb_bind_fail 388 * 389 * Description Deallocate ccb and call callback with connect event 390 * with failure result. 391 * 392 * 393 * Returns Nothing. 394 * 395 ******************************************************************************/ 396 void avct_lcb_bind_fail(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 397 avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL); 398 } 399 400 /******************************************************************************* 401 * 402 * Function avct_lcb_cong_ind 403 * 404 * Description Handle congestion indication from L2CAP. 405 * 406 * 407 * Returns Nothing. 408 * 409 ******************************************************************************/ 410 void avct_lcb_cong_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 411 tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; 412 int i; 413 uint8_t event; 414 BT_HDR* p_buf; 415 416 /* set event */ 417 event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT; 418 p_lcb->cong = p_data->cong; 419 if (p_lcb->cong == false && !fixed_queue_is_empty(p_lcb->tx_q)) { 420 while (!p_lcb->cong && 421 (p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL) { 422 if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) { 423 p_lcb->cong = true; 424 } 425 } 426 } 427 428 /* send event to all ccbs on this lcb */ 429 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { 430 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { 431 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, 432 p_lcb->peer_addr); 433 } 434 } 435 } 436 437 /******************************************************************************* 438 * 439 * Function avct_lcb_discard_msg 440 * 441 * Description Discard a message sent in from the API. 442 * 443 * 444 * Returns Nothing. 445 * 446 ******************************************************************************/ 447 void avct_lcb_discard_msg(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 448 AVCT_TRACE_WARNING("%s Dropping message", __func__); 449 osi_free_and_reset((void**)&p_data->ul_msg.p_buf); 450 } 451 452 /******************************************************************************* 453 * 454 * Function avct_lcb_send_msg 455 * 456 * Description Build and send an AVCTP message. 457 * 458 * 459 * Returns Nothing. 460 * 461 ******************************************************************************/ 462 void avct_lcb_send_msg(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 463 uint16_t curr_msg_len; 464 uint8_t pkt_type; 465 uint8_t hdr_len; 466 uint8_t* p; 467 uint8_t nosp = 0; /* number of subsequent packets */ 468 uint16_t temp; 469 uint16_t buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE; 470 471 /* store msg len */ 472 curr_msg_len = p_data->ul_msg.p_buf->len; 473 474 /* initialize packet type and other stuff */ 475 if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) { 476 pkt_type = AVCT_PKT_TYPE_SINGLE; 477 } else { 478 pkt_type = AVCT_PKT_TYPE_START; 479 temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu); 480 nosp = temp / (p_lcb->peer_mtu - 1) + 1; 481 if ((temp % (p_lcb->peer_mtu - 1)) != 0) nosp++; 482 } 483 484 /* while we haven't sent all packets */ 485 while (curr_msg_len != 0) { 486 BT_HDR* p_buf; 487 488 /* set header len */ 489 hdr_len = avct_lcb_pkt_type_len[pkt_type]; 490 491 /* if remaining msg must be fragmented */ 492 if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len)) { 493 /* get a new buffer for fragment we are sending */ 494 p_buf = (BT_HDR*)osi_malloc(buf_size); 495 496 /* copy portion of data from current message to new buffer */ 497 p_buf->offset = L2CAP_MIN_OFFSET + hdr_len; 498 p_buf->len = p_lcb->peer_mtu - hdr_len; 499 500 memcpy( 501 (uint8_t*)(p_buf + 1) + p_buf->offset, 502 (uint8_t*)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset, 503 p_buf->len); 504 505 p_data->ul_msg.p_buf->offset += p_buf->len; 506 p_data->ul_msg.p_buf->len -= p_buf->len; 507 } else { 508 p_buf = p_data->ul_msg.p_buf; 509 } 510 511 curr_msg_len -= p_buf->len; 512 513 /* set up to build header */ 514 p_buf->len += hdr_len; 515 p_buf->offset -= hdr_len; 516 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 517 518 /* build header */ 519 AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr); 520 if (pkt_type == AVCT_PKT_TYPE_START) { 521 UINT8_TO_STREAM(p, nosp); 522 } 523 if ((pkt_type == AVCT_PKT_TYPE_START) || 524 (pkt_type == AVCT_PKT_TYPE_SINGLE)) { 525 UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid); 526 } 527 528 if (p_lcb->cong == true) { 529 fixed_queue_enqueue(p_lcb->tx_q, p_buf); 530 } 531 532 /* send message to L2CAP */ 533 else { 534 if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) { 535 p_lcb->cong = true; 536 } 537 } 538 539 /* update pkt type for next packet */ 540 if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END)) { 541 pkt_type = AVCT_PKT_TYPE_CONT; 542 } else { 543 pkt_type = AVCT_PKT_TYPE_END; 544 } 545 } 546 AVCT_TRACE_DEBUG("%s tx_q_count:%d", __func__, 547 fixed_queue_length(p_lcb->tx_q)); 548 return; 549 } 550 551 /******************************************************************************* 552 * 553 * Function avct_lcb_free_msg_ind 554 * 555 * Description Discard an incoming AVCTP message. 556 * 557 * 558 * Returns Nothing. 559 * 560 ******************************************************************************/ 561 void avct_lcb_free_msg_ind(UNUSED_ATTR tAVCT_LCB* p_lcb, 562 tAVCT_LCB_EVT* p_data) { 563 if (p_data == NULL) return; 564 565 osi_free_and_reset((void**)&p_data->p_buf); 566 } 567 568 /******************************************************************************* 569 * 570 * Function avct_lcb_msg_ind 571 * 572 * Description Handle an incoming AVCTP message. 573 * 574 * 575 * Returns Nothing. 576 * 577 ******************************************************************************/ 578 void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { 579 uint8_t* p; 580 uint8_t label, type, cr_ipid; 581 uint16_t pid; 582 tAVCT_CCB* p_ccb; 583 584 /* this p_buf is to be reported through p_msg_cback. The layer_specific 585 * needs to be set properly to indicate that it is received through 586 * control channel */ 587 p_data->p_buf->layer_specific = AVCT_DATA_CTRL; 588 589 /* reassemble message; if no message available (we received a fragment) return 590 */ 591 p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf); 592 if (p_data->p_buf == NULL) { 593 return; 594 } 595 596 p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset; 597 598 /* parse header byte */ 599 AVCT_PARSE_HDR(p, label, type, cr_ipid); 600 601 /* check for invalid cr_ipid */ 602 if (cr_ipid == AVCT_CR_IPID_INVALID) { 603 AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid); 604 osi_free_and_reset((void**)&p_data->p_buf); 605 return; 606 } 607 608 /* parse and lookup PID */ 609 BE_STREAM_TO_UINT16(pid, p); 610 p_ccb = avct_lcb_has_pid(p_lcb, pid); 611 if (p_ccb) { 612 /* PID found; send msg up, adjust bt hdr and call msg callback */ 613 p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE; 614 p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE; 615 (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, 616 p_data->p_buf); 617 return; 618 } 619 620 /* PID not found; drop message */ 621 AVCT_TRACE_WARNING("No ccb for PID=%x", pid); 622 osi_free_and_reset((void**)&p_data->p_buf); 623 624 /* if command send reject */ 625 if (cr_ipid == AVCT_CMD) { 626 BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVCT_CMD_BUF_SIZE); 627 p_buf->len = AVCT_HDR_LEN_SINGLE; 628 p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE; 629 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 630 AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ); 631 UINT16_TO_BE_STREAM(p, pid); 632 L2CA_DataWrite(p_lcb->ch_lcid, p_buf); 633 } 634 } 635