Ejemplo n.º 1
0
/*******************************************************************************
**
** Function         avdt_ad_open_req
**
** Description      This function is called by a CCB or SCB to open a transport
**                  channel.  This function allocates and initializes a
**                  transport channel table entry.  The channel can be opened
**                  in two roles:  as an initiator or acceptor.  When opened
**                  as an initiator the function will start an L2CAP connection.
**                  When opened as an acceptor the function simply configures
**                  the table entry to listen for an incoming channel.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role)
{
    tAVDT_TC_TBL    *p_tbl;
    UINT16          lcid;

    if ((p_tbl = avdt_ad_tc_tbl_alloc(p_ccb)) == NULL) {
        AVDT_TRACE_ERROR("avdt_ad_open_req: Cannot allocate p_tbl");
        return;
    }


    p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
    AVDT_TRACE_DEBUG("avdt_ad_open_req: type: %d, role: %d, tcid:%d\n",
                     type, role, p_tbl->tcid);

    if (type == AVDT_CHAN_SIG) {
        /* if signaling, get mtu from registration control block */
        p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
        p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
    } else {
        /* otherwise get mtu from scb */
        p_tbl->my_mtu = p_scb->cs.mtu;
        p_tbl->my_flush_to = p_scb->cs.flush_to;

        /* also set scb_hdl in rt_tbl */
        avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb);
        AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d\n",
                         avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
                         avdt_scb_to_hdl(p_scb));
    }

    /* if we're acceptor, we're done; just sit back and listen */
    if (role == AVDT_ACP) {
        p_tbl->state = AVDT_AD_ST_ACP;
    }
    /* else we're inititator, start the L2CAP connection */
    else {
        p_tbl->state = AVDT_AD_ST_CONN;

        /* call l2cap connect req */
        if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0) {
            /* if connect req ok, store tcid in lcid table  */
            avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
            AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d\n",
                             (lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl));

            avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
            AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x\n",
                             avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
                             lcid);
        } else {
            /* if connect req failed, call avdt_ad_tc_close_ind() */
            avdt_ad_tc_close_ind(p_tbl, 0);
        }
    }
}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         avdt_scb_verify
**
** Description      Verify the condition of a list of scbs.
**
**
** Returns          SEID that failed, or 0 if success.
**
*******************************************************************************/
UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code)
{
    int         i;
    tAVDT_SCB   *p_scb;
    UINT8       nsc_mask;
    UINT8       chk_state;
    UINT8       ret = 0;

    AVDT_TRACE_DEBUG("avdt_scb_verify state %d", state);
    /* set nonsupported command mask */
    /* translate public state into private state */
    nsc_mask = 0;
    chk_state = AVDT_SCB_STREAM_ST;
    switch(state)
    {
    case AVDT_VERIFY_SUSPEND:
        nsc_mask = AVDT_NSC_SUSPEND;
        break;
    case AVDT_VERIFY_OPEN:
    case AVDT_VERIFY_START:
        chk_state = AVDT_SCB_OPEN_ST;
        break;
    }

    /* verify every scb */
    for (i = 0; i < num_seid; i++)
    {
        if ((p_scb = avdt_scb_by_hdl(p_seid[i])) == NULL)
        {
            *p_err_code = AVDT_ERR_BAD_STATE;
            break;
        }
        else if ((p_scb->state != chk_state) || (p_scb->p_ccb != p_ccb))
        {
            *p_err_code = AVDT_ERR_BAD_STATE;
            break;
        }
        else if (p_scb->cs.nsc_mask & nsc_mask)
        {
            *p_err_code = AVDT_ERR_NSC;
            break;
        }
    }

    if (i != num_seid)
    {
        ret = p_seid[i];
    }
    AVDT_TRACE_DEBUG("avdt_scb_verify state %d, nsc_mask0x%x, ret: %d",
        chk_state, nsc_mask, ret);
    return ret;
}
Ejemplo n.º 3
0
/*******************************************************************************
**
** Function         avdt_sec_check_complete_orig
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
        void *p_ref_data, UINT8 res)
{
    tAVDT_CCB       *p_ccb = NULL;
    tL2CAP_CFG_INFO cfg;
    tAVDT_TC_TBL    *p_tbl;
    UNUSED(p_ref_data);

    AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res);
    if (bd_addr) {
        p_ccb = avdt_ccb_by_bd(bd_addr);
    }
    p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
    if (p_tbl == NULL) {
        return;
    }

    if ( res == BTM_SUCCESS ) {
        /* set channel state */
        p_tbl->state = AVDT_AD_ST_CFG;

        /* Send L2CAP config req */
        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
        cfg.mtu_present = TRUE;
        cfg.mtu = p_tbl->my_mtu;
        cfg.flush_to_present = TRUE;
        cfg.flush_to = p_tbl->my_flush_to;
        L2CA_ConfigReq(p_tbl->lcid, &cfg);
    } else {
        L2CA_DisconnectReq (p_tbl->lcid);
        avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
Ejemplo n.º 4
0
/*******************************************************************************
**
** Function         avdt_l2c_config_ind_cback
**
** Description      This is the L2CAP config indication callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
{
    tAVDT_TC_TBL    *p_tbl;

    /* look up info for this channel */
    if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) {
        /* store the mtu in tbl */
        if (p_cfg->mtu_present) {
            p_tbl->peer_mtu = p_cfg->mtu;
        } else {
            p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
        }
        AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x\n", p_tbl->peer_mtu, lcid);

        /* send L2CAP configure response */
        memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
        p_cfg->result = L2CAP_CFG_OK;
        L2CA_ConfigRsp(lcid, p_cfg);

        /* if first config ind */
        if ((p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) == 0) {
            /* update cfg_flags */
            p_tbl->cfg_flags |= AVDT_L2C_CFG_IND_DONE;

            /* if configuration complete */
            if (p_tbl->cfg_flags & AVDT_L2C_CFG_CFM_DONE) {
                avdt_ad_tc_open_ind(p_tbl);
            }
        }
    }
}
Ejemplo n.º 5
0
/*******************************************************************************
**
** Function         avdt_ad_tc_close_ind
**
** Description      This function is called by the L2CAP interface when the
**                  L2CAP channel is closed.  It looks up the CCB or SCB for
**                  the channel and sends it a close event.  The reason
**                  parameter is the same value passed by the L2CAP
**                  callback function.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
{
    tAVDT_CCB   *p_ccb;
    tAVDT_SCB   *p_scb;
    tAVDT_SCB_TC_CLOSE  close;
    // UNUSED(reason);

    close.old_tc_state = p_tbl->state;

    /* clear avdt_ad_tc_tbl entry */
    p_tbl->state = AVDT_AD_ST_UNUSED;
    p_tbl->cfg_flags = 0;
    p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;

    AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d\n",
                     p_tbl->tcid, close.old_tc_state);

    /* if signaling channel, notify ccb that channel open */
    if (p_tbl->tcid == 0) {
        p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
        p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
        avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
    }
    /* if media or other channel, notify scb that channel close */
    else {
        /* look up scb in stream routing table by ccb, tcid */
        p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
        if (p_scb != NULL) {
            close.tcid = p_tbl->tcid;
            close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
            close.disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
            avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
        }
    }
}
Ejemplo n.º 6
0
/*******************************************************************************
**
** Function         AVDT_SINK_Deactivate
**
** Description      Deactivate SEP of A2DP Sink. In Use parameter is adjusted.
**                  In Use will be made TRUE in case of activation. A2DP SRC
**                  will receive in_use as true and will not open A2DP Sink
**                  connection
**
** Returns          void.
**
*******************************************************************************/
void AVDT_SINK_Deactivate()
{
    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
    int                 i;
    AVDT_TRACE_DEBUG("AVDT_SINK_Deactivate");
    /* for all allocated scbs */
    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
        if ((p_scb->allocated) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) {
            AVDT_TRACE_DEBUG("AVDT_SINK_Deactivate, found scb");
            p_scb->sink_activated = FALSE;
            /* update in_use */
            p_scb->in_use = TRUE;
            break;
        }
    }
}
Ejemplo n.º 7
0
/*******************************************************************************
**
** Function         avdt_l2c_disconnect_cfm_cback
**
** Description      This is the L2CAP disconnect confirm callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
{
    tAVDT_TC_TBL    *p_tbl;

    AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d\n",
                     lcid, result);
    /* look up info for this channel */
    if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) {
        avdt_ad_tc_close_ind(p_tbl, result);
    }
}
Ejemplo n.º 8
0
/*******************************************************************************
**
** Function         avdt_scb_alloc
**
** Description      Allocate a stream control block.
**
**
** Returns          pointer to the scb, or NULL if none could be allocated.
**
*******************************************************************************/
tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs)
{
    tAVDT_SCB   *p_scb = &avdt_cb.scb[0];
    int         i;

    /* find available scb */
    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
    {
        if (!p_scb->allocated)
        {
            memset(p_scb,0,sizeof(tAVDT_SCB));
            p_scb->allocated = TRUE;
            p_scb->p_ccb = NULL;

            /* initialize sink as activated */
            if (p_cs->tsep == AVDT_TSEP_SNK)
            {
                p_scb->sink_activated = TRUE;
            }

            memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
#if AVDT_MULTIPLEXING == TRUE
            /* initialize fragments gueue */
            GKI_init_q(&p_scb->frag_q);

            if(p_cs->cfg.psc_mask & AVDT_PSC_MUX)
            {
                p_scb->cs.cfg.mux_tcid_media = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
#if AVDT_REPORTING == TRUE
                if(p_cs->cfg.psc_mask & AVDT_PSC_REPORT)
                {
                    p_scb->cs.cfg.mux_tcid_report = avdt_ad_type_to_tcid(AVDT_CHAN_REPORT, p_scb);
                }
#endif
            }
#endif
            p_scb->timer_entry.param = (UINT32) p_scb;
            AVDT_TRACE_DEBUG("avdt_scb_alloc hdl=%d, psc_mask:0x%x", i+1, p_cs->cfg.psc_mask);
            break;
        }
    }

    if (i == AVDT_NUM_SEPS)
    {
        /* out of ccbs */
        p_scb = NULL;
        AVDT_TRACE_WARNING("Out of scbs");
    }

    return p_scb;
}
Ejemplo n.º 9
0
/*******************************************************************************
**
** Function         avdt_l2c_connect_cfm_cback
**
** Description      This is the L2CAP connect confirm callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
{
    tAVDT_TC_TBL    *p_tbl;
    tL2CAP_CFG_INFO cfg;
    tAVDT_CCB *p_ccb;

    AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d\n",
                     lcid, result);
    /* look up info for this channel */
    if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) {
        /* if in correct state */
        if (p_tbl->state == AVDT_AD_ST_CONN) {
            /* if result successful */
            if (result == L2CAP_CONN_OK) {
                if (p_tbl->tcid != AVDT_CHAN_SIG) {
                    /* set channel state */
                    p_tbl->state = AVDT_AD_ST_CFG;

                    /* Send L2CAP config req */
                    memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
                    cfg.mtu_present = TRUE;
                    cfg.mtu = p_tbl->my_mtu;
                    cfg.flush_to_present = TRUE;
                    cfg.flush_to = p_tbl->my_flush_to;
                    L2CA_ConfigReq(lcid, &cfg);
                } else {
                    p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
                    if (p_ccb == NULL) {
                        result = L2CAP_CONN_NO_RESOURCES;
                    } else {
                        /* set channel state */
                        p_tbl->state = AVDT_AD_ST_SEC_INT;
                        p_tbl->lcid = lcid;
                        p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;

                        /* Check the security */
                        btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
                                                   TRUE, BTM_SEC_PROTO_AVDT,
                                                   AVDT_CHAN_SIG,
                                                   &avdt_sec_check_complete_orig, NULL);
                    }
                }
            }

            /* failure; notify adaption that channel closed */
            if (result != L2CAP_CONN_OK) {
                avdt_ad_tc_close_ind(p_tbl, result);
            }
        }
    }
}
Ejemplo n.º 10
0
/*******************************************************************************
**
** Function         avdt_scb_dealloc
**
** Description      Deallocate a stream control block.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
{
    UNUSED(p_data);

    AVDT_TRACE_DEBUG("avdt_scb_dealloc hdl=%d\n", avdt_scb_to_hdl(p_scb));
    btu_stop_timer(&p_scb->timer_entry);

#if AVDT_MULTIPLEXING == TRUE
    /* free fragments we're holding, if any; it shouldn't happen */
    fixed_queue_free(p_scb->frag_q, osi_free_func);
