Пример #1
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__);
    }
}
Пример #2
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;
}
Пример #3
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);
        }
    }
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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);
        }
    }
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
/*******************************************************************************
**
** 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;

    BTTRC_AVDT_API0(AVDT_TRACE_API_OPEN_REQ);


    /* 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;
}
Пример #11
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);
        }
    }
}
/*******************************************************************************
**
** 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;

    BTTRC_AVDT_API0(AVDT_TRACE_API_CONFIG_RSP);

    /* 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;
}
Пример #13
0
/*******************************************************************************
**
** 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;

    /* 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;
}
Пример #14
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);
        }
    }
}
/*******************************************************************************
**
** Function         avdt_process_timeout
**
** Description      This function is called by BTU when an AVDTP timer
**                  expires.  The function sends a timer event to the
**                  appropriate CCB or SCB state machine.
**
**                  This function is for use internal to the stack only.
**
**
** Returns          void
**
*******************************************************************************/
void avdt_process_timeout(TIMER_LIST_ENT *p_tle)
{
    UINT8   event = 0;
    UINT8   err_code = AVDT_ERR_TIMEOUT;

    switch (p_tle->event)
    {
        case BTU_TTYPE_AVDT_CCB_RET:
            event = AVDT_CCB_RET_TOUT_EVT + AVDT_CCB_MKR;
            break;

        case BTU_TTYPE_AVDT_CCB_RSP:
            event = AVDT_CCB_RSP_TOUT_EVT + AVDT_CCB_MKR;
            break;

        case BTU_TTYPE_AVDT_CCB_IDLE:
            event = AVDT_CCB_IDLE_TOUT_EVT + AVDT_CCB_MKR;
            break;

        case BTU_TTYPE_AVDT_SCB_TC:
            event = AVDT_SCB_TC_TOUT_EVT;
            break;

        default:
            break;
    }

    if (event & AVDT_CCB_MKR)
    {
        avdt_ccb_event((tAVDT_CCB *) p_tle->param, (UINT8) (event & ~AVDT_CCB_MKR),
                       (tAVDT_CCB_EVT *) &err_code);
    }
    else
    {
        avdt_scb_event((tAVDT_SCB *) p_tle->param, event, NULL);
    }
}
/*******************************************************************************
**
** 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.
**
*******************************************************************************/
AVDT_API 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;

    BTTRC_AVDT_API1(AVDT_TRACE_API_WRITE_DATA_REQ, BTTRC_PARAM_UINT32, data_len);

    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_WARNING1("mux_tsid_media:%d", 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_WARNING4("p_scb->p_pkt=%x, p_scb->p_ccb=%x, IsQueueEmpty=%x, p_scb->frag_off=%x",
                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_WARNING0("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_WARNING1("*** AVDT_WriteDataReq failed result=%d",result);
    }
#endif
    return result;
}