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