Home | History | Annotate | Download | only in avct
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2003-2016 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 *  Name:           avct_bcb_act.cc
     22 *
     23 *  Description:    This module contains action functions of the browsing control
     24 *                  state machine.
     25 *
     26  *****************************************************************************/
     27 
     28 #include <string.h>
     29 #include "avct_api.h"
     30 #include "avct_int.h"
     31 #include "bt_target.h"
     32 #include "bt_utils.h"
     33 #include "btm_api.h"
     34 #include "osi/include/osi.h"
     35 
     36 /* action function list */
     37 const tAVCT_BCB_ACTION avct_bcb_action[] = {
     38     avct_bcb_chnl_open,   /* AVCT_LCB_CHNL_OPEN */
     39     avct_bcb_chnl_disc,   /* AVCT_LCB_CHNL_DISC */
     40     avct_bcb_send_msg,    /* AVCT_LCB_SEND_MSG */
     41     avct_bcb_open_ind,    /* AVCT_LCB_OPEN_IND */
     42     avct_bcb_open_fail,   /* AVCT_LCB_OPEN_FAIL */
     43     avct_bcb_close_ind,   /* AVCT_LCB_CLOSE_IND */
     44     avct_bcb_close_cfm,   /* AVCT_LCB_CLOSE_CFM */
     45     avct_bcb_msg_ind,     /* AVCT_LCB_MSG_IND */
     46     avct_bcb_cong_ind,    /* AVCT_LCB_CONG_IND */
     47     avct_bcb_bind_conn,   /* AVCT_LCB_BIND_CONN */
     48     avct_bcb_bind_fail,   /* AVCT_LCB_BIND_FAIL */
     49     avct_bcb_unbind_disc, /* AVCT_LCB_UNBIND_DISC */
     50     avct_bcb_chk_disc,    /* AVCT_LCB_CHK_DISC */
     51     avct_bcb_discard_msg, /* AVCT_LCB_DISCARD_MSG */
     52     avct_bcb_dealloc,     /* AVCT_LCB_DEALLOC */
     53     avct_bcb_free_msg_ind /* AVCT_LCB_FREE_MSG_IND */
     54 };
     55 
     56 /*******************************************************************************
     57  *
     58  * Function         avct_bcb_msg_asmbl
     59  *
     60  * Description      Reassemble incoming message.
     61  *
     62  *
     63  * Returns          Pointer to reassembled message;  NULL if no message
     64  *                  available.
     65  *
     66  ******************************************************************************/
     67 static BT_HDR* avct_bcb_msg_asmbl(UNUSED_ATTR tAVCT_BCB* p_bcb, BT_HDR* p_buf) {
     68   uint8_t* p;
     69   uint8_t pkt_type;
     70 
     71   /* parse the message header */
     72   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
     73   pkt_type = AVCT_PKT_TYPE(p);
     74 
     75   /* must be single packet - can not fragment */
     76   if (pkt_type != AVCT_PKT_TYPE_SINGLE) {
     77     osi_free_and_reset((void**)&p_buf);
     78     AVCT_TRACE_WARNING("Pkt type=%d - fragmentation not allowed. drop it",
     79                        pkt_type);
     80   }
     81   return p_buf;
     82 }
     83 
     84 /*******************************************************************************
     85  *
     86  * Function         avct_bcb_chnl_open
     87  *
     88  * Description      Open L2CAP channel to peer
     89  *
     90  *
     91  * Returns          Nothing.
     92  *
     93  ******************************************************************************/
     94 void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
     95   uint16_t result = AVCT_RESULT_FAIL;
     96   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
     97   tL2CAP_ERTM_INFO ertm_info;
     98 
     99   BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP_BROWSE, 0);
    100 
    101   /* Set the FCR options: Browsing channel mandates ERTM */
    102   ertm_info.preferred_mode = avct_l2c_br_fcr_opts_def.mode;
    103   ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
    104   ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
    105   ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
    106   ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
    107   ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
    108 
    109   /* call l2cap connect req */
    110   p_bcb->ch_state = AVCT_CH_CONN;
    111   p_bcb->ch_lcid =
    112       L2CA_ErtmConnectReq(AVCT_BR_PSM, p_lcb->peer_addr, &ertm_info);
    113   if (p_bcb->ch_lcid == 0) {
    114     /* if connect req failed, send ourselves close event */
    115     avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result);
    116   }
    117 }
    118 
    119 /*******************************************************************************
    120  *
    121  * Function         avct_bcb_unbind_disc
    122  *
    123  * Description      call callback with disconnect event.
    124  *
    125  *
    126  * Returns          Nothing.
    127  *
    128  ******************************************************************************/
    129 void avct_bcb_unbind_disc(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    130   p_data->p_ccb->p_bcb = NULL;
    131   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
    132                                     AVCT_BROWSE_DISCONN_CFM_EVT, 0, NULL);
    133 }
    134 
    135 /*******************************************************************************
    136  *
    137  * Function         avct_bcb_open_ind
    138  *
    139  * Description      Handle an LL_OPEN event.
    140  *                  For the allocated ccb already bound to the bcb, send a
    141  *                  connect event. For the unbound ccb with a new PID, bind that
    142  *                  ccb to the bcb with the same bd_addr and send a connect
    143  *                  event.
    144  *
    145  *
    146  * Returns          Nothing.
    147  *
    148  ******************************************************************************/
    149 void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    150   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    151   tAVCT_CCB* p_ccb_bind = NULL;
    152   bool bind = false;
    153   tAVCT_UL_MSG ul_msg;
    154 
    155   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    156     /* if ccb allocated and */
    157     if (p_ccb->allocated) {
    158       /* if bound to this bcb send connect confirm event */
    159       if (p_ccb->p_bcb == p_bcb) {
    160         bind = true;
    161         p_ccb_bind = p_ccb;
    162         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT,
    163                                0, p_ccb->p_lcb->peer_addr);
    164       }
    165       /* if unbound acceptor and lcb allocated and bd_addr are the same for bcb
    166          and lcb */
    167       else if ((p_ccb->p_bcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
    168                (p_ccb->p_lcb != NULL) &&
    169                (!memcmp(p_bcb->peer_addr, p_ccb->p_lcb->peer_addr,
    170                         BD_ADDR_LEN))) {
    171         /* bind bcb to ccb and send connect ind event */
    172         bind = true;
    173         p_ccb_bind = p_ccb;
    174         p_ccb->p_bcb = p_bcb;
    175         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_IND_EVT,
    176                                0, p_ccb->p_lcb->peer_addr);
    177       }
    178     }
    179   }
    180 
    181   /* if no ccbs bound to this lcb, disconnect */
    182   if (bind == false) {
    183     avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
    184     return;
    185   }
    186 
    187   if (!p_bcb->p_tx_msg || !p_ccb_bind) {
    188     return;
    189   }
    190 
    191   ul_msg.p_buf = p_bcb->p_tx_msg;
    192   ul_msg.p_ccb = p_ccb_bind;
    193   ul_msg.label = (uint8_t)(p_bcb->p_tx_msg->layer_specific & 0xFF);
    194   ul_msg.cr = (uint8_t)((p_bcb->p_tx_msg->layer_specific & 0xFF00) >> 8);
    195   p_bcb->p_tx_msg->layer_specific = AVCT_DATA_BROWSE;
    196   p_bcb->p_tx_msg = NULL;
    197 
    198   /* send msg event to bcb */
    199   avct_bcb_event(p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT*)&ul_msg);
    200 }
    201 
    202 /*******************************************************************************
    203  *
    204  * Function         avct_bcb_open_fail
    205  *
    206  * Description      L2CAP channel open attempt failed.  Mark the ccbs
    207  *                  as NULL bcb.
    208  *
    209  *
    210  * Returns          Nothing.
    211  *
    212  ******************************************************************************/
    213 void avct_bcb_open_fail(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    214   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    215 
    216   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    217     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
    218       p_ccb->p_bcb = NULL;
    219     }
    220   }
    221 }
    222 
    223 /*******************************************************************************
    224  *
    225  * Function         avct_bcb_close_ind
    226  *
    227  * Description      L2CAP channel closed by peer.  Deallocate any initiator
    228  *                  ccbs on this lcb and send disconnect ind event.
    229  *
    230  *
    231  * Returns          Nothing.
    232  *
    233  ******************************************************************************/
    234 void avct_bcb_close_ind(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    235   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    236   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
    237 
    238   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    239     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
    240       if (p_ccb->cc.role == AVCT_INT) {
    241         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
    242                                   AVCT_BROWSE_DISCONN_CFM_EVT, 0,
    243                                   p_lcb->peer_addr);
    244       } else {
    245         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
    246                                   AVCT_BROWSE_DISCONN_IND_EVT, 0, NULL);
    247       }
    248       p_ccb->p_bcb = NULL;
    249     }
    250   }
    251 }
    252 
    253 /*******************************************************************************
    254  *
    255  * Function         avct_bcb_close_cfm
    256  *
    257  * Description      L2CAP channel closed by us.  Deallocate any initiator
    258  *                  ccbs on this lcb and send disconnect ind or cfm event.
    259  *
    260  *
    261  * Returns          Nothing.
    262  *
    263  ******************************************************************************/
    264 void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    265   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    266   uint8_t event = 0;
    267   /* Whether BCB initiated channel close */
    268   bool ch_close = p_bcb->ch_close;
    269   tAVCT_CTRL_CBACK* p_cback;
    270 
    271   p_bcb->ch_close = false;
    272   p_bcb->allocated = 0;
    273   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    274     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
    275       /* if this ccb initiated close send disconnect cfm otherwise ind */
    276       if (ch_close) {
    277         event = AVCT_BROWSE_DISCONN_CFM_EVT;
    278       } else {
    279         event = AVCT_BROWSE_DISCONN_IND_EVT;
    280       }
    281 
    282       p_cback = p_ccb->cc.p_ctrl_cback;
    283       p_ccb->p_bcb = NULL;
    284       if (p_ccb->p_lcb == NULL) avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
    285       (*p_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result,
    286                  p_bcb->peer_addr);
    287     }
    288   }
    289 }
    290 
    291 /*******************************************************************************
    292  *
    293  * Function         avct_bcb_bind_conn
    294  *
    295  * Description      Bind ccb to lcb and send connect cfm event.
    296  *
    297  *
    298  * Returns          Nothing.
    299  *
    300  ******************************************************************************/
    301 void avct_bcb_bind_conn(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    302   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
    303   p_data->p_ccb->p_bcb = p_bcb;
    304   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
    305                                     AVCT_BROWSE_CONN_CFM_EVT, 0,
    306                                     p_lcb->peer_addr);
    307 }
    308 
    309 /*******************************************************************************
    310  *
    311  * Function         avct_bcb_chk_disc
    312  *
    313  * Description      A ccb wants to close; if it is the last ccb on this lcb,
    314  *                  close channel.  Otherwise just deallocate and call
    315  *                  callback.
    316  *
    317  *
    318  * Returns          Nothing.
    319  *
    320  ******************************************************************************/
    321 void avct_bcb_chk_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    322   p_bcb->ch_close = avct_bcb_get_last_ccb_index(p_bcb, p_data->p_ccb);
    323   if (p_bcb->ch_close) {
    324     avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
    325     return;
    326   }
    327 
    328   avct_bcb_unbind_disc(p_bcb, p_data);
    329 }
    330 
    331 /*******************************************************************************
    332  *
    333  * Function         avct_bcb_chnl_disc
    334  *
    335  * Description      Disconnect L2CAP channel.
    336  *
    337  *
    338  * Returns          Nothing.
    339  *
    340  ******************************************************************************/
    341 void avct_bcb_chnl_disc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    342   L2CA_DisconnectReq(p_bcb->ch_lcid);
    343 }
    344 
    345 /*******************************************************************************
    346  *
    347  * Function         avct_bcb_bind_fail
    348  *
    349  * Description      Deallocate ccb and call callback with connect event
    350  *                  with failure result.
    351  *
    352  *
    353  * Returns          Nothing.
    354  *
    355  ******************************************************************************/
    356 void avct_bcb_bind_fail(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    357   p_data->p_ccb->p_bcb = NULL;
    358   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
    359                                     AVCT_BROWSE_CONN_CFM_EVT, AVCT_RESULT_FAIL,
    360                                     NULL);
    361 }
    362 
    363 /*******************************************************************************
    364  *
    365  * Function         avct_bcb_cong_ind
    366  *
    367  * Description      Handle congestion indication from L2CAP.
    368  *
    369  *
    370  * Returns          Nothing.
    371  *
    372  ******************************************************************************/
    373 void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    374   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    375   uint8_t event;
    376   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
    377 
    378   /* set event */
    379   event =
    380       (p_data->cong) ? AVCT_BROWSE_CONG_IND_EVT : AVCT_BROWSE_UNCONG_IND_EVT;
    381 
    382   /* send event to all ccbs on this lcb */
    383   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    384     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
    385       (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0,
    386                                 p_lcb->peer_addr);
    387     }
    388   }
    389 }
    390 
    391 /*******************************************************************************
    392  *
    393  * Function         avct_bcb_discard_msg
    394  *
    395  * Description      Discard a message sent in from the API.
    396  *
    397  *
    398  * Returns          Nothing.
    399  *
    400  ******************************************************************************/
    401 void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    402   osi_free_and_reset((void**)&p_bcb->p_tx_msg);
    403 
    404   /* if control channel is up, save the message and open the browsing channel */
    405   if (p_data->ul_msg.p_ccb->p_lcb == NULL) {
    406     osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
    407     return;
    408   }
    409   p_bcb->p_tx_msg = p_data->ul_msg.p_buf;
    410 
    411   if (p_bcb->p_tx_msg) {
    412     p_bcb->p_tx_msg->layer_specific =
    413         (p_data->ul_msg.cr << 8) + p_data->ul_msg.label;
    414 
    415     /* the channel is closed, opening or closing - open it again */
    416     AVCT_TRACE_DEBUG("ch_state: %d, allocated:%d->%d", p_bcb->ch_state,
    417                      p_bcb->allocated, p_data->ul_msg.p_ccb->p_lcb->allocated);
    418     p_bcb->allocated = p_data->ul_msg.p_ccb->p_lcb->allocated;
    419     avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT,
    420                    (tAVCT_LCB_EVT*)p_data->ul_msg.p_ccb);
    421   }
    422 }
    423 
    424 /*******************************************************************************
    425  *
    426  * Function         avct_bcb_send_msg
    427  *
    428  * Description      Build and send an AVCTP message.
    429  *
    430  *
    431  * Returns          Nothing.
    432  *
    433  ******************************************************************************/
    434 void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    435   uint16_t curr_msg_len;
    436   uint8_t pkt_type = AVCT_PKT_TYPE_SINGLE;
    437   uint8_t hdr_len;
    438   BT_HDR* p_buf;
    439   uint8_t* p;
    440 
    441   /* store msg len */
    442   curr_msg_len = p_data->ul_msg.p_buf->len;
    443 
    444   /* initialize packet type and other stuff */
    445   if (curr_msg_len > (p_bcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) {
    446     AVCT_TRACE_ERROR("%s msg len (%d) exceeds peer mtu(%d-%d)!!", __func__,
    447                      curr_msg_len, p_bcb->peer_mtu, AVCT_HDR_LEN_SINGLE);
    448     osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
    449     return;
    450   }
    451 
    452   /* set header len */
    453   hdr_len = avct_lcb_pkt_type_len[pkt_type];
    454   p_buf = p_data->ul_msg.p_buf;
    455 
    456   /* set up to build header */
    457   p_buf->len += hdr_len;
    458   p_buf->offset -= hdr_len;
    459   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
    460 
    461   /* build header */
    462   AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
    463   UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
    464 
    465   p_buf->layer_specific = AVCT_DATA_BROWSE;
    466 
    467   /* send message to L2CAP */
    468   L2CA_DataWrite(p_bcb->ch_lcid, p_buf);
    469 }
    470 
    471 /*******************************************************************************
    472  *
    473  * Function         avct_bcb_free_msg_ind
    474  *
    475  * Description      Discard an incoming AVCTP message.
    476  *
    477  *
    478  * Returns          Nothing.
    479  *
    480  ******************************************************************************/
    481 void avct_bcb_free_msg_ind(UNUSED_ATTR tAVCT_BCB* p_bcb,
    482                            tAVCT_LCB_EVT* p_data) {
    483   if (p_data) osi_free_and_reset((void**)&p_data->p_buf);
    484 }
    485 
    486 /*******************************************************************************
    487  *
    488  * Function         avct_bcb_msg_ind
    489  *
    490  * Description      Handle an incoming AVCTP message.
    491  *
    492  *
    493  * Returns          Nothing.
    494  *
    495  ******************************************************************************/
    496 void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    497   uint8_t* p;
    498   uint8_t label, type, cr_ipid;
    499   uint16_t pid;
    500   tAVCT_CCB* p_ccb;
    501   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
    502 
    503   if ((p_data == NULL) || (p_data->p_buf == NULL)) {
    504     AVCT_TRACE_WARNING("%s p_data is NULL, returning!", __func__);
    505     return;
    506   }
    507 
    508   /* this p_buf is to be reported through p_msg_cback. The layer_specific
    509    * needs to be set properly to indicate that it is received through
    510    * browsing channel */
    511   p_data->p_buf->layer_specific = AVCT_DATA_BROWSE;
    512 
    513   /* reassemble message; if no message available (we received a fragment) return
    514    */
    515   p_data->p_buf = avct_bcb_msg_asmbl(p_bcb, p_data->p_buf);
    516   if (p_data->p_buf == NULL) {
    517     return;
    518   }
    519 
    520   p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset;
    521 
    522   /* parse header byte */
    523   AVCT_PARSE_HDR(p, label, type, cr_ipid);
    524 
    525   /* check for invalid cr_ipid */
    526   if (cr_ipid == AVCT_CR_IPID_INVALID) {
    527     AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
    528     osi_free_and_reset((void**)&p_data->p_buf);
    529     return;
    530   }
    531 
    532   /* parse and lookup PID */
    533   BE_STREAM_TO_UINT16(pid, p);
    534   p_ccb = avct_lcb_has_pid(p_lcb, pid);
    535   if (p_ccb) {
    536     /* PID found; send msg up, adjust bt hdr and call msg callback */
    537     p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
    538     p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
    539     (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
    540                              p_data->p_buf);
    541     return;
    542   }
    543 
    544   /* PID not found; drop message */
    545   AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
    546   osi_free_and_reset((void**)&p_data->p_buf);
    547 
    548   /* if command send reject */
    549   if (cr_ipid == AVCT_CMD) {
    550     BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVRC_CMD_BUF_SIZE);
    551     p_buf->len = AVCT_HDR_LEN_SINGLE;
    552     p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
    553     p = (uint8_t*)(p_buf + 1) + p_buf->offset;
    554     AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
    555     UINT16_TO_BE_STREAM(p, pid);
    556     p_buf->layer_specific = AVCT_DATA_BROWSE;
    557     L2CA_DataWrite(p_bcb->ch_lcid, p_buf);
    558   }
    559 }
    560 
    561 /*******************************************************************************
    562  *
    563  * Function         avct_bcb_dealloc
    564  *
    565  * Description      Deallocate a browse control block.
    566  *
    567  *
    568  * Returns          void.
    569  *
    570  ******************************************************************************/
    571 void avct_bcb_dealloc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
    572   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    573 
    574   AVCT_TRACE_DEBUG("%s %d", __func__, p_bcb->allocated);
    575 
    576   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
    577     /* if ccb allocated and */
    578     if ((p_ccb->allocated) && (p_ccb->p_bcb == p_bcb)) {
    579       p_ccb->p_bcb = NULL;
    580       AVCT_TRACE_DEBUG("%s used by ccb: %d", __func__, idx);
    581       break;
    582     }
    583   }
    584 
    585   /* the browsing channel is down. Check if we have pending messages */
    586   osi_free_and_reset((void**)&p_bcb->p_tx_msg);
    587   memset(p_bcb, 0, sizeof(tAVCT_BCB));
    588 }
    589 
    590 /*******************************************************************************
    591  *
    592  * Function         avct_close_bcb
    593  *
    594  * Description      this function is called right before LCB disconnects.
    595  *
    596  *
    597  * Returns          Nothing.
    598  *
    599  ******************************************************************************/
    600 void avct_close_bcb(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    601   tAVCT_BCB* p_bcb = avct_bcb_by_lcb(p_lcb);
    602   if (p_bcb->allocated) {
    603     avct_bcb_event(p_bcb, AVCT_LCB_UL_UNBIND_EVT, p_data);
    604   }
    605 }
    606 
    607 /*******************************************************************************
    608  *
    609  * Function         avct_lcb_by_bcb
    610  *
    611  * Description      This lookup function finds the lcb for a bcb.
    612  *
    613  * Returns          pointer to the lcb.
    614  *
    615  ******************************************************************************/
    616 tAVCT_LCB* avct_lcb_by_bcb(tAVCT_BCB* p_bcb) {
    617   return &avct_cb.lcb[p_bcb->allocated - 1];
    618 }
    619 
    620 /*******************************************************************************
    621  *
    622  * Function         avct_bcb_by_lcb
    623  *
    624  * Description      This lookup function finds the bcb for a lcb.
    625  *
    626  * Returns          pointer to the lcb.
    627  *
    628  ******************************************************************************/
    629 tAVCT_BCB* avct_bcb_by_lcb(tAVCT_LCB* p_lcb) {
    630   return &avct_cb.bcb[p_lcb->allocated - 1];
    631 }
    632 
    633 /*******************************************************************************
    634  *
    635  * Function         avct_bcb_get_last_ccb_index
    636  *
    637  * Description      See if given ccb is only one on the bcb.
    638  *
    639  *
    640  * Returns          0, if ccb is last,  (ccb index + 1) otherwise.
    641  *
    642  ******************************************************************************/
    643 uint8_t avct_bcb_get_last_ccb_index(tAVCT_BCB* p_bcb, tAVCT_CCB* p_ccb_last) {
    644   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
    645   uint8_t idx = 0;
    646 
    647   for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
    648     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
    649       if (p_ccb != p_ccb_last) return 0;
    650       idx = (uint8_t)(i + 1);
    651     }
    652   }
    653   return idx;
    654 }
    655 
    656 /*******************************************************************************
    657  *
    658  * Function         avct_bcb_by_lcid
    659  *
    660  * Description      Find the BCB associated with the L2CAP LCID
    661  *
    662  *
    663  * Returns          pointer to the lcb, or NULL if none found.
    664  *
    665  ******************************************************************************/
    666 tAVCT_BCB* avct_bcb_by_lcid(uint16_t lcid) {
    667   tAVCT_BCB* p_bcb = &avct_cb.bcb[0];
    668   int idx;
    669 
    670   for (idx = 0; idx < AVCT_NUM_LINKS; idx++, p_bcb++) {
    671     if (p_bcb->allocated && (p_bcb->ch_lcid == lcid)) {
    672       return p_bcb;
    673     }
    674   }
    675 
    676   /* out of lcbs */
    677   AVCT_TRACE_WARNING("No bcb for lcid %x", lcid);
    678   return NULL;
    679 }
    680