/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; }