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