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 "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 */
     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         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 *******************************************************************************/
    171 void 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 *******************************************************************************/
    196 void 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 *******************************************************************************/
    216 void 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 *******************************************************************************/
    267 void 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 *******************************************************************************/
    293 void 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 *******************************************************************************/
    329 void 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 *******************************************************************************/
    374 void 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 *******************************************************************************/
    393 void 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 *******************************************************************************/
    422 void 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 *******************************************************************************/
    440 void 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 *******************************************************************************/
    457 void 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 *******************************************************************************/
    498 void 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 *******************************************************************************/
    517 void 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 *******************************************************************************/
    635 void 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 *******************************************************************************/
    654 void 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