Ejemplo n.º 1
0
/*******************************************************************************
**
** 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;
    }
}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         avdt_ccb_hdl_discover_cmd
**
** Description      This function is called when a discover command is
**                  received from the peer.  It gathers up the stream
**                  information for all allocated streams and initiates
**                  sending of a discover response.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    tAVDT_SEP_INFO      sep_info[AVDT_NUM_SEPS];
    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
    int                 i;

    p_data->msg.discover_rsp.p_sep_info = sep_info;
    p_data->msg.discover_rsp.num_seps = 0;

    /* for all allocated scbs */
    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
    {
        if (p_scb->allocated)
        {
            /* copy sep info */
            sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
            sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
            sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
            sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;

            p_data->msg.discover_rsp.num_seps++;
        }
    }

    /* send response */
    avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_RSP_EVT, p_data);
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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.º 5
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;
}
Ejemplo n.º 6
0
/*******************************************************************************
**
** 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);
    }
}
Ejemplo n.º 7
0
/*******************************************************************************
**
** Function         avdt_get_cap_req
**
** Description      internal function to serve both AVDT_GetCapReq and
**                  AVDT_GetAllCapReq
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
static UINT16 avdt_get_cap_req(BD_ADDR bd_addr, tAVDT_CCB_API_GETCAP *p_evt)
{
    tAVDT_CCB       *p_ccb = NULL;
    UINT16          result = AVDT_SUCCESS;

    /* verify SEID */
    if ((p_evt->single.seid < AVDT_SEID_MIN) || (p_evt->single.seid > AVDT_SEID_MAX)) {
        AVDT_TRACE_ERROR("seid: %d\n", p_evt->single.seid);
        result = AVDT_BAD_PARAMS;
    }
    /* 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;
        }
    }

    if (result == AVDT_SUCCESS) {
        /* make sure no discovery or get capabilities req already in progress */
        if (p_ccb->proc_busy) {
            result = AVDT_BUSY;
        }
        /* send event to ccb */
        else {
            avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_REQ_EVT, (tAVDT_CCB_EVT *)p_evt);
        }
    }
    return result;
}
Ejemplo n.º 8
0
/*******************************************************************************
**
** Function         AVDT_DiscoverReq
**
** Description      This function initiates a connection to the AVDTP service
**                  on the peer device, if not already present, and discovers
**                  the stream endpoints on the peer device.  (Please note
**                  that AVDTP discovery is unrelated to SDP discovery).
**                  This function can be called at any time regardless of whether
**                  there is an AVDTP connection to the peer device.
**
**                  When discovery is complete, an AVDT_DISCOVER_CFM_EVT
**                  is sent to the application via its callback function.
**                  The application must not call AVDT_GetCapReq() or
**                  AVDT_DiscoverReq() again to the same device until
**                  discovery is complete.
**
**                  The memory addressed by sep_info is allocated by the
**                  application.  This memory is written to by AVDTP as part
**                  of the discovery procedure.  This memory must remain
**                  accessible until the application receives the
**                  AVDT_DISCOVER_CFM_EVT.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_DiscoverReq(BD_ADDR bd_addr, tAVDT_SEP_INFO *p_sep_info,
                        UINT8 max_seps, tAVDT_CTRL_CBACK *p_cback)
{
    tAVDT_CCB       *p_ccb;
    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;
        }
    }

    if (result == AVDT_SUCCESS) {
        /* make sure no discovery or get capabilities req already in progress */
        if (p_ccb->proc_busy) {
            result = AVDT_BUSY;
        }
        /* send event to ccb */
        else {
            evt.discover.p_sep_info = p_sep_info;
            evt.discover.num_seps = max_seps;
            evt.discover.p_cback = p_cback;
            avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCOVER_REQ_EVT, &evt);
        }
    }
    return result;
}
Ejemplo n.º 9
0
/*******************************************************************************
**
** 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);
}
Ejemplo n.º 10
0
/*******************************************************************************
**
** Function         avdt_ccb_hdl_start_cmd
**
** Description      This function is called when a start command is received
**                  from the peer.  It verifies that all requested streams
**                  are in the proper state.  If so, it initiates sending of
**                  a start response.  Otherwise it sends a start reject.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_hdl_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    UINT8   err_code = 0;

    /* verify all streams in the right state */
    UINT8 seid = avdt_scb_verify(p_ccb, AVDT_VERIFY_START, p_data->msg.multi.seid_list,
                                 p_data->msg.multi.num_seps, &err_code);
    if (seid == 0 && err_code == 0) {
        /* we're ok, send response */
        avdt_ccb_event(p_ccb, AVDT_CCB_API_START_RSP_EVT, p_data);
    } else {
        /* not ok, send reject */
        p_data->msg.hdr.err_code = err_code;
        p_data->msg.hdr.err_param = seid;
        avdt_msg_send_rej(p_ccb, AVDT_SIG_START, &p_data->msg);
    }
}
Ejemplo n.º 11
0
/*******************************************************************************
**
** Function         AVDT_DisconnectReq
**
** Description      This function disconnect an AVDTP signaling connection
**                  to the peer device.  When disconnected an
**                  AVDT_DISCONNECT_IND_EVT is sent to the application via its
**                  control callback function.
**
** Returns          AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
UINT16 AVDT_DisconnectReq(BD_ADDR bd_addr, 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, error */
    if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL) {
        result = AVDT_BAD_PARAMS;
    }

    if (result == AVDT_SUCCESS) {
        /* send event to ccb */
        evt.disconnect.p_cback = p_cback;
        avdt_ccb_event(p_ccb, AVDT_CCB_API_DISCONNECT_REQ_EVT, &evt);
    }
    return result;
}
Ejemplo n.º 12
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);
        }
    }
}
Ejemplo n.º 13
0
/*******************************************************************************
**
** Function         avdt_ccb_chk_reconn
**
** Description      This function is called to check if a reconnect attempt
**                  is enabled.  If enabled, it sends an AVDT_CCB_UL_OPEN_EVT
**                  to the CCB.  If disabled, the CCB is deallocated.
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    UINT8   err_code = AVDT_ERR_CONNECT;
    UNUSED(p_data);

    if (p_ccb->reconn) {
        p_ccb->reconn = FALSE;

        /* clear out ccb */
        avdt_ccb_clear_ccb(p_ccb);

        /* clear out current command, if any */
        avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code);

        /* reopen the signaling channel */
        avdt_ccb_event(p_ccb, AVDT_CCB_UL_OPEN_EVT, NULL);
    } else {
        avdt_ccb_ll_closed(p_ccb, NULL);
    }
}
Ejemplo n.º 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);
        }
    }
}