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