#endif

    memset(p_scb, 0, sizeof(tAVDT_SCB));
}
Ejemplo n.º 11
0
/*******************************************************************************
**
** Function         avdt_scb_verify
**
** Description      Verify the condition of a list of scbs.
**
**
** Returns          SEID that failed, or 0 if success.
**
*******************************************************************************/
UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code)
{
    int         i;
    tAVDT_SCB   *p_scb;
    UINT8       nsc_mask;
    UINT8       ret = 0;

    AVDT_TRACE_DEBUG("avdt_scb_verify state %d\n", state);
    /* set nonsupported command mask */
    /* translate public state into private state */
    nsc_mask = 0;
    if (state == AVDT_VERIFY_SUSPEND) {
        nsc_mask = AVDT_NSC_SUSPEND;
    }

    /* verify every scb */
    for (i = 0, *p_err_code = 0; (i < num_seid) && (*p_err_code == 0) && (i < AVDT_NUM_SEPS); i++) {
        if ((p_scb = avdt_scb_by_hdl(p_seid[i])) == NULL) {
            *p_err_code = AVDT_ERR_BAD_STATE;
        } else if (p_scb->p_ccb != p_ccb) {
            *p_err_code = AVDT_ERR_BAD_STATE;
        } else if (p_scb->cs.nsc_mask & nsc_mask) {
            *p_err_code = AVDT_ERR_NSC;
        }

        switch (state) {
        case AVDT_VERIFY_OPEN:
        case AVDT_VERIFY_START:
            if (p_scb->state != AVDT_SCB_OPEN_ST && p_scb->state != AVDT_SCB_STREAM_ST) {
                *p_err_code = AVDT_ERR_BAD_STATE;
            }
            break;

        case AVDT_VERIFY_SUSPEND:
        case AVDT_VERIFY_STREAMING:
            if (p_scb->state != AVDT_SCB_STREAM_ST) {
                *p_err_code = AVDT_ERR_BAD_STATE;
            }
            break;
        }
    }

    if ((i != num_seid) && (i < AVDT_NUM_SEPS)) {
        ret = p_seid[i];
    }

    return ret;
}
Ejemplo n.º 12
0
/*******************************************************************************
**
** Function         avdt_ad_tcid_to_type
**
** Description      Derives the channel type from the TCID.
**
**
** Returns          Channel type value.
**
*******************************************************************************/
static UINT8 avdt_ad_tcid_to_type(UINT8 tcid)
{
    UINT8 type;

    if (tcid == 0) {
        type = AVDT_CHAN_SIG;
    } else {
        /* tcid translates to type based on number of channels, as follows:
        ** only media channel   :  tcid=1,2,3,4,5,6...  type=1,1,1,1,1,1...
        ** media and report     :  tcid=1,2,3,4,5,6...  type=1,2,1,2,1,2...
        ** media, report, recov :  tcid=1,2,3,4,5,6...  type=1,2,3,1,2,3...
        */
        type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1;
    }
    AVDT_TRACE_DEBUG("tcid: %d, type: %d\n", tcid, type);
    return type;
}
Ejemplo n.º 13
0
/*******************************************************************************
**
** Function         avdt_l2c_disconnect_ind_cback
**
** Description      This is the L2CAP disconnect indication callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
{
    tAVDT_TC_TBL    *p_tbl;
    UINT16          disc_rsn = AVDT_DISC_RSN_NORMAL;
    AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d\n",
                     lcid, ack_needed);
    /* look up info for this channel */
    if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) {
        if (ack_needed) {
            /* send L2CAP disconnect response */
            L2CA_DisconnectRsp(lcid);
        } else {
            disc_rsn = AVDT_DISC_RSN_ABNORMAL;
        }

        avdt_ad_tc_close_ind(p_tbl, disc_rsn);
    }
}
Ejemplo n.º 14
0
/*******************************************************************************
**
** Function         avdt_scb_dealloc
**
** Description      Deallocate a stream control block.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
{
#if AVDT_MULTIPLEXING == TRUE
    void *p_buf;
#endif
    UNUSED(p_data);

    AVDT_TRACE_DEBUG("avdt_scb_dealloc hdl=%d", avdt_scb_to_hdl(p_scb));
    btu_stop_timer(&p_scb->timer_entry);

#if AVDT_MULTIPLEXING == TRUE
    /* free fragments we're holding, if any; it shouldn't happen */
    while ((p_buf = GKI_dequeue (&p_scb->frag_q)) != NULL)
        GKI_freebuf(p_buf);
