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