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