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