summaryrefslogtreecommitdiffstats
path: root/stack/avrc
diff options
context:
space:
mode:
authorAyan Ghosh <abghosh@codeaurora.org>2014-07-25 17:51:32 +0530
committerLinux Build Service Account <lnxbuild@localhost>2015-10-06 03:21:46 -0600
commiteceafe97c9a07a5bf4e5f84cadaad3b731c38d21 (patch)
treedaa810c800a3e34ae6c812f51b5d279aeac2fd23 /stack/avrc
parent0887ba37967b83b0264f9f336f5f3d8074daf761 (diff)
downloadandroid_system_bt-eceafe97c9a07a5bf4e5f84cadaad3b731c38d21.tar.gz
android_system_bt-eceafe97c9a07a5bf4e5f84cadaad3b731c38d21.tar.bz2
android_system_bt-eceafe97c9a07a5bf4e5f84cadaad3b731c38d21.zip
AVRCP 1.5 Implementation.
AVRCP 1.5 Implementation Change-Id: Ia35dc4344b05584cf5ab3b463815c9e6297d24ab Proper check to ensure attributes are populated properly Incorporated proper check to ensure if memory is allocated properly then all requested attributes are populated in response from DUT. CRs-Fixed: 753309 Change-Id: Iead549635cd2059bc8cf33585a5d87ae023149d4 Reset Browsing Bit if carkit is blacklisted - Reset Browsing bit if carkit is blacklisted for avrcp 1.5. - Not to send 1.3+ specific supported events if carkit is blacklisted. CRs-Fixed: 762470 Change-Id: I32ac80c0549b2b89dd2522dbb0dea89d255d33dc Free Browse packet Free Borwse packet in AVRC layer once the same is copied to BTA for further processing. CRs-Fixed: 785286 Change-Id: I8037a649cff5a1e527c28ba36999a1bed34d315a BTIF-AV: Use valid memory for AVRCP message After the context switch to BTIF for META message processing the buffer allocated for tAVRC_MSG will be freed, hence allocate the required memory and free that after handling the META message. Conflicts: stack/avrc/avrc_api.c Crs-Fixed: 651506 Change-Id: Icbf61776a6fb63fac1555bf25d3700beccf2b67a
Diffstat (limited to 'stack/avrc')
-rwxr-xr-xstack/avrc/avrc_api.c385
-rw-r--r--stack/avrc/avrc_bld_tg.c461
-rw-r--r--stack/avrc/avrc_int.h1
-rw-r--r--stack/avrc/avrc_pars_tg.c24
-rw-r--r--stack/avrc/avrc_sdp.c35
-rw-r--r--stack/avrc/avrc_utils.c2
6 files changed, 723 insertions, 185 deletions
diff --git a/stack/avrc/avrc_api.c b/stack/avrc/avrc_api.c
index 1b874dc8c..359d910ec 100755
--- a/stack/avrc/avrc_api.c
+++ b/stack/avrc/avrc_api.c
@@ -150,7 +150,7 @@ static void avrc_prep_end_frag(UINT8 handle)
UINT8 *p_data, *p_orig_data;
UINT8 rsp_type;
- AVRC_TRACE_DEBUG ("avrc_prep_end_frag" );
+ AVRC_TRACE_DEBUG("avrc_prep_end_frag" );
p_fcb = &avrc_cb.fcb[handle];
/* The response type of the end fragment should be the same as the the PDU of "End Fragment
@@ -226,7 +226,7 @@ static void avrc_send_continue_frag(UINT8 handle, UINT8 label)
p_pkt = p_fcb->p_fmsg;
p_fcb->p_fmsg = NULL;
p_fcb->frag_enabled = FALSE;
- AVRC_TRACE_ERROR ("AVRC_MsgReq no buffers for fragmentation - send internal error" );
+ AVRC_TRACE_ERROR("AVRC_MsgReq no buffers for fragmentation - send internal error" );
p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
*p_data++ = AVRC_PDU_REQUEST_CONTINUATION_RSP;
*p_data++ = 0;
@@ -274,7 +274,7 @@ static BT_HDR * avrc_proc_vendor_command(UINT8 handle, UINT8 label,
if (pkt_type != AVRC_PKT_SINGLE)
{
/* reject - commands can only be in single packets at AVRCP level */
- AVRC_TRACE_ERROR ("commands must be in single packet pdu:0x%x", *p_data );
+ AVRC_TRACE_ERROR("commands must be in single packet pdu:0x%x", *p_data );
/* use the current GKI buffer to send the reject */
status = AVRC_STS_BAD_CMD;
}
@@ -390,7 +390,7 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_
p_data += AVRC_VENDOR_HDR_SIZE;
pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
- AVRC_TRACE_DEBUG ("pkt_type %d", pkt_type );
+ AVRC_TRACE_DEBUG("pkt_type %d", pkt_type );
p_rcb = &avrc_cb.rcb[handle];
if (p_msg->company_id == AVRC_CO_METADATA)
{
@@ -433,7 +433,7 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_
{
/* Unable to allocate buffer for fragmented avrc message. Reuse START
buffer for reassembly (re-assembled message may fit into ACL buf) */
- AVRC_TRACE_DEBUG ("Unable to allocate buffer for fragmented avrc message, \
+ AVRC_TRACE_DEBUG("Unable to allocate buffer for fragmented avrc message, \
reusing START buffer for reassembly");
p_rcb->rasm_offset = p_pkt->offset;
p_rcb->p_rmsg = p_pkt;
@@ -447,7 +447,7 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_
{
/* Received a CONTINUE/END, but no corresponding START
(or previous fragmented response was dropped) */
- AVRC_TRACE_DEBUG ("Received a CONTINUE/END without no corresponding START \
+ AVRC_TRACE_DEBUG("Received a CONTINUE/END without no corresponding START \
(or previous fragmented response was dropped)");
drop_code = 5;
GKI_freebuf(p_pkt);
@@ -551,6 +551,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
UINT8 opcode;
tAVRC_MSG msg;
UINT8 *p_data;
+ UINT8 *browse_length;
UINT8 *p_begin;
BOOLEAN drop = FALSE;
BOOLEAN do_free = TRUE;
@@ -585,111 +586,100 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
memset(&msg, 0, sizeof(tAVRC_MSG) );
+ /* layer_specific value use to distinguish
+ * Browsing and control channel PDU ID.
+ * AVCT_DATA_BROWSE to be used for browsing
+ * channel
+ */
+ AVRC_TRACE_DEBUG("layer_specific %x",p_pkt->layer_specific);
+ if (p_pkt->layer_specific != AVCT_DATA_BROWSE)
{
- msg.hdr.ctype = p_data[0] & AVRC_CTYPE_MASK;
- AVRC_TRACE_DEBUG("avrc_msg_cback handle:%d, ctype:%d, offset:%d, len: %d",
- handle, msg.hdr.ctype, p_pkt->offset, p_pkt->len);
- msg.hdr.subunit_type = (p_data[1] & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
- msg.hdr.subunit_id = p_data[1] & AVRC_SUBID_MASK;
- opcode = p_data[2];
- }
-
- if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
- ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
- {
-
- switch(opcode)
{
- case AVRC_OP_UNIT_INFO:
- if (cr == AVCT_CMD)
- {
- /* send the response to the peer */
- p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN);
- p_rsp_data = avrc_get_data_ptr(p_rsp);
- *p_rsp_data = AVRC_RSP_IMPL_STBL;
- /* check & set the offset. set response code, set subunit_type & subunit_id,
- set AVRC_OP_UNIT_INFO */
- /* 3 bytes: ctype, subunit*, opcode */
- p_rsp_data += AVRC_AVC_HDR_SIZE;
- *p_rsp_data++ = 7;
- /* Panel subunit & id=0 */
- *p_rsp_data++ = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
- AVRC_CO_ID_TO_BE_STREAM(p_rsp_data, avrc_cb.ccb[handle].company_id);
- p_rsp->len = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
- cr = AVCT_RSP;
-#if (BT_USE_TRACES == TRUE)
- p_drop_msg = "auto respond";
-#endif
- }
- else
- {
- /* parse response */
- p_data += 4; /* 3 bytes: ctype, subunit*, opcode + octet 3 (is 7)*/
- msg.unit.unit_type = (*p_data & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
- msg.unit.unit = *p_data & AVRC_SUBID_MASK;
- p_data++;
- AVRC_BE_STREAM_TO_CO_ID(msg.unit.company_id, p_data);
- }
- break;
+ msg.hdr.ctype = p_data[0] & AVRC_CTYPE_MASK;
+ AVRC_TRACE_DEBUG("avrc_msg_cback handle:%d, ctype:%d, offset:%d, len: %d",
+ handle, msg.hdr.ctype, p_pkt->offset, p_pkt->len);
+ msg.hdr.subunit_type = (p_data[1] & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
+ msg.hdr.subunit_id = p_data[1] & AVRC_SUBID_MASK;
+ opcode = p_data[2];
+ }
- case AVRC_OP_SUB_INFO:
- if (cr == AVCT_CMD)
+ if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
+ ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
+ {
+ switch(opcode)
{
- /* send the response to the peer */
- p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
- p_rsp_data = avrc_get_data_ptr(p_rsp);
- *p_rsp_data = AVRC_RSP_IMPL_STBL;
- /* check & set the offset. set response code, set (subunit_type & subunit_id),
- set AVRC_OP_SUB_INFO, set (page & extention code) */
- p_rsp_data += 4;
- /* Panel subunit & id=0 */
- *p_rsp_data++ = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
- memset(p_rsp_data, AVRC_CMD_OPRND_PAD, AVRC_SUBRSP_OPRND_BYTES);
- p_rsp_data += AVRC_SUBRSP_OPRND_BYTES;
- p_rsp->len = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
- cr = AVCT_RSP;
+ case AVRC_OP_UNIT_INFO:
+ if (cr == AVCT_CMD)
+ {
+ /* send the response to the peer */
+ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN);
+ p_rsp_data = avrc_get_data_ptr(p_rsp);
+ *p_rsp_data = AVRC_RSP_IMPL_STBL;
+ /* check & set the offset. set response code, set subunit_type & subunit_id,
+ set AVRC_OP_UNIT_INFO */
+ /* 3 bytes: ctype, subunit*, opcode */
+ p_rsp_data += AVRC_AVC_HDR_SIZE;
+ *p_rsp_data++ = 7;
+ /* Panel subunit & id=0 */
+ *p_rsp_data++ = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
+ AVRC_CO_ID_TO_BE_STREAM(p_rsp_data, avrc_cb.ccb[handle].company_id);
+ p_rsp->len = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
+ cr = AVCT_RSP;
#if (BT_USE_TRACES == TRUE)
- p_drop_msg = "auto responded";
+ p_drop_msg = "auto respond";
#endif
- }
- else
- {
- /* parse response */
- p_data += AVRC_AVC_HDR_SIZE; /* 3 bytes: ctype, subunit*, opcode */
- msg.sub.page = (*p_data++ >> AVRC_SUB_PAGE_SHIFT) & AVRC_SUB_PAGE_MASK;
- xx = 0;
- while (*p_data != AVRC_CMD_OPRND_PAD && xx<AVRC_SUB_TYPE_LEN)
+ }
+ else
{
- msg.sub.subunit_type[xx] = *p_data++ >> AVRC_SUBTYPE_SHIFT;
- if (msg.sub.subunit_type[xx] == AVRC_SUB_PANEL)
- msg.sub.panel = TRUE;
- xx++;
+ /* parse response */
+ p_data += 4; /* 3 bytes: ctype, subunit*, opcode + octet 3 (is 7)*/
+ msg.unit.unit_type = (*p_data & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
+ msg.unit.unit = *p_data & AVRC_SUBID_MASK;
+ p_data++;
+ AVRC_BE_STREAM_TO_CO_ID(msg.unit.company_id, p_data);
}
- }
- break;
+ break;
- case AVRC_OP_VENDOR:
- p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
- p_begin = p_data;
- if (p_pkt->len < AVRC_VENDOR_HDR_SIZE) /* 6 = ctype, subunit*, opcode & CO_ID */
- {
+ case AVRC_OP_SUB_INFO:
if (cr == AVCT_CMD)
- reject = TRUE;
+ {
+ /* send the response to the peer */
+ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
+ p_rsp_data = avrc_get_data_ptr(p_rsp);
+ *p_rsp_data = AVRC_RSP_IMPL_STBL;
+ /* check & set the offset. set response code, set (subunit_type & subunit_id),
+ set AVRC_OP_SUB_INFO, set (page & extention code) */
+ p_rsp_data += 4;
+ /* Panel subunit & id=0 */
+ *p_rsp_data++ = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
+ memset(p_rsp_data, AVRC_CMD_OPRND_PAD, AVRC_SUBRSP_OPRND_BYTES);
+ p_rsp_data += AVRC_SUBRSP_OPRND_BYTES;
+ p_rsp->len = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
+ cr = AVCT_RSP;
+#if (BT_USE_TRACES == TRUE)
+ p_drop_msg = "auto responded";
+#endif
+ }
else
- drop = TRUE;
+ {
+ /* parse response */
+ p_data += AVRC_AVC_HDR_SIZE; /* 3 bytes: ctype, subunit*, opcode */
+ msg.sub.page = (*p_data++ >> AVRC_SUB_PAGE_SHIFT) & AVRC_SUB_PAGE_MASK;
+ xx = 0;
+ while (*p_data != AVRC_CMD_OPRND_PAD && xx<AVRC_SUB_TYPE_LEN)
+ {
+ msg.sub.subunit_type[xx] = *p_data++ >> AVRC_SUBTYPE_SHIFT;
+ if (msg.sub.subunit_type[xx] == AVRC_SUB_PANEL)
+ msg.sub.panel = TRUE;
+ xx++;
+ }
+ }
break;
- }
- p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
- AVRC_BE_STREAM_TO_CO_ID(p_msg->company_id, p_data);
- p_msg->p_vendor_data = p_data;
- p_msg->vendor_len = p_pkt->len - (p_data - p_begin);
-#if (AVRC_METADATA_INCLUDED == TRUE)
- UINT8 drop_code = 0;
- if (p_msg->company_id == AVRC_CO_METADATA)
- {
- /* Validate length for metadata message */
- if (p_pkt->len < (AVRC_VENDOR_HDR_SIZE + AVRC_MIN_META_HDR_SIZE))
+ case AVRC_OP_VENDOR:
+ p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+ p_begin = p_data;
+ if (p_pkt->len < AVRC_VENDOR_HDR_SIZE) /* 6 = ctype, subunit*, opcode & CO_ID */
{
if (cr == AVCT_CMD)
reject = TRUE;
@@ -697,117 +687,144 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
drop = TRUE;
break;
}
+ p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
+ AVRC_BE_STREAM_TO_CO_ID(p_msg->company_id, p_data);
+ p_msg->p_vendor_data = p_data;
+ p_msg->vendor_len = p_pkt->len - (p_data - p_begin);
- /* Check+handle fragmented messages */
+#if (AVRC_METADATA_INCLUDED == TRUE)
+ UINT8 drop_code = 0;
drop_code = avrc_proc_far_msg(handle, label, cr, &p_pkt, p_msg);
if (drop_code > 0)
drop = TRUE;
- }
- if (drop_code > 0)
- {
- if (drop_code != 4)
- do_free = FALSE;
-#if (BT_USE_TRACES == TRUE)
- switch (drop_code)
+ if (drop_code > 0)
{
- case 1:
- p_drop_msg = "sent_frag";
- break;
- case 2:
- p_drop_msg = "req_cont";
- break;
- case 3:
- p_drop_msg = "sent_frag3";
- break;
- case 4:
- p_drop_msg = "sent_frag_free";
- break;
- default:
- p_drop_msg = "sent_fragd";
- }
+ if (drop_code != 4)
+ do_free = FALSE;
+#if (BT_USE_TRACES == TRUE)
+ switch (drop_code)
+ {
+ case 1:
+ p_drop_msg = "sent_frag";
+ break;
+ case 2:
+ p_drop_msg = "req_cont";
+ break;
+ case 3:
+ p_drop_msg = "sent_frag3";
+ break;
+ case 4:
+ p_drop_msg = "sent_frag_free";
+ break;
+ default:
+ p_drop_msg = "sent_fragd";
+ }
#endif
- }
+ }
#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
- break;
+ break;
- case AVRC_OP_PASS_THRU:
- if (p_pkt->len < 5) /* 3 bytes: ctype, subunit*, opcode & op_id & len */
- {
- if (cr == AVCT_CMD)
- reject = TRUE;
+ case AVRC_OP_PASS_THRU:
+ if (p_pkt->len < 5) /* 3 bytes: ctype, subunit*, opcode & op_id & len */
+ {
+ if (cr == AVCT_CMD)
+ reject = TRUE;
+ else
+ drop = TRUE;
+ break;
+ }
+ p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
+ msg.pass.op_id = (AVRC_PASS_OP_ID_MASK & *p_data);
+ if (AVRC_PASS_STATE_MASK & *p_data)
+ msg.pass.state = TRUE;
else
- drop = TRUE;
+ msg.pass.state = FALSE;
+ p_data++;
+ msg.pass.pass_len = *p_data++;
+ if (msg.pass.pass_len != p_pkt->len - 5)
+ msg.pass.pass_len = p_pkt->len - 5;
+ if (msg.pass.pass_len)
+ msg.pass.p_pass_data = p_data;
+ else
+ msg.pass.p_pass_data = NULL;
break;
- }
- p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
- msg.pass.op_id = (AVRC_PASS_OP_ID_MASK & *p_data);
- if (AVRC_PASS_STATE_MASK & *p_data)
- msg.pass.state = TRUE;
- else
- msg.pass.state = FALSE;
- p_data++;
- msg.pass.pass_len = *p_data++;
- if (msg.pass.pass_len != p_pkt->len - 5)
- msg.pass.pass_len = p_pkt->len - 5;
- if (msg.pass.pass_len)
- msg.pass.p_pass_data = p_data;
- else
- msg.pass.p_pass_data = NULL;
- break;
- default:
- if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
- {
- /* reject unsupported opcode */
- reject = TRUE;
+ default:
+ if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
+ {
+ /* reject unsupported opcode */
+ reject = TRUE;
+ }
+ drop = TRUE;
+ break;
}
+ }
+ else /* drop the event */
+ {
drop = TRUE;
- break;
}
- }
- else /* drop the event */
- {
+
+ if (reject)
+ {
+ /* reject unsupported opcode */
+ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
+ p_rsp_data = avrc_get_data_ptr(p_rsp);
+ *p_rsp_data = AVRC_RSP_REJ;
+#if (BT_USE_TRACES == TRUE)
+ p_drop_msg = "rejected";
+#endif
+ cr = AVCT_RSP;
drop = TRUE;
- }
+ }
- if (reject)
- {
- /* reject unsupported opcode */
- p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
- p_rsp_data = avrc_get_data_ptr(p_rsp);
- *p_rsp_data = AVRC_RSP_REJ;
+ if (p_rsp)
+ {
+ /* set to send response right away */
+ AVCT_MsgReq( handle, label, cr, p_rsp);
+ drop = TRUE;
+ }
+
+ if (drop == FALSE)
+ {
+ msg.hdr.opcode = opcode;
+ (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+ }
#if (BT_USE_TRACES == TRUE)
- p_drop_msg = "rejected";
+ else
+ {
+ AVRC_TRACE_WARNING("avrc_msg_cback %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
+ p_drop_msg,
+ handle, avrc_cb.ccb[handle].control, cr, opcode);
+ }
#endif
- cr = AVCT_RSP;
- drop = TRUE;
- }
- if (p_rsp)
- {
- /* set to send response right away */
- AVCT_MsgReq( handle, label, cr, p_rsp);
- drop = TRUE;
- }
- if (drop == FALSE)
- {
- msg.hdr.opcode = opcode;
- (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+ if (do_free)
+ GKI_freebuf(p_pkt);
}
-#if (BT_USE_TRACES == TRUE)
else
{
- AVRC_TRACE_WARNING("avrc_msg_cback %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
- p_drop_msg,
- handle, avrc_cb.ccb[handle].control, cr, opcode);
+ opcode = p_data[0];
+ AVRC_TRACE_DEBUG("opcode:%x, length:%x",opcode, p_pkt->len);
+ /*Do sanity Check here*/
+ if (cr == AVCT_CMD)
+ {
+ opcode = AVRC_OP_BROWSE;
+ msg.browse.browse_len = p_pkt->len;
+ AVRC_TRACE_DEBUG("Browsing length %x",msg.browse.browse_len);
+ /* Browse data remains same */
+ msg.browse.p_browse_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+ (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
+ }
+ else
+ {
+ AVRC_TRACE_ERROR("### expect AVCT_CMD");
+ }
+ /*Free the packet as the same already got copied in BTA*/
+ GKI_freebuf(p_pkt);
}
-#endif
-
- if (do_free)
- GKI_freebuf(p_pkt);
}
@@ -1076,7 +1093,7 @@ UINT16 AVRC_MsgReq (UINT8 handle, UINT8 label, UINT8 ctype, BT_HDR *p_pkt)
}
else
{
- AVRC_TRACE_ERROR ("AVRC_MsgReq no buffers for fragmentation" );
+ AVRC_TRACE_ERROR("AVRC_MsgReq no buffers for fragmentation" );
GKI_freebuf(p_pkt);
return AVRC_NO_RESOURCES;
}
diff --git a/stack/avrc/avrc_bld_tg.c b/stack/avrc/avrc_bld_tg.c
index a9b1a2adf..c4dfcf81e 100644
--- a/stack/avrc/avrc_bld_tg.c
+++ b/stack/avrc/avrc_bld_tg.c
@@ -28,6 +28,10 @@
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
+#define EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH 1
+#define EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH 5
+#define EVT_NOW_PLAYING_CHANGE_RSP_LENGTH 1
+
/*******************************************************************************
**
** Function avrc_bld_get_capability_rsp
@@ -639,6 +643,20 @@ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt)
status = AVRC_STS_BAD_PARAM;
break;
+ case AVRC_EVT_AVAL_PLAYERS_CHANGE:
+ len = EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH;
+ break;
+
+ case AVRC_EVT_ADDR_PLAYER_CHANGE:
+ UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.player_id);
+ UINT16_TO_BE_STREAM(p_data,p_rsp->param.addr_player.uid_counter);
+ len = EVT_ADDR_PLAYER_CHANGE_RSP_LENGTH;
+ break;
+
+ case AVRC_EVT_NOW_PLAYING_CHANGE:
+ len = EVT_NOW_PLAYING_CHANGE_RSP_LENGTH;
+ break;
+
default:
status = AVRC_STS_BAD_PARAM;
AVRC_TRACE_ERROR("unknown event_id");
@@ -671,6 +689,58 @@ static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
return AVRC_STS_NO_ERROR;
}
+/*****************************************************************************
+**
+** Function avrc_bld_set_address_player_rsp
+**
+** Description This function builds the set address player response
+**
+** Returns AVRC_STS_NO_ERROR, if the response is build successfully
+** Otherwise, the error code.
+**
+******************************************************************************/
+static tAVRC_STS avrc_bld_set_address_player_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ tAVRC_STS status = AVRC_STS_NO_ERROR;
+
+ AVRC_TRACE_API(" avrc_bld_set_address_player_rsp");
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ /* To calculate length */
+ p_data = p_start + 2;
+ /* add fixed lenth status(1) */
+ UINT16_TO_BE_STREAM(p_data, 1);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ p_pkt->len = (p_data - p_start);
+ return status;
+}
+
+/*****************************************************************************
+**
+** Function avrc_bld_play_item_rsp
+**
+** Description This function builds the play item response
+**
+** Returns AVRC_STS_NO_ERROR, if the response is build successfully
+** Otherwise, the error code.
+**
+******************************************************************************/
+static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ tAVRC_STS status = AVRC_STS_NO_ERROR;
+
+ AVRC_TRACE_API(" avrc_bld_play_item_rsp");
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ /* To calculate length */
+ p_data = p_start + 2;
+ /* add fixed lenth status(1) */
+ UINT16_TO_BE_STREAM(p_data, 1);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ p_pkt->len = (p_data - p_start);
+ return status;
+}
+
/*******************************************************************************
**
** Function avrc_bld_group_navigation_rsp
@@ -699,6 +769,256 @@ tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
return AVRC_STS_NO_ERROR;
}
+/*****************************************************************************
+**
+** Function avrc_bld_folder_item_values_rsp
+**
+** Description This function builds the folder item response.
+**
+** Returns AVRC_STS_NO_ERROR,if the response is built successfully
+** otherwise error code
+**
+******************************************************************************/
+static tAVRC_STS avrc_bld_folder_item_values_rsp(tAVRC_GET_ITEMS_RSP *p_rsp, BT_HDR *p_pkt )
+{
+ UINT8 *p_data, *p_start, *p_length, *p_media_element_len;
+ UINT8 *item_length;
+ UINT16 itemlength, param_length;
+ UINT16 length = 0, item_numb = 0, i, xx, media_attr_count;
+
+ AVRC_TRACE_DEBUG(" avrc_bld_folder_item_values_rsp offset :x%x", p_pkt->offset);
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ /* As per AVRCP spec, first byte of response is PDU ID
+ * and Response does not have any opcode
+ */
+ p_data = p_start;
+ /*First OCT carry PDU information */
+ *p_data++ = p_rsp->pdu;
+
+ /* Refer Media Play list AVRCP 1.5 22.19 (Get Folder Items)
+ * Mark a pointer to be filled once length is calculated at last
+ */
+ p_length = p_data;
+
+ /*increment to adjust length*/
+ p_data = p_data + 2;
+ /*Status is checked in Btif layer*/
+ *p_data++ = p_rsp->status;
+ if(p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ //TODO Response
+ AVRC_TRACE_ERROR(" ### Folder_item_values response error");
+ return p_rsp->status;
+ }
+ /*UID Counter OCT 4 and 5*/
+ UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+ /*Number of Items OCT 6 and 7*/
+ item_numb = p_rsp->item_count;
+ UINT16_TO_BE_STREAM(p_data, p_rsp->item_count);
+ param_length = 0;
+ for (i = 0; i < item_numb; i++)
+ {
+ itemlength = 0;
+ switch(p_rsp->p_item_list[i].item_type)
+ {
+ case AVRC_ITEM_PLAYER:
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+ itemlength = 28 + p_rsp->p_item_list[i].u.player.name.str_len;
+ UINT16_TO_BE_STREAM(p_data, itemlength);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.player_id);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.major_type);
+ UINT32_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.sub_type);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.play_status);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.features,\
+ AVRC_FEATURE_MASK_SIZE);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.player.name.p_str,\
+ p_rsp->p_item_list[i].u.player.name.str_len);
+ break;
+ case AVRC_ITEM_FOLDER:
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+ itemlength = 14 + p_rsp->p_item_list[i].u.folder.name.str_len;
+ UINT16_TO_BE_STREAM(p_data, itemlength);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.uid ,AVRC_UID_SIZE);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.type);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.playable);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.folder.name.p_str,\
+ p_rsp->p_item_list[i].u.folder.name.str_len);
+ break;
+ case AVRC_ITEM_MEDIA:
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].item_type);
+ p_media_element_len = p_data;
+ itemlength = 13 + p_rsp->p_item_list[i].u.media.name.str_len;
+ p_data = p_data + 2; /* for length */
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.uid ,AVRC_UID_SIZE);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.type);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.name.p_str,\
+ p_rsp->p_item_list[i].u.media.name.str_len);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_item_list[i].u.media.attr_count);
+ media_attr_count = p_rsp->p_item_list[i].u.media.attr_count;
+ itemlength += 1; /* for attribute count */
+ for (xx = 0; xx < media_attr_count; xx++)
+ {
+ itemlength += 8 + p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len;
+ UINT32_TO_BE_STREAM(p_data,\
+ p_rsp->p_item_list[i].u.media.p_attr_list[xx].attr_id);
+ UINT16_TO_BE_STREAM(p_data,\
+ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.charset_id);
+ UINT16_TO_BE_STREAM(p_data,\
+ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len);
+ ARRAY_TO_BE_STREAM(p_data,\
+ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.p_str,\
+ p_rsp->p_item_list[i].u.media.p_attr_list[xx].name.str_len);
+ }
+ UINT16_TO_BE_STREAM(p_media_element_len, itemlength);
+ break;
+ }
+ param_length += itemlength + 3; /* 3 to accommodate item_len and item_type */
+ }
+ param_length = param_length + 5; //Add explicit 5, 2 num items+ 2UID Counter + 1 status counter
+ UINT16_TO_BE_STREAM(p_length, param_length);
+ p_pkt->len = p_data - p_start;
+ return AVRC_STS_NO_ERROR;
+}
+
+/**************************************************************************************
+**
+** Function avrc_bld_change_path_rsp
+**
+** Description
+**
+** Returns
+**
+************************************************************************************/
+static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_pkt )
+{
+ UINT8 *p_data, *p_start;
+ UINT16 param_len; /* parameter length feild of Rsp */
+ UINT8 folder_index = 0;
+
+
+ AVRC_TRACE_DEBUG("avrc_bld_change_path_rsp offset :x%x", p_pkt->offset);
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start;
+ UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+ param_len = 5; /* refer spec */
+ UINT16_TO_BE_STREAM(p_data, param_len);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
+ p_pkt->len = p_data - p_start;
+ AVRC_TRACE_DEBUG("length = %d",p_pkt->len);
+ return AVRC_STS_NO_ERROR ;
+}
+
+/**************************************************************************************
+**
+** Function avrc_bld_set_browse_player_rsp
+**
+** Description
+**
+** Returns
+**
+************************************************************************************/
+static tAVRC_STS avrc_bld_set_browse_player_rsp (tAVRC_SET_BR_PLAYER_RSP *p_rsp, BT_HDR *p_pkt )
+{
+ UINT8 *p_data, *p_start;
+ UINT16 param_len_folder_name = 0;
+ UINT16 param_len; /* parameter length feild of Rsp */
+ UINT8 folder_index = 0;
+
+ AVRC_TRACE_DEBUG("avrc_bld_set_browse_player_rsp offset :x%x", p_pkt->offset);
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start;
+ UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+
+ for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++)
+ {
+ param_len_folder_name += p_rsp->p_folders[folder_index].str_len;
+ }
+ param_len = 10 + (p_rsp->folder_depth * 2) + param_len_folder_name; /* refer spec */
+
+ UINT16_TO_BE_STREAM(p_data, param_len);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+ UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->charset_id);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->folder_depth);
+
+ for(folder_index = 0; folder_index < p_rsp->folder_depth; folder_index++)
+ {
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_folders[folder_index].str_len);
+ ARRAY_TO_BE_STREAM(p_data,p_rsp->p_folders[folder_index].p_str, \
+ p_rsp->p_folders[folder_index].str_len);
+ }
+ p_pkt->len = p_data - p_start;
+ AVRC_TRACE_DEBUG("length = %d",p_pkt->len);
+ return AVRC_STS_NO_ERROR ;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_item_attrs_rsp
+**
+** Description This function builds the Get Item Attributes
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ UINT16 param_len;
+ UINT8 xx;
+
+ AVRC_TRACE_API("avrc_bld_get_item_attrs_rsp");
+ if (!p_rsp->p_attr_list)
+ {
+ AVRC_TRACE_ERROR("avrc_bld_get_item_attrs_rsp NULL parameter");
+ return AVRC_STS_BAD_PARAM;
+ }
+
+ /* get the existing length, if any, and also the num attributes */
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start;
+ UINT8_TO_BE_STREAM(p_data, p_rsp->pdu);
+
+ param_len = 2; /* for status and num_attr*/
+ for(xx = 0; xx < p_rsp->attr_count; xx++)
+ {
+ /* 8 for attr_id, char_set_id, attr_value_len */
+ param_len = param_len + 8 + p_rsp->p_attr_list[xx].name.str_len;
+ }
+ AVRC_TRACE_API(" param_len = %d ", param_len);
+ UINT16_TO_BE_STREAM(p_data, param_len);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->attr_count);
+
+ for (xx=0; xx < p_rsp->attr_count; xx++)
+ {
+ if ( !p_rsp->p_attr_list[xx].name.p_str )
+ {
+ p_rsp->p_attr_list[xx].name.str_len = 0;
+ }
+ UINT32_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].attr_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.p_str, \
+ p_rsp->p_attr_list[xx].name.str_len);
+ }
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+
+
/*******************************************************************************
**
** Function avrc_bld_rejected_rsp
@@ -728,6 +1048,34 @@ static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt )
/*******************************************************************************
**
+** Function avrc_bld_browse_rejected_rsp
+**
+** Description This function builds the Browse Reject response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_browse_rejected_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+
+ AVRC_TRACE_API("avrc_bld_browse_rejected_rsp: status=%d, pdu:x%x, offset=%d", p_rsp->status,
+ p_rsp->pdu, p_pkt->offset);
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start;
+ *p_data++ = p_rsp->pdu;
+
+ UINT16_TO_BE_STREAM(p_data, 1); //Parameter length
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ p_pkt->len = p_data - p_start;
+ AVRC_TRACE_DEBUG("Browse rejected rsp length=%d", p_pkt->len);
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
** Function avrc_bld_init_rsp_buffer
**
** Description This function initializes the response buffer based on PDU
@@ -902,6 +1250,14 @@ tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
break;
+
+ case AVRC_PDU_SET_ADDRESSED_PLAYER: /*PDU 0x60*/
+ status = avrc_bld_set_address_player_rsp(&p_rsp->addr_player, p_pkt);
+ break;
+
+ case AVRC_PDU_PLAY_ITEM:
+ status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt);
+ break;
}
if (alloc && (status != AVRC_STS_NO_ERROR) )
@@ -913,5 +1269,110 @@ tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt
return status;
}
+/*******************************************************************************
+**
+** Function avrc_bld_init_browse_rsp_buffer
+**
+** Description This function initializes the response buffer based on PDU
+**
+** Returns NULL, if no GKI buffer or failure to build the message.
+** Otherwise, the GKI buffer that contains the initialized message.
+**
+*******************************************************************************/
+static BT_HDR *avrc_bld_init_browse_rsp_buffer(tAVRC_RESPONSE *p_rsp)
+{
+ UINT16 offset = AVCT_BROWSE_OFFSET;
+ UINT16 chnl = AVCT_DATA_BROWSE;
+ UINT16 len = AVRC_BROWSE_POOL_SIZE;
+ BT_HDR *p_pkt = NULL;
+
+ AVRC_TRACE_API("avrc_bld_init_browse_rsp_buffer ");
+ /* allocate and initialize the buffer */
+ p_pkt = (BT_HDR *)GKI_getbuf(len);
+
+ if (p_pkt != NULL)
+ {
+ p_pkt->layer_specific = chnl;
+ p_pkt->event = AVRC_OP_BROWSE; /* Browsing Opcode */
+ p_pkt->offset = offset;
+ }
+ else
+ {
+ AVRC_TRACE_ERROR("### browse_rsp_buffer BUFF not allocated");
+ }
+ return p_pkt;
+}
+
+/*******************************************************************************
+**
+** Function AVRC_BldBrowseResponse
+**
+** Description This function builds the given AVRCP response to the given
+** GKI buffer
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+tAVRC_STS AVRC_BldBrowseResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt)
+{
+ tAVRC_STS status = AVRC_STS_BAD_PARAM;
+ BT_HDR *p_pkt;
+ BOOLEAN alloc = FALSE;
+
+ if (!p_rsp || !pp_pkt)
+ {
+ AVRC_TRACE_ERROR("### BldResponse error p_rsp=%p, pp_pkt=%p",
+ p_rsp, pp_pkt);
+ return AVRC_STS_BAD_PARAM;
+ }
+
+ if (*pp_pkt == NULL)
+ {
+ if ((*pp_pkt = avrc_bld_init_browse_rsp_buffer(p_rsp)) == NULL)
+ {
+ AVRC_TRACE_ERROR("### BldResponse: Failed to initialize response buffer");
+ return AVRC_STS_INTERNAL_ERR;
+ }
+ alloc = TRUE;
+ }
+ status = AVRC_STS_NO_ERROR;
+ p_pkt = *pp_pkt;
+
+ AVRC_TRACE_API("BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
+ if (p_rsp->rsp.status != AVRC_STS_NO_ERROR)
+ {
+ AVRC_TRACE_ERROR("###ERROR AVRC_BldBrowseResponse");
+ return (avrc_bld_browse_rejected_rsp(&p_rsp->rsp, p_pkt));
+ }
+
+ switch (p_rsp->pdu)
+ {
+ case AVRC_PDU_GET_FOLDER_ITEMS:
+ status = avrc_bld_folder_item_values_rsp(&p_rsp->get_items, p_pkt);
+ break;
+
+ case AVRC_PDU_SET_BROWSED_PLAYER:
+ status = avrc_bld_set_browse_player_rsp(&p_rsp->br_player, p_pkt);
+ break;
+
+ case AVRC_PDU_CHANGE_PATH:
+ status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_ITEM_ATTRIBUTES:
+ status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
+ break;
+ default :
+ break;
+ }
+ if (alloc && (status != AVRC_STS_NO_ERROR) )
+ {
+ GKI_freebuf(p_pkt);
+ *pp_pkt = NULL;
+ AVRC_TRACE_ERROR("### error status:%d",status);
+ }
+ return status;
+}
#endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
diff --git a/stack/avrc/avrc_int.h b/stack/avrc/avrc_int.h
index 36bb0c5fa..feb2b0e99 100644
--- a/stack/avrc/avrc_int.h
+++ b/stack/avrc/avrc_int.h
@@ -42,6 +42,7 @@
/* Number of protocol elements in protocol element list. */
#define AVRC_NUM_PROTO_ELEMS 2
+#define AVRC_NUM_ADDL_PROTO_ELEMS 1
#ifndef AVRC_MIN_CMD_LEN
#define AVRC_MIN_CMD_LEN 20
diff --git a/stack/avrc/avrc_pars_tg.c b/stack/avrc/avrc_pars_tg.c
index 6e39c1c5a..b75ee907c 100644
--- a/stack/avrc/avrc_pars_tg.c
+++ b/stack/avrc/avrc_pars_tg.c
@@ -267,7 +267,31 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_
/* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
/* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
+ case AVRC_PDU_SET_ADDRESSED_PLAYER:
+ if (len != 2)
+ {
+ status = AVRC_STS_NOT_FOUND;
+ AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER: bad len");
+ }
+ else
+ {
+ BE_STREAM_TO_UINT16 (p_result->addr_player.player_id, p);
+ }
+ break;
+ case AVRC_PDU_PLAY_ITEM:
+ if (len != 11)
+ {
+ status = AVRC_STS_NOT_FOUND;
+ AVRC_TRACE_ERROR("AVRC_PDU_PLAY_ITEM: bad len");
+ }
+ else
+ {
+ BE_STREAM_TO_UINT8 (p_result->play_item.scope, p);
+ BE_STREAM_TO_UINT64(p_result->play_item.uid, p);
+ BE_STREAM_TO_UINT16 (p_result->play_item.uid_counter, p);
+ }
+ break;
default:
status = AVRC_STS_BAD_CMD;
break;
diff --git a/stack/avrc/avrc_sdp.c b/stack/avrc/avrc_sdp.c
index ba10c1c5a..96582110b 100644
--- a/stack/avrc/avrc_sdp.c
+++ b/stack/avrc/avrc_sdp.c
@@ -27,6 +27,7 @@
#include "avrc_api.h"
#include "avrc_int.h"
+
#ifndef SDP_AVRCP_1_4
#define SDP_AVRCP_1_4 FALSE
#endif
@@ -49,6 +50,9 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] =
#if SDP_AVCTP_1_4 == TRUE
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }
#else
+#if SDP_AVRCP_1_5 == TRUE
+ {UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }
+#else
#if SDP_AVRCP_1_4 == TRUE
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} }
#else
@@ -59,8 +63,18 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] =
#endif
#endif
#endif
+#endif
};
+#if SDP_AVRCP_1_5 == TRUE
+const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] =
+{
+ {AVRC_NUM_PROTO_ELEMS,
+ {
+ {UUID_PROTOCOL_L2CAP, 1, {AVCT_BR_PSM, 0} },
+ {UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }}}
+};
+#else
#if SDP_AVRCP_1_4 == TRUE
const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] =
{
@@ -70,6 +84,7 @@ const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] =
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} }}}
};
#endif
+#endif
/******************************************************************************
@@ -242,6 +257,13 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name,
count = 2;
}
#else
+#if SDP_AVRCP_1_5 == TRUE
+ if( service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL )
+ {
+ class_list[1] = UUID_SERVCLASS_AV_REM_CTRL_CONTROL;
+ count = 2;
+ }
+#else
#if SDP_AVRCP_1_4 == TRUE
if( service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL )
{
@@ -250,24 +272,35 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name,
}
#endif
#endif
+#endif
result &= SDP_AddServiceClassIdList(sdp_handle, count, class_list);
/* add protocol descriptor list */
result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS, (tSDP_PROTOCOL_ELEM *)avrc_proto_list);
/* add profile descriptor list */
+#if SDP_AVRCP_1_5 == TRUE
+ /* additional protocol list to include browsing channel */
+ result &= SDP_AddAdditionProtoLists( sdp_handle, AVRC_NUM_ADDL_PROTO_ELEMS,
+ (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_list);
+
+ result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_5);
+#else
#if SDP_AVRCP_1_4 == TRUE
/* additional protocol list to include browsing channel */
result &= SDP_AddAdditionProtoLists( sdp_handle, 1, (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_list);
- result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_4);
+ result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_5);
#else
#if AVRC_METADATA_INCLUDED == TRUE
+
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_3);
+
#else
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_0);
#endif
#endif
+#endif
/* add supported categories */
p = temp;
diff --git a/stack/avrc/avrc_utils.c b/stack/avrc/avrc_utils.c
index 432ecc0cd..9c9082f79 100644
--- a/stack/avrc/avrc_utils.c
+++ b/stack/avrc/avrc_utils.c
@@ -59,6 +59,8 @@ BOOLEAN AVRC_IsValidAvcType(UINT8 pdu_id, UINT8 avc_type)
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
+ case AVRC_PDU_SET_ADDRESSED_PLAYER:
+ case AVRC_PDU_PLAY_ITEM:
if (avc_type == AVRC_CMD_CTRL)
result=TRUE;
break;