/*******************************************************************************
**
** Function         avrc_bld_get_capability_rsp
**
** Description      This function builds the Get Capability response.
**
** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
**                  Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR *p_pkt)
{
    UINT8   *p_data, *p_start, *p_len, *p_count;
    UINT16  len = 0;
    UINT8   xx;
    UINT32  *p_company_id;
    UINT8   *p_event_id;
    tAVRC_STS status = AVRC_STS_NO_ERROR;

    if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id)))
    {
        AVRC_TRACE_ERROR1("avrc_bld_get_capability_rsp bad parameter. p_rsp: %x", p_rsp);
        status = AVRC_STS_BAD_PARAM;
        return status;
    }

    AVRC_TRACE_API0("avrc_bld_get_capability_rsp");
    /* get the existing length, if any, and also the num attributes */
    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    p_data = p_len = p_start + 2; /* pdu + rsvd */

    BE_STREAM_TO_UINT16(len, p_data);
    UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id);
    p_count = p_data;

    if (len == 0)
    {
        *p_count = p_rsp->count;
        p_data++;
        len = 2; /* move past the capability_id and count */
    }
    else
    {
        p_data = p_start + p_pkt->len;
        *p_count += p_rsp->count;
    }

    if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
    {
        p_company_id = p_rsp->param.company_id;
        for (xx=0; xx< p_rsp->count; xx++)
        {
            UINT24_TO_BE_STREAM(p_data, p_company_id[xx]);
        }
        len += p_rsp->count * 3;
    }
    else
    {
        p_event_id = p_rsp->param.event_id;
        *p_count = 0;
        for (xx=0; xx< p_rsp->count; xx++)
        {
            if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx]))
            {
                (*p_count)++;
                UINT8_TO_BE_STREAM(p_data, p_event_id[xx]);
            }
        }
        len += (*p_count);
    }
    UINT16_TO_BE_STREAM(p_len, len);
    p_pkt->len = (p_data - p_start);
    status = AVRC_STS_NO_ERROR;

    return status;
}
Exemple #2
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;
}