Пример #1
0
/*******************************************************************************
**
** Function         AVDT_WriteDataReq
**
** Description      Send a media packet to the peer device.  The stream must
**                  be started before this function is called.  Also, this
**                  function can only be called if the stream is a SRC.
**
**                  When AVDTP has sent the media packet and is ready for the
**                  next packet, an AVDT_WRITE_CFM_EVT is sent to the
**                  application via the control callback.  The application must
**                  wait for the AVDT_WRITE_CFM_EVT before it makes the next
**                  call to AVDT_WriteDataReq().  If the applications calls
**                  AVDT_WriteDataReq() before it receives the event the packet
**                  will not be sent.  The application may make its first call
**                  to AVDT_WriteDataReq() after it receives an
**                  AVDT_START_CFM_EVT or AVDT_START_IND_EVT.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
extern UINT16 AVDT_WriteDataReq(UINT8 handle, UINT8 *p_data, UINT32 data_len,
                                UINT32 time_stamp, UINT8 m_pt, UINT8 marker)
{

    tAVDT_SCB       *p_scb;
    tAVDT_SCB_EVT   evt;
    UINT16          result = AVDT_SUCCESS;

    do {
        /* check length of media frame */
        if (data_len > AVDT_MAX_MEDIA_SIZE) {
            result = AVDT_BAD_PARAMS;
            break;
        }
        /* map handle to scb */
        if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
            result = AVDT_BAD_HANDLE;
            break;
        }
        AVDT_TRACE_WARNING("mux_tsid_media:%d\n", p_scb->curr_cfg.mux_tsid_media);

        if (p_scb->p_pkt != NULL
                || p_scb->p_ccb == NULL
                || !GKI_queue_is_empty(&p_scb->frag_q)
                || p_scb->frag_off != 0
                || p_scb->curr_cfg.mux_tsid_media == 0) {
            result = AVDT_ERR_BAD_STATE;
            AVDT_TRACE_WARNING("p_scb->p_pkt=%p, p_scb->p_ccb=%p, IsQueueEmpty=%x, p_scb->frag_off=%x\n",
                               p_scb->p_pkt, p_scb->p_ccb, GKI_queue_is_empty(&p_scb->frag_q), p_scb->frag_off);
            break;
        }
        evt.apiwrite.p_buf = 0; /* it will indicate using of fragments queue frag_q */
        /* create queue of media fragments */
        GKI_init_q (&evt.apiwrite.frag_q);

        /* compose fragments from media payload and put fragments into gueue */
        avdt_scb_queue_frags(p_scb, &p_data, &data_len, &evt.apiwrite.frag_q);

        if (GKI_queue_is_empty(&evt.apiwrite.frag_q)) {
            AVDT_TRACE_WARNING("AVDT_WriteDataReq out of GKI buffers");
            result = AVDT_ERR_RESOURCE;
            break;
        }
        evt.apiwrite.data_len = data_len;
        evt.apiwrite.p_data = p_data;

        /* process the fragments queue */
        evt.apiwrite.time_stamp = time_stamp;
        evt.apiwrite.m_pt = m_pt | (marker << 7);
        avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
    } while (0);

#if (BT_USE_TRACES == TRUE)
    if (result != AVDT_SUCCESS) {
        AVDT_TRACE_WARNING("*** AVDT_WriteDataReq failed result=%d\n", result);
    }
#endif
    return result;
}
Пример #2
0
/*******************************************************************************
**
** Function         AVDT_ConnectReq
**
** Description      This function initiates an AVDTP signaling connection
**                  to the peer device.  When the connection is completed, an
**                  AVDT_CONNECT_IND_EVT is sent to the application via its
**                  control callback function.  If the connection attempt fails
**                  an AVDT_DISCONNECT_IND_EVT is sent.  The security mask
**                  parameter overrides the outgoing security mask set in
**                  AVDT_Register().
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_ConnectReq(BD_ADDR bd_addr, UINT8 sec_mask, tAVDT_CTRL_CBACK *p_cback)
{
    tAVDT_CCB       *p_ccb = NULL;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_CCB_EVT   evt;

    /* find channel control block for this bd addr; if none, allocate one */
    if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL) {
        if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL) {
            /* could not allocate channel control block */
            result = AVDT_NO_RESOURCES;
        }
    } else if (p_ccb->ll_opened == FALSE) {
        AVDT_TRACE_WARNING("AVDT_ConnectReq: CCB LL is in the middle of opening");

        /* ccb was already allocated for the incoming signalling. */
        result = AVDT_BUSY;
    }

    if (result == AVDT_SUCCESS) {
        /* send event to ccb */
        evt.connect.p_cback = p_cback;
        evt.connect.sec_mask = sec_mask;
        avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt);
    }
    return result;
}
Пример #3
0
/*******************************************************************************
**
** Function         avdt_scb_by_hdl
**
** Description      Given an scb handle (or seid), return a pointer to the scb.
**
**
** Returns          Pointer to scb or NULL if index is out of range or scb
**                  is not allocated.
**
*******************************************************************************/
tAVDT_SCB *avdt_scb_by_hdl(UINT8 hdl)
{
    tAVDT_SCB   *p_scb;

    /* verify index */
    if ((hdl > 0) && (hdl <= AVDT_NUM_SEPS)) {
        p_scb = &avdt_cb.scb[hdl - 1];

        /* verify scb is allocated */
        if (!p_scb->allocated) {
            p_scb = NULL;
            AVDT_TRACE_WARNING("scb hdl %d not allocated\n", hdl);
        }
    } else {
        p_scb = NULL;
        AVDT_TRACE_WARNING("scb hdl %d out of range\n", hdl);
    }
    return p_scb;
}
Пример #4
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;
}
Пример #5
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);
    }
}