/*******************************************************************************
**
** Function         AVDT_WriteReqOpt
**
** 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_WriteReq().  If the applications calls
**                  AVDT_WriteReq() before it receives the event the packet
**                  will not be sent.  The application may make its first call
**                  to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
**                  or AVDT_START_IND_EVT.
**
**                  The application passes the packet using the BT_HDR structure.
**                  This structure is described in section 2.1.  The offset
**                  field must be equal to or greater than AVDT_MEDIA_OFFSET
**                  (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used).
**                  This allows enough space in the buffer for the L2CAP and
**                  AVDTP headers.
**
**                  The memory pointed to by p_pkt must be a GKI buffer
**                  allocated by the application.  This buffer will be freed
**                  by the protocol stack; the application must not free
**                  this buffer.
**
**                  The opt parameter allows passing specific options like:
**                  - NO_RTP : do not add the RTP header to buffer
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt, tAVDT_DATA_OPT_MASK opt)
{
    tAVDT_SCB       *p_scb;
    tAVDT_SCB_EVT   evt;
    UINT16          result = AVDT_SUCCESS;

    BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
    {
        result = AVDT_BAD_HANDLE;
    }
    else
    {
        evt.apiwrite.p_buf = p_pkt;
        evt.apiwrite.time_stamp = time_stamp;
        evt.apiwrite.m_pt = m_pt;
        evt.apiwrite.opt = opt;
#if AVDT_MULTIPLEXING == TRUE
        GKI_init_q (&evt.apiwrite.frag_q);
#endif
        avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
    }

    return result;
}
/*******************************************************************************
**
** Function         avdt_ccb_cmd_fail
**
** Description      This function is called when there is a response timeout.
**                  The currently pending command is freed and we fake a
**                  reject message back to ourselves.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    tAVDT_MSG       msg;
    UINT8           evt;
    tAVDT_SCB       *p_scb;

    if (p_ccb->p_curr_cmd != NULL)
    {
        /* set up data */
        msg.hdr.err_code = p_data->err_code;
        msg.hdr.err_param = 0;
        msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);

        /* pretend that we received a rej message */
        evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1];

        if (evt & AVDT_CCB_MKR)
        {
            avdt_ccb_event(p_ccb, (UINT8) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
        }
        else
        {
            /* we get the scb out of the current cmd */
            p_scb = avdt_scb_by_hdl(*((UINT8 *)(p_ccb->p_curr_cmd + 1)));
            if (p_scb != NULL)
            {
                avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
            }
        }

        GKI_freebuf(p_ccb->p_curr_cmd);
        p_ccb->p_curr_cmd = NULL;
    }
}
/*******************************************************************************
**
** Function         AVDT_SetMediaBuf
**
** Description      Assigns buffer for media packets or forbids using of assigned
**                  buffer if argument p_buf is NULL. This function can only
**                  be called if the stream is a SNK.
**
**                  AVDTP uses this buffer to reassemble fragmented media packets.
**                  When AVDTP receives a complete media packet, it calls the
**                  p_media_cback assigned by AVDT_CreateStream().
**                  This function can be called during callback to assign a
**                  different buffer for next media packet or can leave the current
**                  buffer for next packet.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
AVDT_API extern UINT16 AVDT_SetMediaBuf(UINT8 handle, UINT8 *p_buf, UINT32 buf_len)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;

    BTTRC_AVDT_API0(AVDT_TRACE_API_SET_MEDIABUF);

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
    {
        result = AVDT_BAD_HANDLE;
    }
    else
    {
        if(p_buf && p_scb->cs.p_media_cback == NULL)
            result = AVDT_NO_RESOURCES;
        else
        {
            p_scb->p_media_buf = p_buf;
            p_scb->media_buf_len = buf_len;
        }
    }

    return result;
}
/*******************************************************************************
**
** Function         AVDT_SecurityRsp
**
** Description      Respond to a security request from the peer device.
**                  This function must be called if the application receives
**                  an AVDT_SECURITY_IND_EVT through its control callback.
**                  (Please note that AVDTP security procedures are unrelated
**                  to Bluetooth link level security.)
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
                        UINT8 *p_data, UINT16 len)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_SCB_EVT   evt;

    BTTRC_AVDT_API0(AVDT_TRACE_API_SECURITY_RSP);

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
    {
        result = AVDT_BAD_HANDLE;
    }
    /* send event to scb */
    else
    {
        evt.msg.security_rsp.hdr.err_code = error_code;
        evt.msg.security_rsp.hdr.label = label;
        evt.msg.security_rsp.p_data = p_data;
        evt.msg.security_rsp.len = len;
        avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, &evt);
    }
    return result;
}
Exemple #5
0
/*******************************************************************************
**
** Function         avdt_ad_tc_data_ind
**
** Description      This function is called by the L2CAP interface layer when
**                  incoming data is received from L2CAP.  It looks up the CCB
**                  or SCB for the channel and routes the data accordingly.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
{
    tAVDT_CCB   *p_ccb;
    tAVDT_SCB   *p_scb;

    /* store type (media, recovery, reporting) */
    p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);


    /* if signaling channel, handle control message */
    if (p_tbl->tcid == 0) {
        p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
        avdt_msg_ind(p_ccb, p_buf);
    }
    /* if media or other channel, send event to scb */
    else {
        p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
        if (p_scb != NULL) {
            avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
        } else {
            GKI_freebuf(p_buf);
            AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
        }
    }
}
Exemple #6
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);
        }
    }
}
Exemple #7
0
/*******************************************************************************
**
** Function         AVDT_OpenReq
**
** Description      This function initiates a connection to the AVDTP service
**                  on the peer device, if not already present, and connects
**                  to a stream endpoint on a peer device.  When the connection
**                  is completed, an AVDT_OPEN_CFM_EVT is sent to the
**                  application via the control callback function for this handle.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_OpenReq(UINT8 handle, BD_ADDR bd_addr, UINT8 seid, tAVDT_CFG *p_cfg)
{
    tAVDT_CCB       *p_ccb = NULL;
    tAVDT_SCB       *p_scb = NULL;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_SCB_EVT   evt;

    /* verify SEID */
    if ((seid < AVDT_SEID_MIN) || (seid > AVDT_SEID_MAX)) {
        result = AVDT_BAD_PARAMS;
    }
    /* map handle to scb */
    else if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    }
    /* find channel control block for this bd addr; if none, allocate one */
    else 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;
        }
    }

    /* send event to scb */
    if (result == AVDT_SUCCESS) {
        evt.msg.config_cmd.hdr.seid = seid;
        evt.msg.config_cmd.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
        evt.msg.config_cmd.int_seid = handle;
        evt.msg.config_cmd.p_cfg = p_cfg;
        avdt_scb_event(p_scb, AVDT_SCB_API_SETCONFIG_REQ_EVT, &evt);
    }
    return result;
}
Exemple #8
0
/*******************************************************************************
**
** Function         AVDT_ConfigRsp
**
** Description      Respond to a configure request from the peer device.  This
**                  function must be called if the application receives an
**                  AVDT_CONFIG_IND_EVT through its control callback.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_ConfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
{
    tAVDT_SCB       *p_scb;
    tAVDT_SCB_EVT   evt;
    UINT16          result = AVDT_SUCCESS;
    UINT8           event_code;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    }
    /* handle special case when this function is called but peer has not send
    ** a configuration cmd; ignore and return error result
    */
    else if (!p_scb->in_use) {
        result = AVDT_BAD_HANDLE;
    }
    /* send event to scb */
    else {
        evt.msg.hdr.err_code = error_code;
        evt.msg.hdr.err_param = category;
        evt.msg.hdr.label = label;
        if (error_code == 0) {
            event_code = AVDT_SCB_API_SETCONFIG_RSP_EVT;
        } else {
            event_code = AVDT_SCB_API_SETCONFIG_REJ_EVT;
        }
        avdt_scb_event(p_scb, event_code, &evt);
    }

    return result;
}
/*******************************************************************************
**
** Function         avdt_ccb_snd_suspend_cmd
**
** Description      This function is called to send a suspend command to the
**                  peer.  It verifies that all requested streams are in the
**                  proper state.  If so, it sends a suspend command.
**                  Otherwise it calls the callback function for each requested
**                  stream and sends a suspend confirmation with failure.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    int             i;
    tAVDT_SCB       *p_scb;
    tAVDT_MSG       avdt_msg;
    UINT8           seid_list[AVDT_NUM_SEPS];

    /* make copy of our seid list */
    memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps);

    /* verify all streams in the right state */
    if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list,
                                  p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0)
    {
        /* set peer seid list in messsage */
        avdt_scb_peer_seid_list(&p_data->msg.multi);

        /* send command */
        avdt_msg_send_cmd(p_ccb, seid_list, AVDT_SIG_SUSPEND, &p_data->msg);
    }
    else
    {
        /* failed; send ourselves a reject for each stream */
        for (i = 0; i < p_data->msg.multi.num_seps; i++)
        {
            if ((p_scb = avdt_scb_by_hdl(seid_list[i])) != NULL)
            {
                avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_REJ_EVT, (tAVDT_SCB_EVT *) &avdt_msg.hdr);
            }
        }
    }
}
Exemple #10
0
/*******************************************************************************
**
** Function         AVDT_SuspendReq
**
** Description      Suspend one or more stream endpoints. This suspends the
**                  transfer of media packets for the streams.  All stream
**                  endpoints must previously be open and started.  When the
**                  streams are suspended, an AVDT_SUSPEND_CFM_EVT is sent to
**                  the application via the control callback function for
**                  each stream.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_SuspendReq(UINT8 *p_handles, UINT8 num_handles)
{
    tAVDT_SCB       *p_scb = NULL;
    tAVDT_CCB_EVT   evt;
    UINT16          result = AVDT_SUCCESS;
    int             i;

    if ((num_handles == 0) || (num_handles > AVDT_NUM_SEPS)) {
        result = AVDT_BAD_PARAMS;
    } else {
        /* verify handles */
        for (i = 0; i < num_handles; i++) {
            if ((p_scb = avdt_scb_by_hdl(p_handles[i])) == NULL) {
                result = AVDT_BAD_HANDLE;
                break;
            }
        }
    }

    if (result == AVDT_SUCCESS) {
        if (p_scb->p_ccb == NULL) {
            result = AVDT_BAD_HANDLE;
        } else {
            /* send event to ccb */
            memcpy(evt.msg.multi.seid_list, p_handles, num_handles);
            evt.msg.multi.num_seps = num_handles;
            avdt_ccb_event(p_scb->p_ccb, AVDT_CCB_API_SUSPEND_REQ_EVT, &evt);
        }
    }

    return result;
}
Exemple #11
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;
}
/*******************************************************************************
**
** Function         avdt_ccb_hdl_getcap_cmd
**
** Description      This function is called when a get capabilities command
**                  is received from the peer.  It retrieves the stream
**                  configuration for the requested stream and initiates
**                  sending of a get capabilities response.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    tAVDT_SCB       *p_scb;

    /* look up scb for seid sent to us */
    p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);

    p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;

    avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
}
Exemple #13
0
void AVDT_AbortReq(UINT8 handle)
{
    AVDT_TRACE_ERROR("%s\n", __func__);

    tAVDT_SCB *p_scb = avdt_scb_by_hdl(handle);
    if (p_scb != NULL) {
        avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_REQ_EVT, NULL);
    } else {
        AVDT_TRACE_ERROR("%s Improper SCB, can not abort the stream\n", __func__);
    }
}
Exemple #14
0
/*******************************************************************************
**
** Function         avdt_scb_peer_seid_list
**
** Description      Given a list of SCB handles, return a list of peer SEIDs
**                  for the handles, copied in place into the struct passed in.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi)
{
    int         i;
    tAVDT_SCB   *p_scb;

    for (i = 0; i < p_multi->num_seps; i++) {
        if ((p_scb = avdt_scb_by_hdl(p_multi->seid_list[i])) != NULL) {
            p_multi->seid_list[i] = p_scb->peer_seid;
        }
    }
}
Exemple #15
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;
}
Exemple #16
0
/*******************************************************************************
**
** Function         AVDT_RemoveStream
**
** Description      Remove a stream endpoint.  This function is called when
**                  the application is no longer using a stream endpoint.
**                  If this function is called when the endpoint is connected
**                  the connection is closed and then the stream endpoint
**                  is removed.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_RemoveStream(UINT8 handle)
{
    UINT16      result = AVDT_SUCCESS;
    tAVDT_SCB   *p_scb;

    /* look up scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    } else {
        /* send remove event to scb */
        avdt_scb_event(p_scb, AVDT_SCB_API_REMOVE_EVT, NULL);
    }
    return result;
}
Exemple #17
0
/*******************************************************************************
**
** Function         avdt_ccb_snd_suspend_rsp
**
** Description      This function is called to send a suspend response to the
**                  peer.  It takes the stream information passed in the event
**                  and sends a suspend response.  Then it sends a suspend event
**                  to the SCB for each stream.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    tAVDT_SCB *p_scb;
    int i;

    /* send response message */
    avdt_msg_send_rsp(p_ccb, AVDT_SIG_SUSPEND, &p_data->msg);

    /* send start event to each scb */
    for (i = 0; i < p_data->msg.multi.num_seps; i++) {
        if ((p_scb = avdt_scb_by_hdl(p_data->msg.multi.seid_list[i])) != NULL) {
            avdt_scb_event(p_scb, AVDT_SCB_MSG_SUSPEND_CMD_EVT, NULL);
        }
    }
}
Exemple #18
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;
}
Exemple #19
0
/*******************************************************************************
**
** Function         AVDT_CloseReq
**
** Description      Close a stream endpoint.  This stops the transfer of media
**                  packets and closes the transport channel associated with
**                  this stream endpoint.  When the stream is closed, an
**                  AVDT_CLOSE_CFM_EVT is sent to the application via the
**                  control callback function for this handle.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_CloseReq(UINT8 handle)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    } else
        /* send event to scb */
    {
        avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_REQ_EVT, NULL);
    }

    return result;
}
Exemple #20
0
/*******************************************************************************
**
** Function         AVDT_GetSignalChannel
**
** Description      Get the L2CAP CID used by the signal channel of the given handle.
**
** Returns          CID if successful, otherwise 0.
**
*******************************************************************************/
UINT16 AVDT_GetSignalChannel(UINT8 handle, BD_ADDR bd_addr)
{
    tAVDT_SCB       *p_scb;
    tAVDT_CCB       *p_ccb;
    UINT8           tcid = 0; /* tcid is always 0 for signal channel */
    UINT16          lcid = 0;

    /* map handle to scb */
    if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
            && ((p_ccb = p_scb->p_ccb) != NULL)) {
        lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
    } else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) != NULL) {
        lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
    }

    return (lcid);
}
Exemple #21
0
/*******************************************************************************
**
** Function         AVDT_SecurityReq
**
** Description      Send a security request to the peer device.  When the
**                  security procedure is completed, an AVDT_SECURITY_CFM_EVT
**                  is sent to the application via the control callback function
**                  for this handle.  (Please note that AVDTP security procedures
**                  are unrelated to Bluetooth link level security.)
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_SecurityReq(UINT8 handle, UINT8 *p_data, UINT16 len)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_SCB_EVT   evt;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    }
    /* send event to scb */
    else {
        evt.msg.security_rsp.p_data = p_data;
        evt.msg.security_rsp.len = len;
        avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_REQ_EVT, &evt);
    }
    return result;
}
Exemple #22
0
/*******************************************************************************
**
** Function         AVDT_GetL2CapChannel
**
** Description      Get the L2CAP CID used by the handle.
**
** Returns          CID if successful, otherwise 0.
**
*******************************************************************************/
UINT16 AVDT_GetL2CapChannel(UINT8 handle)
{
    tAVDT_SCB       *p_scb;
    tAVDT_CCB       *p_ccb;
    UINT8           tcid;
    UINT16          lcid = 0;

    /* map handle to scb */
    if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
            && ((p_ccb = p_scb->p_ccb) != NULL)) {
        /* get tcid from type, scb */
        tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);

        lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
    }

    return (lcid);
}
Exemple #23
0
/*******************************************************************************
**
** Function         AVDT_DelayReport
**
** Description      This functions sends a Delay Report to the peer device
**                  that is associated with a particular SEID.
**                  This function is called by SNK device.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_DelayReport(UINT8 handle, UINT8 seid, UINT16 delay)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_SCB_EVT   evt;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    } else
        /* send event to scb */
    {
        evt.apidelay.hdr.seid   = seid;
        evt.apidelay.delay      = delay;
        avdt_scb_event(p_scb, AVDT_SCB_API_DELAY_RPT_REQ_EVT, &evt);
    }

    return result;
}
Exemple #24
0
/*******************************************************************************
**
** Function         avdt_ad_tc_cong_ind
**
** Description      This function is called by the L2CAP interface layer when
**                  L2CAP calls the congestion callback.  It looks up the CCB
**                  or SCB for the channel and sends it a congestion event.
**                  The is_congested parameter is the same value passed by
**                  the L2CAP callback function.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
{
    tAVDT_CCB   *p_ccb;
    tAVDT_SCB   *p_scb;

    /* if signaling channel, notify ccb of congestion */
    if (p_tbl->tcid == 0) {
        p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
        avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested);
    }
    /* if media or other channel, notify scb that channel open */
    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) {
            avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested);
        }
    }
}
Exemple #25
0
/*******************************************************************************
**
** Function         AVDT_ReconfigReq
**
** Description      Reconfigure a stream endpoint.  This allows the application
**                  to change the codec or content protection capabilities of
**                  a stream endpoint after it has been opened.  This function
**                  can only be called if the stream is opened but not started
**                  or if the stream has been suspended.  When the procedure
**                  is completed, an AVDT_RECONFIG_CFM_EVT is sent to the
**                  application via the control callback function for this handle.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_ReconfigReq(UINT8 handle, tAVDT_CFG *p_cfg)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_SUCCESS;
    tAVDT_SCB_EVT   evt;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    }
    /* send event to scb */
    else {
        /* force psc_mask to zero */
        p_cfg->psc_mask = 0;

        evt.msg.reconfig_cmd.p_cfg = p_cfg;
        avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_REQ_EVT, &evt);
    }
    return result;
}
Exemple #26
0
/*******************************************************************************
**
** Function         AVDT_ReconfigRsp
**
** Description      Respond to a reconfigure request from the peer device.
**                  This function must be called if the application receives
**                  an AVDT_RECONFIG_IND_EVT through its control callback.
**
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_ReconfigRsp(UINT8 handle, UINT8 label, UINT8 error_code, UINT8 category)
{
    tAVDT_SCB       *p_scb;
    tAVDT_SCB_EVT   evt;
    UINT16          result = AVDT_SUCCESS;

    /* map handle to scb */
    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
        result = AVDT_BAD_HANDLE;
    }
    /* send event to scb */
    else {
        evt.msg.hdr.err_code = error_code;
        evt.msg.hdr.err_param = category;
        evt.msg.hdr.label = label;
        avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, &evt);
    }

    return result;
}
Exemple #27
0
/*******************************************************************************
**
** Function         avdt_ccb_hdl_suspend_rsp
**
** Description      This function is called when a suspend response or reject
**                  is received from the peer.  Using the SEIDs stored in the
**                  current command message, it sends a suspend response or
**                  suspend reject event to each SCB associated with the command.
**
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    UINT8       event;
    int         i;
    UINT8       *p;
    tAVDT_SCB   *p_scb;

    /* determine rsp or rej event */
    event = (p_data->msg.hdr.err_code == 0) ?
            AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT;

    /* get to where seid's are stashed in current cmd */
    p = (UINT8 *)(p_ccb->p_curr_cmd + 1);

    /* little trick here; length of current command equals number of streams */
    for (i = 0; i < p_ccb->p_curr_cmd->len; i++) {
        if ((p_scb = avdt_scb_by_hdl(p[i])) != NULL) {
            avdt_scb_event(p_scb, event, (tAVDT_SCB_EVT *) &p_data->msg);
        }
    }
}
Exemple #28
0
/*******************************************************************************
**
** Function         avdt_ad_tc_open_ind
**
** Description      This function is called by the L2CAP interface when
**                  the L2CAP channel is opened.  It looks up the CCB or SCB
**                  for the channel and sends it an open event.
**
**
** Returns          Nothing.
**
*******************************************************************************/
void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
{
    tAVDT_CCB   *p_ccb;
    tAVDT_SCB   *p_scb;
    tAVDT_OPEN  open;
    tAVDT_EVT_HDR evt;

    p_tbl->state = AVDT_AD_ST_OPEN;

    /* if signaling channel, notify ccb that channel open */
    if (p_tbl->tcid == 0) {
        /* set the signal channel to use high priority within the ACL link */
        L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH);

        p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
        /* use err_param to indicate the role of connection.
         * AVDT_ACP, if ACP */
        evt.err_param = AVDT_INT;
        if (p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP) {
            evt.err_param = AVDT_ACP;
        }
        avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt);
    }
    /* if media or other channel, notify scb that channel open */
    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);

        /* put lcid in event data */
        if (p_scb != NULL) {
            open.peer_mtu = p_tbl->peer_mtu;
            open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
            open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
            avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open);
        }
    }
}
Exemple #29
0
/*******************************************************************************
**
** Function         AVDT_SendReport
**
** Description
**
**
**
** Returns
**
*******************************************************************************/
UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
                       tAVDT_REPORT_DATA *p_data)
{
    tAVDT_SCB       *p_scb;
    UINT16          result = AVDT_BAD_PARAMS;
    BT_HDR          *p_pkt;
    tAVDT_TC_TBL    *p_tbl;
    UINT8           *p, *plen, *pm1, *p_end;
#if AVDT_MULTIPLEXING == TRUE
    UINT8           *p_al = NULL, u;
#endif
    UINT32  ssrc;
    UINT16  len;

    /* map handle to scb && verify parameters */
    if (((p_scb = avdt_scb_by_hdl(handle)) != NULL)
            && (p_scb->p_ccb != NULL)
            && (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) ||
                ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) ||
                (type == AVDT_RTCP_PT_SDES)) ) {
        result = AVDT_NO_RESOURCES;

        /* build SR - assume fit in one packet */
        p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
        if ((p_tbl->state == AVDT_AD_ST_OPEN) &&
                (p_pkt = (BT_HDR *)GKI_getbuf(p_tbl->peer_mtu)) != NULL) {
            p_pkt->offset = L2CAP_MIN_OFFSET;
            p = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
#if AVDT_MULTIPLEXING == TRUE
            if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) {
                /* Adaptation Layer header later */
                p_al = p;
                p += 2;
            }
#endif
            pm1 = p;
            *p++ = AVDT_MEDIA_OCTET1 | 1;
            *p++ = type;
            /* save the location for length */
            plen = p;
            p += 2;
            ssrc = avdt_scb_gen_ssrc(p_scb);
            UINT32_TO_BE_STREAM(p, ssrc);

            switch (type) {
            case AVDT_RTCP_PT_SR:   /* Sender Report */
                *pm1 = AVDT_MEDIA_OCTET1;
                UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec);
                UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac);
                UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time);
                UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count);
                UINT32_TO_BE_STREAM(p, p_data->sr.octet_count);
                break;

            case AVDT_RTCP_PT_RR:   /* Receiver Report */
                *p++ = p_data->rr.frag_lost;
                AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost);
                p_data->rr.packet_lost &= 0xFFFFFF;
                AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost);
                UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost);
                UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd);
                UINT32_TO_BE_STREAM(p, p_data->rr.jitter);
                UINT32_TO_BE_STREAM(p, p_data->rr.lsr);
                UINT32_TO_BE_STREAM(p, p_data->rr.dlsr);
                break;

            case AVDT_RTCP_PT_SDES: /* Source Description */
                *p++ = AVDT_RTCP_SDES_CNAME;
                len = strlen((char *)p_data->cname);
                if (len > AVDT_MAX_CNAME_SIZE) {
                    len = AVDT_MAX_CNAME_SIZE;
                }
                *p++ = (UINT8)len;
                BCM_STRNCPY_S((char *)p, len + 1, (char *)p_data->cname, len + 1);
                p += len;
                break;
            }
            p_end = p;
            len = p - pm1 - 1;
            UINT16_TO_BE_STREAM(plen, len);

#if AVDT_MULTIPLEXING == TRUE
            if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) {
                /* Adaptation Layer header */
                p = p_al;
                len++;
                UINT16_TO_BE_STREAM(p_al, len );
                /* TSID, no-fragment bit and coding of length(9-bit length field) */
                u = *p;
                *p = (p_scb->curr_cfg.mux_tsid_report << 3) | AVDT_ALH_LCODE_9BITM0;
                if (u) {
                    *p |= AVDT_ALH_LCODE_9BITM1;
                }
            }
#endif

            /* set the actual payload length */
            p_pkt->len = p_end - p;
            /* send the packet */
            if (L2CAP_DW_FAILED != avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt)) {
                result = AVDT_SUCCESS;
            }
        }
    }

    return result;
}