#endif

    memset(p_scb, 0, sizeof(tAVDT_SCB));
}
Ejemplo n.º 15
0
/*******************************************************************************
**
** Function         avdt_sec_check_complete_term
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport,
        void *p_ref_data, UINT8 res)
{
    tAVDT_CCB       *p_ccb = NULL;
    tL2CAP_CFG_INFO cfg;
    tAVDT_TC_TBL    *p_tbl;
    UNUSED(p_ref_data);

    AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res);
    if (!bd_addr) {
        AVDT_TRACE_WARNING("avdt_sec_check_complete_term: NULL BD_ADDR");
        return;

    }
    p_ccb = avdt_ccb_by_bd(bd_addr);

    p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP);
    if (p_tbl == NULL) {
        return;
    }

    if (res == BTM_SUCCESS) {
        /* Send response to the L2CAP layer. */
        L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);

        /* store idx in LCID table, store LCID in routing table */
        avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
        avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;

        /* transition to configuration state */
        p_tbl->state = AVDT_AD_ST_CFG;

        /* Send L2CAP config req */
        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
        cfg.mtu_present = TRUE;
        cfg.mtu = p_tbl->my_mtu;
        cfg.flush_to_present = TRUE;
        cfg.flush_to = p_tbl->my_flush_to;
        L2CA_ConfigReq(p_tbl->lcid, &cfg);
    } else {
        L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
        avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
Ejemplo n.º 16
0
/*******************************************************************************
**
** Function         avdt_ad_close_req
**
** Description      This function is called by a CCB or SCB to close a
**                  transport channel.  The function looks up the LCID for the
**                  channel and calls L2CA_DisconnectReq().
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
{
    UINT8           tcid;
    tAVDT_TC_TBL    *p_tbl;

    p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
    AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state);

    switch (p_tbl->state) {
    case AVDT_AD_ST_UNUSED:
        /* probably for reporting */
        break;
    case AVDT_AD_ST_ACP:
        /* if we're listening on this channel, send ourselves a close ind */
        avdt_ad_tc_close_ind(p_tbl, 0);
        break;
    default:
        /* get tcid from type, scb */
        tcid = avdt_ad_type_to_tcid(type, p_scb);

        /* call l2cap disconnect req */
        L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
    }
}
Ejemplo n.º 17
0
/*******************************************************************************
**
** Function         avdt_ad_tc_tbl_to_idx
**
** Description      Convert a transport channel table entry to an index.
**
**
** Returns          Index value.
**
*******************************************************************************/
UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl)
{
    AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d\n", (p_tbl - avdt_cb.ad.tc_tbl));
    /* use array arithmetic to determine index */
    return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl);
}