Home | History | Annotate | Download | only in avct
      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