Home | History | Annotate | Download | only in avdt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2002-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 the AVDTP adaption layer.
     22  *
     23  ******************************************************************************/
     24 
     25 #include <string.h>
     26 #include "data_types.h"
     27 #include "bt_target.h"
     28 #include "bt_utils.h"
     29 #include "avdt_api.h"
     30 #include "avdtc_api.h"
     31 #include "avdt_int.h"
     32 #include "l2c_api.h"
     33 #include "l2cdefs.h"
     34 #include "wcassert.h"
     35 
     36 
     37 /*******************************************************************************
     38 **
     39 ** Function         avdt_ad_type_to_tcid
     40 **
     41 ** Description      Derives the TCID from the channel type and SCB.
     42 **
     43 **
     44 ** Returns          TCID value.
     45 **
     46 *******************************************************************************/
     47 UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb)
     48 {
     49     UINT8 scb_idx;
     50 
     51     if (type == AVDT_CHAN_SIG)
     52     {
     53         return 0;
     54     }
     55     else
     56     {
     57         scb_idx = avdt_scb_to_hdl(p_scb) - 1;
     58         /*
     59         AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type));
     60         */
     61         return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
     62     }
     63 }
     64 
     65 /*******************************************************************************
     66 **
     67 ** Function         avdt_ad_tcid_to_type
     68 **
     69 ** Description      Derives the channel type from the TCID.
     70 **
     71 **
     72 ** Returns          Channel type value.
     73 **
     74 *******************************************************************************/
     75 static UINT8 avdt_ad_tcid_to_type(UINT8 tcid)
     76 {
     77     UINT8 type;
     78 
     79     if (tcid == 0)
     80     {
     81         type = AVDT_CHAN_SIG;
     82     }
     83     else
     84     {
     85         /* tcid translates to type based on number of channels, as follows:
     86         ** only media channel   :  tcid=1,2,3,4,5,6...  type=1,1,1,1,1,1...
     87         ** media and report     :  tcid=1,2,3,4,5,6...  type=1,2,1,2,1,2...
     88         ** media, report, recov :  tcid=1,2,3,4,5,6...  type=1,2,3,1,2,3...
     89         */
     90         type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1;
     91     }
     92     AVDT_TRACE_DEBUG("tcid: %d, type: %d", tcid, type);
     93     return type;
     94 }
     95 
     96 
     97 /*******************************************************************************
     98 **
     99 ** Function         avdt_ad_init
    100 **
    101 ** Description      Initialize adaption layer.
    102 **
    103 **
    104 ** Returns          Nothing.
    105 **
    106 *******************************************************************************/
    107 void avdt_ad_init(void)
    108 {
    109     int             i;
    110     tAVDT_TC_TBL    *p_tbl = avdt_cb.ad.tc_tbl;
    111     memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
    112 
    113     /* make sure the peer_mtu is a valid value */
    114     for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
    115     {
    116         p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
    117     }
    118 }
    119 
    120 
    121 /*******************************************************************************
    122 **
    123 ** Function         avdt_ad_tc_tbl_by_st
    124 **
    125 ** Description      Find adaption layer transport channel table entry matching
    126 **                  the given state.
    127 **
    128 **
    129 ** Returns          Pointer to matching entry.  For control channel it returns
    130 **                  the matching entry.  For media or other it returns the
    131 **                  first matching entry (there could be more than one).
    132 **
    133 *******************************************************************************/
    134 tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state)
    135 {
    136     int             i;
    137     tAVDT_TC_TBL    *p_tbl = avdt_cb.ad.tc_tbl;
    138     UINT8           ccb_idx;
    139 
    140     if (p_ccb == NULL)
    141     {
    142         /* resending security req */
    143         for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
    144         {
    145             /* must be AVDT_CHAN_SIG - tcid always zero */
    146             if ((p_tbl->tcid == 0) &&
    147                 (p_tbl->state == state))
    148             {
    149                 break;
    150             }
    151         }
    152     }
    153     else
    154     {
    155         ccb_idx = avdt_ccb_to_idx(p_ccb);
    156 
    157         for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
    158         {
    159             if (type == AVDT_CHAN_SIG)
    160             {
    161                 /* if control channel, tcid always zero */
    162                 if ((p_tbl->tcid == 0) &&
    163                     (p_tbl->ccb_idx == ccb_idx) &&
    164                     (p_tbl->state == state))
    165                 {
    166                     break;
    167                 }
    168             }
    169             else
    170             {
    171                 /* if other channel, tcid is always > zero */
    172                 if ((p_tbl->tcid > 0) &&
    173                     (p_tbl->ccb_idx == ccb_idx) &&
    174                     (p_tbl->state == state))
    175                 {
    176                     break;
    177                 }
    178             }
    179         }
    180     }
    181 
    182     /* if nothing found return null */
    183     if (i == AVDT_NUM_TC_TBL)
    184     {
    185         p_tbl = NULL;
    186     }
    187 
    188     return p_tbl;
    189 }
    190 
    191 
    192 /*******************************************************************************
    193 **
    194 ** Function         avdt_ad_tc_tbl_by_lcid
    195 **
    196 ** Description      Find adaption layer transport channel table entry by LCID.
    197 **
    198 **
    199 ** Returns          Pointer to entry.
    200 **
    201 *******************************************************************************/
    202 tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid)
    203 {
    204     UINT8 idx;
    205 
    206     idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
    207 
    208     if (idx < AVDT_NUM_TC_TBL)
    209     {
    210         return &avdt_cb.ad.tc_tbl[idx];
    211     }
    212     else
    213     {
    214         return NULL;
    215     }
    216 }
    217 
    218 
    219 /*******************************************************************************
    220 **
    221 ** Function         avdt_ad_tc_tbl_by_type
    222 **
    223 ** Description      This function retrieves the transport channel table entry
    224 **                  for a particular channel.
    225 **
    226 **
    227 ** Returns          Pointer to transport channel table entry.
    228 **
    229 *******************************************************************************/
    230 tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
    231 {
    232     UINT8           tcid;
    233     int             i;
    234     tAVDT_TC_TBL    *p_tbl = avdt_cb.ad.tc_tbl;
    235     UINT8           ccb_idx = avdt_ccb_to_idx(p_ccb);
    236 
    237     /* get tcid from type, scb */
    238     tcid = avdt_ad_type_to_tcid(type, p_scb);
    239 
    240     for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
    241     {
    242         if ((p_tbl->tcid == tcid) && (p_tbl->ccb_idx == ccb_idx))
    243         {
    244             break;
    245         }
    246     }
    247 
    248     WC_ASSERT(i != AVDT_NUM_TC_TBL);
    249 
    250     return p_tbl;
    251 }
    252 
    253 
    254 /*******************************************************************************
    255 **
    256 ** Function         avdt_ad_tc_tbl_alloc
    257 **
    258 ** Description      Allocate an entry in the traffic channel table.
    259 **
    260 **
    261 ** Returns          Pointer to entry.
    262 **
    263 *******************************************************************************/
    264 tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb)
    265 {
    266     int             i;
    267     tAVDT_TC_TBL    *p_tbl = avdt_cb.ad.tc_tbl;
    268 
    269     /* find next free entry in tc table */
    270     for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
    271     {
    272         if (p_tbl->state == AVDT_AD_ST_UNUSED)
    273         {
    274             break;
    275         }
    276     }
    277 
    278     /* sanity check */
    279     WC_ASSERT(i != AVDT_NUM_TC_TBL);
    280 
    281     /* initialize entry */
    282     p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
    283     p_tbl->cfg_flags = 0;
    284     p_tbl->ccb_idx = avdt_ccb_to_idx(p_ccb);
    285     p_tbl->state = AVDT_AD_ST_IDLE;
    286 
    287     return p_tbl;
    288 }
    289 
    290 /*******************************************************************************
    291 **
    292 ** Function         avdt_ad_tc_tbl_to_idx
    293 **
    294 ** Description      Convert a transport channel table entry to an index.
    295 **
    296 **
    297 ** Returns          Index value.
    298 **
    299 *******************************************************************************/
    300 UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl)
    301 {
    302     AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl));
    303     /* use array arithmetic to determine index */
    304     return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl);
    305 }
    306 
    307 /*******************************************************************************
    308 **
    309 ** Function         avdt_ad_tc_close_ind
    310 **
    311 ** Description      This function is called by the L2CAP interface when the
    312 **                  L2CAP channel is closed.  It looks up the CCB or SCB for
    313 **                  the channel and sends it a close event.  The reason
    314 **                  parameter is the same value passed by the L2CAP
    315 **                  callback function.
    316 **
    317 **
    318 ** Returns          Nothing.
    319 **
    320 *******************************************************************************/
    321 void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
    322 {
    323     tAVDT_CCB   *p_ccb;
    324     tAVDT_SCB   *p_scb;
    325     tAVDT_SCB_TC_CLOSE  close;
    326     UNUSED(reason);
    327 
    328     close.old_tc_state = p_tbl->state;
    329     /* clear avdt_ad_tc_tbl entry */
    330     p_tbl->state = AVDT_AD_ST_UNUSED;
    331     p_tbl->cfg_flags = 0;
    332     p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
    333 
    334     AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d",
    335         p_tbl->tcid, close.old_tc_state);
    336     /* if signaling channel, notify ccb that channel open */
    337     if (p_tbl->tcid == 0)
    338     {
    339         p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
    340         avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
    341     }
    342     /* if media or other channel, notify scb that channel close */
    343     else
    344     {
    345         /* look up scb in stream routing table by ccb, tcid */
    346         p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
    347         if (p_scb != NULL)
    348         {
    349             close.tcid = p_tbl->tcid;
    350             close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
    351             avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
    352         }
    353     }
    354 }
    355 
    356 /*******************************************************************************
    357 **
    358 ** Function         avdt_ad_tc_open_ind
    359 **
    360 ** Description      This function is called by the L2CAP interface when
    361 **                  the L2CAP channel is opened.  It looks up the CCB or SCB
    362 **                  for the channel and sends it an open event.
    363 **
    364 **
    365 ** Returns          Nothing.
    366 **
    367 *******************************************************************************/
    368 void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
    369 {
    370     tAVDT_CCB   *p_ccb;
    371     tAVDT_SCB   *p_scb;
    372     tAVDT_OPEN  open;
    373     tAVDT_EVT_HDR evt;
    374 
    375     p_tbl->state = AVDT_AD_ST_OPEN;
    376 
    377     /* if signaling channel, notify ccb that channel open */
    378     if (p_tbl->tcid == 0)
    379     {
    380         /* set the signal channel to use high priority within the ACL link */
    381         L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH);
    382 
    383         p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
    384         /* use err_param to indicate the role of connection.
    385          * AVDT_ACP, if ACP */
    386         evt.err_param = AVDT_INT;
    387         if(p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP)
    388         {
    389             evt.err_param = AVDT_ACP;
    390         }
    391         avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt);
    392     }
    393     /* if media or other channel, notify scb that channel open */
    394     else
    395     {
    396         /* look up scb in stream routing table by ccb, tcid */
    397         p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
    398 
    399         /* put lcid in event data */
    400         if (p_scb != NULL)
    401         {
    402             open.peer_mtu = p_tbl->peer_mtu;
    403             open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
    404             open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
    405             avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open);
    406         }
    407     }
    408 }
    409 
    410 
    411 /*******************************************************************************
    412 **
    413 ** Function         avdt_ad_tc_cong_ind
    414 **
    415 ** Description      This function is called by the L2CAP interface layer when
    416 **                  L2CAP calls the congestion callback.  It looks up the CCB
    417 **                  or SCB for the channel and sends it a congestion event.
    418 **                  The is_congested parameter is the same value passed by
    419 **                  the L2CAP callback function.
    420 **
    421 **
    422 ** Returns          Nothing.
    423 **
    424 *******************************************************************************/
    425 void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
    426 {
    427     tAVDT_CCB   *p_ccb;
    428     tAVDT_SCB   *p_scb;
    429 
    430     /* if signaling channel, notify ccb of congestion */
    431     if (p_tbl->tcid == 0)
    432     {
    433         p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
    434         avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested);
    435     }
    436     /* if media or other channel, notify scb that channel open */
    437     else
    438     {
    439         /* look up scb in stream routing table by ccb, tcid */
    440         p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
    441         if (p_scb != NULL)
    442         {
    443             avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested);
    444         }
    445     }
    446 }
    447 
    448 
    449 /*******************************************************************************
    450 **
    451 ** Function         avdt_ad_tc_data_ind
    452 **
    453 ** Description      This function is called by the L2CAP interface layer when
    454 **                  incoming data is received from L2CAP.  It looks up the CCB
    455 **                  or SCB for the channel and routes the data accordingly.
    456 **
    457 **
    458 ** Returns          Nothing.
    459 **
    460 *******************************************************************************/
    461 void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
    462 {
    463     tAVDT_CCB   *p_ccb;
    464     tAVDT_SCB   *p_scb;
    465 
    466     /* store type (media, recovery, reporting) */
    467     p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
    468 
    469 
    470     /* if signaling channel, handle control message */
    471     if (p_tbl->tcid == 0)
    472     {
    473         p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
    474         avdt_msg_ind(p_ccb, p_buf);
    475     }
    476     /* if media or other channel, send event to scb */
    477     else
    478     {
    479         p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
    480         if (p_scb != NULL)
    481         {
    482             avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
    483         }
    484         else
    485         {
    486             GKI_freebuf(p_buf);
    487             AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
    488         }
    489     }
    490 }
    491 
    492 /*******************************************************************************
    493 **
    494 ** Function         avdt_ad_write_req
    495 **
    496 ** Description      This function is called by a CCB or SCB to send data to a
    497 **                  transport channel.  It looks up the LCID of the channel
    498 **                  based on the type, CCB, and SCB (if present).  Then it
    499 **                  passes the data to L2CA_DataWrite().
    500 **
    501 **
    502 ** Returns          AVDT_AD_SUCCESS, if data accepted, else FALSE
    503 **                  AVDT_AD_CONGESTED, if data accepted and the channel is congested
    504 **                  AVDT_AD_FAILED, if error
    505 **
    506 *******************************************************************************/
    507 UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf)
    508 {
    509     UINT8   tcid;
    510 
    511     /* get tcid from type, scb */
    512     tcid = avdt_ad_type_to_tcid(type, p_scb);
    513 
    514 
    515     return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
    516 }
    517 
    518 
    519 /*******************************************************************************
    520 **
    521 ** Function         avdt_ad_open_req
    522 **
    523 ** Description      This function is called by a CCB or SCB to open a transport
    524 **                  channel.  This function allocates and initializes a
    525 **                  transport channel table entry.  The channel can be opened
    526 **                  in two roles:  as an initiator or acceptor.  When opened
    527 **                  as an initiator the function will start an L2CAP connection.
    528 **                  When opened as an acceptor the function simply configures
    529 **                  the table entry to listen for an incoming channel.
    530 **
    531 **
    532 ** Returns          Nothing.
    533 **
    534 *******************************************************************************/
    535 void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role)
    536 {
    537     tAVDT_TC_TBL    *p_tbl;
    538     UINT16          lcid;
    539 
    540     p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
    541 
    542     p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
    543     AVDT_TRACE_DEBUG("avdt_ad_open_req: type: %d, role: %d, tcid:%d",
    544         type, role, p_tbl->tcid);
    545 
    546     if (type == AVDT_CHAN_SIG)
    547     {
    548         /* if signaling, get mtu from registration control block */
    549         p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
    550         p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
    551     }
    552     else
    553     {
    554         /* otherwise get mtu from scb */
    555         p_tbl->my_mtu = p_scb->cs.mtu;
    556         p_tbl->my_flush_to = p_scb->cs.flush_to;
    557 
    558         /* also set scb_hdl in rt_tbl */
    559         avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb);
    560         AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
    561             avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
    562             avdt_scb_to_hdl(p_scb));
    563     }
    564 
    565     /* if we're acceptor, we're done; just sit back and listen */
    566     if (role == AVDT_ACP)
    567     {
    568         p_tbl->state = AVDT_AD_ST_ACP;
    569     }
    570     /* else we're inititator, start the L2CAP connection */
    571     else
    572     {
    573         p_tbl->state = AVDT_AD_ST_CONN;
    574 
    575         /* call l2cap connect req */
    576         if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0)
    577         {
    578             /* if connect req ok, store tcid in lcid table  */
    579             avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
    580             AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d",
    581                 (lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl));
    582 
    583             avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
    584             AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
    585                 avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
    586                 lcid);
    587         }
    588         else
    589         {
    590             /* if connect req failed, call avdt_ad_tc_close_ind() */
    591             avdt_ad_tc_close_ind(p_tbl, 0);
    592         }
    593     }
    594 }
    595 
    596 /*******************************************************************************
    597 **
    598 ** Function         avdt_ad_close_req
    599 **
    600 ** Description      This function is called by a CCB or SCB to close a
    601 **                  transport channel.  The function looks up the LCID for the
    602 **                  channel and calls L2CA_DisconnectReq().
    603 **
    604 **
    605 ** Returns          Nothing.
    606 **
    607 *******************************************************************************/
    608 void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
    609 {
    610     UINT8           tcid;
    611     tAVDT_TC_TBL    *p_tbl;
    612 
    613     p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
    614     AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d", p_tbl->state);
    615 
    616     switch(p_tbl->state)
    617     {
    618     case AVDT_AD_ST_UNUSED:
    619         /* probably for reporting */
    620         break;
    621     case AVDT_AD_ST_ACP:
    622         /* if we're listening on this channel, send ourselves a close ind */
    623         avdt_ad_tc_close_ind(p_tbl, 0);
    624         break;
    625     default:
    626         /* get tcid from type, scb */
    627         tcid = avdt_ad_type_to_tcid(type, p_scb);
    628 
    629         /* call l2cap disconnect req */
    630         L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
    631     }
    632 }
    633 
    634