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