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 "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     avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result);
    177   }
    178 }
    179 
    180 /*******************************************************************************
    181  *
    182  * Function         avct_lcb_unbind_disc
    183  *
    184  * Description      Deallocate ccb and call callback with disconnect event.
    185  *
    186  *
    187  * Returns          Nothing.
    188  *
    189  ******************************************************************************/
    190 void avct_lcb_unbind_disc(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    191   avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
    192 }
    193 
    194 /*******************************************************************************
    195  *
    196  * Function         avct_lcb_open_ind
    197  *
    198  * Description      Handle an LL_OPEN event.  For each allocated ccb already
    199  *                  bound to this lcb, send a connect event.  For each
    200  *                  unbound ccb with a new PID, bind that ccb to this lcb and
    201  *                  send a connect event.
    202  *
    203  *
    204  * Returns          Nothing.
    205  *
    206  ******************************************************************************/
    207 void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    208   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    209   int i;
    210   bool bind = false;
    211 
    212   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    213     /* if ccb allocated and */
    214     if (p_ccb->allocated) {
    215       /* if bound to this lcb send connect confirm event */
    216       if (p_ccb->p_lcb == p_lcb) {
    217         bind = true;
    218         L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
    219         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0,
    220                                p_lcb->peer_addr);
    221       }
    222       /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
    223       else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
    224                (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) {
    225         /* bind ccb to lcb and send connect ind event */
    226         bind = true;
    227         p_ccb->p_lcb = p_lcb;
    228         L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
    229         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0,
    230                                p_lcb->peer_addr);
    231       }
    232     }
    233   }
    234 
    235   /* if no ccbs bound to this lcb, disconnect */
    236   if (bind == false) {
    237     avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
    238   }
    239 }
    240 
    241 /*******************************************************************************
    242  *
    243  * Function         avct_lcb_open_fail
    244  *
    245  * Description      L2CAP channel open attempt failed.  Deallocate any ccbs
    246  *                  on this lcb and send connect confirm event with failure.
    247  *
    248  *
    249  * Returns          Nothing.
    250  *
    251  ******************************************************************************/
    252 void avct_lcb_open_fail(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    253   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    254   int i;
    255 
    256   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    257     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
    258       avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT, p_data->result,
    259                        p_lcb->peer_addr);
    260     }
    261   }
    262 }
    263 
    264 /*******************************************************************************
    265  *
    266  * Function         avct_lcb_close_ind
    267  *
    268  * Description      L2CAP channel closed by peer.  Deallocate any initiator
    269  *                  ccbs on this lcb and send disconnect ind event.
    270  *
    271  *
    272  * Returns          Nothing.
    273  *
    274  ******************************************************************************/
    275 void avct_lcb_close_ind(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    276   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    277   int i;
    278 
    279   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    280     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
    281       if (p_ccb->cc.role == AVCT_INT) {
    282         avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr);
    283       } else {
    284         p_ccb->p_lcb = NULL;
    285         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
    286                                   AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr);
    287       }
    288     }
    289   }
    290 }
    291 
    292 /*******************************************************************************
    293  *
    294  * Function         avct_lcb_close_cfm
    295  *
    296  * Description      L2CAP channel closed by us.  Deallocate any initiator
    297  *                  ccbs on this lcb and send disconnect ind or cfm event.
    298  *
    299  *
    300  * Returns          Nothing.
    301  *
    302  ******************************************************************************/
    303 void avct_lcb_close_cfm(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    304   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    305   int i;
    306   uint8_t event;
    307 
    308   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    309     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
    310       /* if this ccb initiated close send disconnect cfm otherwise ind */
    311       if (p_ccb->ch_close) {
    312         p_ccb->ch_close = false;
    313         event = AVCT_DISCONNECT_CFM_EVT;
    314       } else {
    315         event = AVCT_DISCONNECT_IND_EVT;
    316       }
    317 
    318       if (p_ccb->cc.role == AVCT_INT) {
    319         avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
    320       } else {
    321         p_ccb->p_lcb = NULL;
    322         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result,
    323                                   p_lcb->peer_addr);
    324       }
    325     }
    326   }
    327 }
    328 
    329 /*******************************************************************************
    330  *
    331  * Function         avct_lcb_bind_conn
    332  *
    333  * Description      Bind ccb to lcb and send connect cfm event.
    334  *
    335  *
    336  * Returns          Nothing.
    337  *
    338  ******************************************************************************/
    339 void avct_lcb_bind_conn(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    340   p_data->p_ccb->p_lcb = p_lcb;
    341   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
    342                                     AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
    343 }
    344 
    345 /*******************************************************************************
    346  *
    347  * Function         avct_lcb_chk_disc
    348  *
    349  * Description      A ccb wants to close; if it is the last ccb on this lcb,
    350  *                  close channel.  Otherwise just deallocate and call
    351  *                  callback.
    352  *
    353  *
    354  * Returns          Nothing.
    355  *
    356  ******************************************************************************/
    357 void avct_lcb_chk_disc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    358   AVCT_TRACE_WARNING("%s", __func__);
    359 
    360   avct_close_bcb(p_lcb, p_data);
    361   if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb)) {
    362     AVCT_TRACE_WARNING("%s: closing", __func__);
    363     p_data->p_ccb->ch_close = true;
    364     avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
    365   } else {
    366     AVCT_TRACE_WARNING("%s: dealloc ccb", __func__);
    367     avct_lcb_unbind_disc(p_lcb, p_data);
    368   }
    369 }
    370 
    371 /*******************************************************************************
    372  *
    373  * Function         avct_lcb_chnl_disc
    374  *
    375  * Description      Disconnect L2CAP channel.
    376  *
    377  *
    378  * Returns          Nothing.
    379  *
    380  ******************************************************************************/
    381 void avct_lcb_chnl_disc(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    382   L2CA_DisconnectReq(p_lcb->ch_lcid);
    383 }
    384 
    385 /*******************************************************************************
    386  *
    387  * Function         avct_lcb_bind_fail
    388  *
    389  * Description      Deallocate ccb and call callback with connect event
    390  *                  with failure result.
    391  *
    392  *
    393  * Returns          Nothing.
    394  *
    395  ******************************************************************************/
    396 void avct_lcb_bind_fail(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    397   avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
    398 }
    399 
    400 /*******************************************************************************
    401  *
    402  * Function         avct_lcb_cong_ind
    403  *
    404  * Description      Handle congestion indication from L2CAP.
    405  *
    406  *
    407  * Returns          Nothing.
    408  *
    409  ******************************************************************************/
    410 void avct_lcb_cong_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    411   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    412   int i;
    413   uint8_t event;
    414   BT_HDR* p_buf;
    415 
    416   /* set event */
    417   event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
    418   p_lcb->cong = p_data->cong;
    419   if (p_lcb->cong == false && !fixed_queue_is_empty(p_lcb->tx_q)) {
    420     while (!p_lcb->cong &&
    421            (p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL) {
    422       if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) {
    423         p_lcb->cong = true;
    424       }
    425     }
    426   }
    427 
    428   /* send event to all ccbs on this lcb */
    429   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    430     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
    431       (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0,
    432                                 p_lcb->peer_addr);
    433     }
    434   }
    435 }
    436 
    437 /*******************************************************************************
    438  *
    439  * Function         avct_lcb_discard_msg
    440  *
    441  * Description      Discard a message sent in from the API.
    442  *
    443  *
    444  * Returns          Nothing.
    445  *
    446  ******************************************************************************/
    447 void avct_lcb_discard_msg(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    448   AVCT_TRACE_WARNING("%s Dropping message", __func__);
    449   osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
    450 }
    451 
    452 /*******************************************************************************
    453  *
    454  * Function         avct_lcb_send_msg
    455  *
    456  * Description      Build and send an AVCTP message.
    457  *
    458  *
    459  * Returns          Nothing.
    460  *
    461  ******************************************************************************/
    462 void avct_lcb_send_msg(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    463   uint16_t curr_msg_len;
    464   uint8_t pkt_type;
    465   uint8_t hdr_len;
    466   uint8_t* p;
    467   uint8_t nosp = 0; /* number of subsequent packets */
    468   uint16_t temp;
    469   uint16_t buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
    470 
    471   /* store msg len */
    472   curr_msg_len = p_data->ul_msg.p_buf->len;
    473 
    474   /* initialize packet type and other stuff */
    475   if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) {
    476     pkt_type = AVCT_PKT_TYPE_SINGLE;
    477   } else {
    478     pkt_type = AVCT_PKT_TYPE_START;
    479     temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
    480     nosp = temp / (p_lcb->peer_mtu - 1) + 1;
    481     if ((temp % (p_lcb->peer_mtu - 1)) != 0) nosp++;
    482   }
    483 
    484   /* while we haven't sent all packets */
    485   while (curr_msg_len != 0) {
    486     BT_HDR* p_buf;
    487 
    488     /* set header len */
    489     hdr_len = avct_lcb_pkt_type_len[pkt_type];
    490 
    491     /* if remaining msg must be fragmented */
    492     if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len)) {
    493       /* get a new buffer for fragment we are sending */
    494       p_buf = (BT_HDR*)osi_malloc(buf_size);
    495 
    496       /* copy portion of data from current message to new buffer */
    497       p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
    498       p_buf->len = p_lcb->peer_mtu - hdr_len;
    499 
    500       memcpy(
    501           (uint8_t*)(p_buf + 1) + p_buf->offset,
    502           (uint8_t*)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset,
    503           p_buf->len);
    504 
    505       p_data->ul_msg.p_buf->offset += p_buf->len;
    506       p_data->ul_msg.p_buf->len -= p_buf->len;
    507     } else {
    508       p_buf = p_data->ul_msg.p_buf;
    509     }
    510 
    511     curr_msg_len -= p_buf->len;
    512 
    513     /* set up to build header */
    514     p_buf->len += hdr_len;
    515     p_buf->offset -= hdr_len;
    516     p = (uint8_t*)(p_buf + 1) + p_buf->offset;
    517 
    518     /* build header */
    519     AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
    520     if (pkt_type == AVCT_PKT_TYPE_START) {
    521       UINT8_TO_STREAM(p, nosp);
    522     }
    523     if ((pkt_type == AVCT_PKT_TYPE_START) ||
    524         (pkt_type == AVCT_PKT_TYPE_SINGLE)) {
    525       UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
    526     }
    527 
    528     if (p_lcb->cong == true) {
    529       fixed_queue_enqueue(p_lcb->tx_q, p_buf);
    530     }
    531 
    532     /* send message to L2CAP */
    533     else {
    534       if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) {
    535         p_lcb->cong = true;
    536       }
    537     }
    538 
    539     /* update pkt type for next packet */
    540     if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END)) {
    541       pkt_type = AVCT_PKT_TYPE_CONT;
    542     } else {
    543       pkt_type = AVCT_PKT_TYPE_END;
    544     }
    545   }
    546   AVCT_TRACE_DEBUG("%s tx_q_count:%d", __func__,
    547                    fixed_queue_length(p_lcb->tx_q));
    548   return;
    549 }
    550 
    551 /*******************************************************************************
    552  *
    553  * Function         avct_lcb_free_msg_ind
    554  *
    555  * Description      Discard an incoming AVCTP message.
    556  *
    557  *
    558  * Returns          Nothing.
    559  *
    560  ******************************************************************************/
    561 void avct_lcb_free_msg_ind(UNUSED_ATTR tAVCT_LCB* p_lcb,
    562                            tAVCT_LCB_EVT* p_data) {
    563   if (p_data == NULL) return;
    564 
    565   osi_free_and_reset((void**)&p_data->p_buf);
    566 }
    567 
    568 /*******************************************************************************
    569  *
    570  * Function         avct_lcb_msg_ind
    571  *
    572  * Description      Handle an incoming AVCTP message.
    573  *
    574  *
    575  * Returns          Nothing.
    576  *
    577  ******************************************************************************/
    578 void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    579   uint8_t* p;
    580   uint8_t label, type, cr_ipid;
    581   uint16_t pid;
    582   tAVCT_CCB* p_ccb;
    583 
    584   /* this p_buf is to be reported through p_msg_cback. The layer_specific
    585    * needs to be set properly to indicate that it is received through
    586    * control channel */
    587   p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
    588 
    589   /* reassemble message; if no message available (we received a fragment) return
    590    */
    591   p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf);
    592   if (p_data->p_buf == NULL) {
    593     return;
    594   }
    595 
    596   p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset;
    597 
    598   /* parse header byte */
    599   AVCT_PARSE_HDR(p, label, type, cr_ipid);
    600 
    601   /* check for invalid cr_ipid */
    602   if (cr_ipid == AVCT_CR_IPID_INVALID) {
    603     AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
    604     osi_free_and_reset((void**)&p_data->p_buf);
    605     return;
    606   }
    607 
    608   /* parse and lookup PID */
    609   BE_STREAM_TO_UINT16(pid, p);
    610   p_ccb = avct_lcb_has_pid(p_lcb, pid);
    611   if (p_ccb) {
    612     /* PID found; send msg up, adjust bt hdr and call msg callback */
    613     p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
    614     p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
    615     (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
    616                              p_data->p_buf);
    617     return;
    618   }
    619 
    620   /* PID not found; drop message */
    621   AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
    622   osi_free_and_reset((void**)&p_data->p_buf);
    623 
    624   /* if command send reject */
    625   if (cr_ipid == AVCT_CMD) {
    626     BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVCT_CMD_BUF_SIZE);
    627     p_buf->len = AVCT_HDR_LEN_SINGLE;
    628     p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
    629     p = (uint8_t*)(p_buf + 1) + p_buf->offset;
    630     AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
    631     UINT16_TO_BE_STREAM(p, pid);
    632     L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
    633   }
    634 }
    635