summaryrefslogtreecommitdiffstats
path: root/stack/avrc/avrc_bld_tg.c
diff options
context:
space:
mode:
Diffstat (limited to 'stack/avrc/avrc_bld_tg.c')
-rw-r--r--stack/avrc/avrc_bld_tg.c1547
1 files changed, 1547 insertions, 0 deletions
diff --git a/stack/avrc/avrc_bld_tg.c b/stack/avrc/avrc_bld_tg.c
new file mode 100644
index 0000000..667499e
--- /dev/null
+++ b/stack/avrc/avrc_bld_tg.c
@@ -0,0 +1,1547 @@
+/*****************************************************************************
+**
+** Name: avrc_bld_tg.c
+**
+** Description:Interface to AVRCP build message functions for the Target Role
+**
+** Copyright (c) 2008-2008, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "gki.h"
+#include "avrc_api.h"
+#include "avrc_defs.h"
+#include "avrc_int.h"
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+#if (AVRC_METADATA_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** 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 avrc_bld_list_app_settings_attr_rsp
+**
+** Description This function builds the List Application Settings Attribute
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len, *p_num;
+ UINT16 len = 0;
+ UINT8 xx;
+
+ AVRC_TRACE_API0("avrc_bld_list_app_settings_attr_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);
+ p_num = p_data;
+ if (len == 0)
+ {
+ /* first time initialize the attribute count */
+ *p_num = 0;
+ p_data++;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+ for (xx=0; xx<p_rsp->num_attr; xx++)
+ {
+ if(AVRC_IsValidPlayerAttr(p_rsp->attrs[xx]))
+ {
+ (*p_num)++;
+ UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]);
+ }
+ }
+
+ len = *p_num + 1;
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_list_app_settings_values_rsp
+**
+** Description This function builds the List Application Setting Values
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len, *p_num;
+ UINT8 xx;
+ UINT16 len;
+
+ AVRC_TRACE_API0("avrc_bld_list_app_settings_values_rsp");
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_len = p_start + 2; /* pdu + rsvd */
+
+ /* get the existing length, if any, and also the num attributes */
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_num = p_data;
+ /* first time initialize the attribute count */
+ if (len == 0)
+ {
+ *p_num = p_rsp->num_val;
+ p_data++;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ *p_num += p_rsp->num_val;
+ }
+
+
+ for (xx=0; xx<p_rsp->num_val; xx++)
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]);
+ }
+
+ len = *p_num + 1;
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_cur_app_setting_value_rsp
+**
+** Description This function builds the Get Current Application Setting Value
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len, *p_count;
+ UINT16 len;
+ UINT8 xx;
+
+ if (!p_rsp->p_vals)
+ {
+ AVRC_TRACE_ERROR0("avrc_bld_get_cur_app_setting_value_rsp NULL parameter");
+ return AVRC_STS_BAD_PARAM;
+ }
+
+ AVRC_TRACE_API0("avrc_bld_get_cur_app_setting_value_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);
+ p_count = p_data;
+ if (len == 0)
+ {
+ /* first time initialize the attribute count */
+ *p_count = 0;
+ p_data++;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+ for (xx=0; xx<p_rsp->num_val; xx++)
+ {
+ if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val))
+ {
+ (*p_count)++;
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val);
+ }
+ }
+ len = ((*p_count) << 1) + 1;
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_set_app_setting_value_rsp
+**
+** Description This function builds the Set Application Setting Value
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_set_app_setting_value_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ /* nothing to be added. */
+ AVRC_TRACE_API0("avrc_bld_set_app_setting_value_rsp");
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_app_setting_text_rsp
+**
+** Description This function builds the Get Application Settings Attribute Text
+** or Get Application Settings Value Text response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len, *p_count;
+ UINT16 len, len_left;
+ UINT8 xx;
+ tAVRC_STS sts = AVRC_STS_NO_ERROR;
+ UINT8 num_added = 0;
+
+ if (!p_rsp->p_attrs)
+ {
+ AVRC_TRACE_ERROR0("avrc_bld_app_setting_text_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_len = p_start + 2; /* pdu + rsvd */
+ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE - p_pkt->offset - p_pkt->len;
+
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_count = p_data;
+
+ if (len == 0)
+ {
+ *p_count = 0;
+ p_data++;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+ for (xx=0; xx<p_rsp->num_attr; xx++)
+ {
+ if (len_left < (p_rsp->p_attrs[xx].str_len + 4))
+ {
+ AVRC_TRACE_ERROR3("avrc_bld_app_setting_text_rsp out of room (str_len:%d, left:%d)",
+ xx, p_rsp->p_attrs[xx].str_len, len_left);
+ p_rsp->num_attr = num_added;
+ sts = AVRC_STS_INTERNAL_ERR;
+ break;
+ }
+ if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str )
+ {
+ AVRC_TRACE_ERROR1("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx);
+ continue;
+ }
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len);
+ (*p_count)++;
+ num_added++;
+ }
+ len = p_data - p_count;
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+
+ return sts;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_app_setting_attr_text_rsp
+**
+** Description This function builds the Get Application Setting Attribute Text
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ AVRC_TRACE_API0("avrc_bld_get_app_setting_attr_text_rsp");
+ return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_app_setting_value_text_rsp
+**
+** Description This function builds the Get Application Setting Value Text
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ AVRC_TRACE_API0("avrc_bld_get_app_setting_value_text_rsp");
+ return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_inform_charset_rsp
+**
+** Description This function builds the Inform Displayable Character Set
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_inform_charset_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ /* nothing to be added. */
+ AVRC_TRACE_API0("avrc_bld_inform_charset_rsp");
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_inform_battery_status_rsp
+**
+** Description This function builds the Inform Battery Status
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_inform_battery_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ /* nothing to be added. */
+ AVRC_TRACE_API0("avrc_bld_inform_battery_status_rsp");
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_elem_attrs_rsp
+**
+** Description This function builds the Get Element Attributes
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len, *p_count;
+ UINT16 len;
+ UINT8 xx;
+
+ AVRC_TRACE_API0("avrc_bld_get_elem_attrs_rsp");
+ if (!p_rsp->p_attrs)
+ {
+ AVRC_TRACE_ERROR0("avrc_bld_get_elem_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_len = p_start + 2; /* pdu + rsvd */
+
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_count = p_data;
+
+ if (len == 0)
+ {
+ *p_count = 0;
+ p_data++;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+ for (xx=0; xx<p_rsp->num_attr; xx++)
+ {
+ if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id))
+ {
+ AVRC_TRACE_ERROR2("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id);
+ continue;
+ }
+ if ( !p_rsp->p_attrs[xx].name.p_str )
+ {
+ p_rsp->p_attrs[xx].name.str_len = 0;
+ }
+ UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len);
+ (*p_count)++;
+ }
+ len = p_data - p_count;
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_play_status_rsp
+**
+** Description This function builds the Get Play Status
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+
+ AVRC_TRACE_API0("avrc_bld_get_play_status_rsp");
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start + 2;
+
+ /* add fixed lenth - song len(4) + song position(4) + status(1) */
+ UINT16_TO_BE_STREAM(p_data, 9);
+ UINT32_TO_BE_STREAM(p_data, p_rsp->song_len);
+ UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->play_status);
+ p_pkt->len = (p_data - p_start);
+
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_notify_rsp
+**
+** Description This function builds the Notification response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ UINT8 *p_len;
+ UINT16 len = 0;
+ UINT8 xx;
+ tAVRC_STS status = AVRC_STS_NO_ERROR;
+
+ AVRC_TRACE_API0("avrc_bld_notify_rsp");
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_len = p_start + 2; /* pdu + rsvd */
+ p_data += 2;
+
+ UINT8_TO_BE_STREAM(p_data, p_rsp->event_id);
+ switch (p_rsp->event_id)
+ {
+ case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */
+ /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */
+ if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) ||
+ (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) )
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status);
+ len = 2;
+ }
+ else
+ {
+ AVRC_TRACE_ERROR0("bad play state");
+ status = AVRC_STS_BAD_PARAM;
+ }
+ break;
+
+ case AVRC_EVT_TRACK_CHANGE: /* 0x02 */
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE);
+ len = (UINT8)(AVRC_UID_SIZE + 1);
+ break;
+
+ case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */
+ case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+ case AVRC_EVT_NOW_PLAYING_CHANGE: /* 0x09 */
+ case AVRC_EVT_AVAL_PLAYERS_CHANGE: /* 0x0a */
+#endif
+ len = 1;
+ break;
+
+ case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */
+ UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos);
+ len = 5;
+ break;
+
+ case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */
+ if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status))
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status);
+ len = 2;
+ }
+ else
+ {
+ AVRC_TRACE_ERROR0("bad battery status");
+ status = AVRC_STS_BAD_PARAM;
+ }
+ break;
+
+ case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */
+ if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status))
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status);
+ len = 2;
+ }
+ else
+ {
+ AVRC_TRACE_ERROR0("bad system status");
+ status = AVRC_STS_BAD_PARAM;
+ }
+ break;
+
+ case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */
+ if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS)
+ p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
+
+ if (p_rsp->param.player_setting.num_attr > 0)
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr);
+ len = 2;
+ for (xx=0; xx<p_rsp->param.player_setting.num_attr; xx++)
+ {
+ if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx], p_rsp->param.player_setting.attr_value[xx]))
+ {
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]);
+ }
+ else
+ {
+ AVRC_TRACE_ERROR0("bad player app seeting attribute or value");
+ status = AVRC_STS_BAD_PARAM;
+ break;
+ }
+ len += 2;
+ }
+ }
+ else
+ status = AVRC_STS_BAD_PARAM;
+ break;
+
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+ case AVRC_EVT_ADDR_PLAYER_CHANGE: /* 0x0b */
+ UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.player_id); /* player_id */
+ UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.uid_counter); /* uid counter */
+ len = 5;
+ break;
+
+ case AVRC_EVT_UIDS_CHANGE: /* 0x0c */
+ UINT16_TO_BE_STREAM(p_data, p_rsp->param.uid_counter); /* uid counter */
+ len = 3;
+ break;
+
+ case AVRC_EVT_VOLUME_CHANGE: /* 0x0d */
+ UINT8_TO_BE_STREAM(p_data, (UINT8)(p_rsp->param.volume&AVRC_MAX_VOLUME));
+ len = 2;
+ break;
+#endif
+
+ default:
+ status = AVRC_STS_BAD_PARAM;
+ AVRC_TRACE_ERROR0("unknown event_id");
+ }
+
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_next_rsp
+**
+** Description This function builds the Request Continue or Abort
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ /* nothing to be added. */
+ AVRC_TRACE_API0("avrc_bld_next_rsp");
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_group_navigation_rsp
+**
+** Description This function builds the Group Navigation
+** response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
+{
+ UINT8 *p_data;
+
+ if (!AVRC_IS_VALID_GROUP(navi_id))
+ {
+ AVRC_TRACE_ERROR1("avrc_bld_group_navigation_rsp bad navigation op id: %d", navi_id);
+ return AVRC_STS_BAD_PARAM;
+ }
+
+ AVRC_TRACE_API0("avrc_bld_group_navigation_rsp");
+ p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+ UINT16_TO_BE_STREAM(p_data, navi_id);
+ p_pkt->len = 2;
+ return AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_rejected_rsp
+**
+** Description This function builds the General Response response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt )
+{
+ UINT8 *p_data, *p_start;
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu);
+#endif
+
+ AVRC_TRACE_API2("avrc_bld_rejected_rsp: status=%d, pdu:x%x", p_rsp->status, p_rsp->pdu);
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ if (opcode == AVRC_OP_BROWSE)
+ {
+ p_data = p_start + 1;
+ if (avrc_opcode_from_pdu(*p_start) != AVRC_OP_BROWSE)
+ {
+ /* if the given opcode is not recognized as a browsing command opcode, use general reject command */
+ *p_start = AVRC_PDU_GENERAL_REJECT;
+ }
+ }
+ else
+#endif
+ {
+ p_data = p_start + 2;
+ }
+ AVRC_TRACE_DEBUG1("pdu:x%x", *p_start);
+
+ UINT16_TO_BE_STREAM(p_data, 1);
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ p_pkt->len = p_data - p_start;
+
+ return AVRC_STS_NO_ERROR;
+}
+
+
+/*****************************************************************************
+** the following commands are introduced in AVRCP 1.4
+*****************************************************************************/
+
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function avrc_bld_ctrl_status_rsp
+**
+** Description This function builds the responses with a UINT8 parameter.
+**
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_ctrl_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start + 2; /* pdu + rsvd */
+
+ /* 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 AVRC_STS_NO_ERROR;
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_set_addr_player_rsp
+**
+** Description This function builds the Set Addresses Player response.
+**
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_set_addr_player_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ AVRC_TRACE_API0("avrc_bld_set_addr_player_rsp");
+ return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function avrc_bld_set_abs_volume_rsp
+**
+** Description This function builds the Set Absolute Volume response.
+**
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_set_abs_volume_rsp (tAVRC_SET_VOLUME_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ p_rsp->status = (p_rsp->volume & AVRC_MAX_VOLUME);
+ AVRC_TRACE_API2("avrc_bld_set_abs_volume_rsp volume:%d, sts:%d", p_rsp->volume, p_rsp->status);
+ return avrc_bld_ctrl_status_rsp((tAVRC_RSP *)p_rsp, p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_set_browsed_player_rsp
+**
+** Description This function builds the Set Browsed Player response.
+**
+** This message goes through the Browsing channel and is
+** valid only when AVCT_BROWSE_INCLUDED compile option is TRUE
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+static tAVRC_STS avrc_bld_set_browsed_player_rsp (tAVRC_SET_BR_PLAYER_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ UINT8 *p_len, xx;
+ UINT16 len;
+ tAVRC_NAME *p_folders = p_rsp->p_folders;
+ UINT16 len_left;
+ UINT8 *p_num;
+ UINT16 mtu;
+
+ AVRC_TRACE_API0("avrc_bld_set_browsed_player_rsp");
+ /* make sure the given GKI buffer can accomodate this response */
+ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE;
+ p_data = (UINT8 *)(p_pkt + 1);
+ BE_STREAM_TO_UINT16 (mtu, p_data);
+ if (len_left > mtu)
+ {
+ len_left = mtu;
+ }
+ len_left = len_left - p_pkt->offset - p_pkt->len;
+ AVRC_TRACE_DEBUG2("len_left:%d, mtu:%d ", len_left, mtu);
+
+ /* 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 + 1; /* pdu */
+
+ /* the existing len */
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_num = p_data + 9;
+ if (len == 0)
+ {
+ /* first time initialize the attribute count */
+ 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);
+ *p_num = 0;
+ p_data++;
+ len = 10;
+ len_left -= 12; /* assuming that we would never use a GKI buffer that is too small for headers */
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+ for (xx=0; (xx<p_rsp->folder_depth) && (len_left>(p_folders[xx].str_len + 2)); xx++)
+ {
+ (*p_num)++;
+ UINT16_TO_BE_STREAM(p_data, p_folders[xx].str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_folders[xx].p_str, p_folders[xx].str_len);
+ len += (p_folders[xx].str_len + 2);
+ }
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_folder_items_rsp
+**
+** Description This function builds the Get Folder Items response.
+** The error code is returned in *p_status.
+** AVRC_STS_INTERNAL_ERR means no GKI buffers.
+** Try again later or with smaller item_count
+**
+** This message goes through the Browsing channel and is
+** valid only when AVCT_BROWSE_INCLUDED compile option is TRUE
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** AVRC_STS_INTERNAL_ERR, if the given GKI buffer does not have enough room
+** Otherwise, the error code.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+static tAVRC_STS avrc_bld_get_folder_items_rsp (tAVRC_GET_ITEMS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ UINT8 *p_len, xx;
+ UINT16 len;
+ UINT16 item_len;
+ UINT8 *p_item_len, yy;
+ tAVRC_ITEM_PLAYER *p_player;
+ tAVRC_ITEM_FOLDER *p_folder;
+ tAVRC_ITEM_MEDIA *p_media;
+ tAVRC_ATTR_ENTRY *p_attr;
+ tAVRC_ITEM *p_item_list = p_rsp->p_item_list;
+ tAVRC_STS status = AVRC_STS_NO_ERROR;
+ UINT16 len_left;
+ UINT8 *p_num, *p;
+ UINT8 *p_item_start, *p_attr_count;
+ UINT16 item_count;
+ UINT16 mtu;
+
+ AVRC_TRACE_API0("avrc_bld_get_folder_items_rsp");
+ /* make sure the given GKI buffer can accomodate this response */
+ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE;
+ p = (UINT8 *)(p_pkt + 1);
+ BE_STREAM_TO_UINT16 (mtu, p);
+ if (len_left > mtu)
+ len_left = mtu;
+ len_left = len_left - p_pkt->offset - p_pkt->len;
+
+ /* 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 + 1; /* pdu */
+
+ /* the existing len */
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_num = p_data + 3;
+ if (len == 0)
+ {
+ /* first time initialize the attribute count */
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
+ item_count = 0;
+ p_data+= 2;
+ len = 5;
+ len_left -= 5;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ p = p_num;
+ BE_STREAM_TO_UINT16 (item_count, p);
+ }
+ AVRC_TRACE_DEBUG3("len:%d, len_left:%d, num:%d", len, len_left, item_count);
+
+ /* min len required = item_type(1) + item len(2) + min item (14) = 17 */
+ for (xx=0; xx<p_rsp->item_count && len_left > 17; xx++)
+ {
+ p_item_start = p_data;
+ UINT8_TO_BE_STREAM(p_data, p_item_list[xx].item_type);
+ /* variable item lenth - save the location to add length */
+ p_item_len = p_data;
+ p_data += 2;
+ item_len = 0;
+ len_left -= 3; /* item_type(1) + item len(2) */
+ switch (p_item_list[xx].item_type)
+ {
+ case AVRC_ITEM_PLAYER:
+ /* min len required: 2 + 1 + 4 + 1 + 16 + 2 + 2 = 30 + str_len */
+ p_player = &p_item_list[xx].u.player;
+ item_len = AVRC_FEATURE_MASK_SIZE + p_player->name.str_len + 12;
+ if ((len_left > item_len) &&
+ p_player->name.p_str &&
+ (p_player->major_type & AVRC_MJ_TYPE_INVALID) == 0 &&
+ (p_player->sub_type & AVRC_SUB_TYPE_INVALID) == 0 &&
+ (p_player->play_status <= AVRC_PLAYSTATE_REV_SEEK || p_player->play_status == AVRC_PLAYSTATE_ERROR) )
+ {
+ UINT16_TO_BE_STREAM(p_data, p_player->player_id);
+ UINT8_TO_BE_STREAM(p_data, p_player->major_type);
+ UINT32_TO_BE_STREAM(p_data, p_player->sub_type);
+ UINT8_TO_BE_STREAM(p_data, p_player->play_status);
+ ARRAY_TO_BE_STREAM(p_data, p_player->features, AVRC_FEATURE_MASK_SIZE);
+ UINT16_TO_BE_STREAM(p_data, p_player->name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_player->name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_player->name.p_str, p_player->name.str_len);
+ }
+ else
+ {
+ p_data = p_item_start;
+ }
+ break;
+
+ case AVRC_ITEM_FOLDER:
+ /* min len required: 8 + 1 + 1 + 2 + 2 = 14 + str_len */
+ p_folder = &p_item_list[xx].u.folder;
+ item_len = AVRC_UID_SIZE + p_folder->name.str_len + 6;
+ if ((len_left > item_len) &&
+ p_folder->name.p_str &&
+ p_folder->type <= AVRC_FOLDER_TYPE_YEARS &&
+ p_folder->playable <= TRUE)
+ {
+ ARRAY_TO_BE_STREAM(p_data, p_folder->uid, AVRC_UID_SIZE);
+ UINT8_TO_BE_STREAM(p_data, p_folder->type);
+ UINT8_TO_BE_STREAM(p_data, p_folder->playable);
+ UINT16_TO_BE_STREAM(p_data, p_folder->name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_folder->name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_folder->name.p_str, p_folder->name.str_len);
+ }
+ else
+ {
+ p_data = p_item_start;
+ }
+ break;
+
+ case AVRC_ITEM_MEDIA:
+ /* min len required: 8 + 1 + 2 + 2 + 1 = 14 + str_len */
+ p_media = &p_item_list[xx].u.media;
+ item_len = AVRC_UID_SIZE + p_media->name.str_len + 6;
+ if ((len_left > item_len) &&
+ p_media->name.p_str &&
+ p_media->type <= AVRC_MEDIA_TYPE_VIDEO)
+ {
+ ARRAY_TO_BE_STREAM(p_data, p_media->uid, AVRC_UID_SIZE);
+ UINT8_TO_BE_STREAM(p_data, p_media->type);
+ UINT16_TO_BE_STREAM(p_data, p_media->name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_media->name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_media->name.p_str, p_media->name.str_len);
+ p_attr_count = p_data++;
+ *p_attr_count = 0;
+ len_left -= item_len;
+ if (p_media->attr_count>0)
+ {
+ p_attr = p_media->p_attr_list;
+ for (yy=0; yy<p_media->attr_count && len_left > 8; yy++)
+ {
+ if (p_attr[yy].name.p_str &&
+ AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attr[yy].attr_id) &&
+ (len_left >= (p_attr[yy].name.str_len + 8)) )
+ {
+ (*p_attr_count) ++;
+ UINT32_TO_BE_STREAM(p_data, p_attr[yy].attr_id);
+ UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.charset_id);
+ UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.str_len);
+ ARRAY_TO_BE_STREAM(p_data, p_attr[yy].name.p_str, p_attr[yy].name.str_len);
+ item_len += (p_attr[yy].name.str_len + 8);
+ len_left -= (p_attr[yy].name.str_len + 8);
+ }
+ }
+ }
+ }
+ else
+ {
+ p_data = p_item_start;
+ }
+ break;
+ } /* switch item_type */
+
+ if (p_item_start != p_data)
+ {
+ /* successfully added the item */
+ item_count++;
+ /* fill in variable item lenth */
+ UINT16_TO_BE_STREAM(p_item_len, item_len);
+ }
+ else
+ {
+ /* some item is not added properly - set an error status */
+ if (len_left > item_len)
+ status = AVRC_STS_INTERNAL_ERR;
+ else
+ status = AVRC_STS_BAD_PARAM;
+ }
+
+ len += item_len;
+ len += 3; /* the item_type(1) and item_len(2) */
+ AVRC_TRACE_DEBUG4("len:%d, len_left:%d, num:%d, item_len:%d", len, len_left, item_count, item_len);
+ } /* for item_count */
+
+ UINT16_TO_BE_STREAM(p_num, item_count);
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+
+ if (p_rsp->item_count != xx)
+ {
+ p_rsp->item_count = xx;
+ if (status == AVRC_STS_NO_ERROR)
+ status = AVRC_STS_INTERNAL_ERR;
+ }
+
+ return status;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_change_path_rsp
+**
+** Description This function builds the Change Path response.
+**
+** This message goes through the Browsing channel and is
+** valid only when AVCT_BROWSE_INCLUDED compile option is TRUE
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+
+ /* get the existing length, if any, and also the num attributes */
+ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_data = p_start + 1; /* pdu */
+ /* add fixed lenth - status(1) + num_items(4) */
+ UINT16_TO_BE_STREAM(p_data, 5);
+ 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);
+ return AVRC_STS_NO_ERROR;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_get_item_attrs_rsp
+**
+** Description This function builds the Get Item Attributes response.
+**
+** This message goes through the Browsing channel and is
+** valid only when AVCT_BROWSE_INCLUDED compile option is TRUE
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** AVRC_STS_INTERNAL_ERR, if the given GKI buffer does not have enough room
+** Otherwise, the error code.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start;
+ UINT8 *p_len, xx;
+ UINT16 len, len_left;
+ UINT8 *p_num;
+ UINT16 mtu;
+
+ AVRC_TRACE_API0("avrc_bld_get_item_attrs_rsp");
+ /* calculate the GKI buffer size needed and validate the parameters */
+ if (!p_rsp->p_attr_list)
+ {
+ AVRC_TRACE_ERROR0("NULL p_attr_list");
+ return AVRC_STS_BAD_PARAM;
+ }
+
+ /* check the length before adding the attr to the message */
+ len = 2;
+ for (xx=0; xx<p_rsp->attr_count; xx++)
+ {
+ if(p_rsp->p_attr_list[xx].name.p_str == 0 ||
+ !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attr_list[xx].attr_id))
+ {
+ AVRC_TRACE_ERROR2("[%d] NULL p_attr_list str or bad attr_id:%d", xx, p_rsp->p_attr_list[xx].attr_id);
+ return AVRC_STS_BAD_PARAM;
+ }
+ len += (p_rsp->p_attr_list[xx].name.str_len + 8);
+ }
+ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE;
+ p_data = (UINT8 *)(p_pkt + 1);
+ BE_STREAM_TO_UINT16 (mtu, p_data);
+ if (len_left > mtu)
+ {
+ len_left = mtu;
+ }
+ len_left = len_left - p_pkt->offset - p_pkt->len;
+
+ AVRC_TRACE_DEBUG3("len_left:%d, mtu:%d len needed:%d", len_left, mtu, len);
+ if (len_left < 11) /* 11 is 4/attr_id + 2/charset_id + 2/str_len + 3/first timer/attr count & len */
+ {
+ return AVRC_STS_INTERNAL_ERR;
+ }
+ if (len > len_left)
+ {
+ AVRC_TRACE_ERROR0("The GKI buffer does not have enough room to hold the given data.");
+ }
+
+ /* 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 + 1; /* pdu */
+
+ /* the existing len */
+ BE_STREAM_TO_UINT16(len, p_data);
+ p_num = p_data + 1;
+ if (len == 0)
+ {
+ /* first time initialize the attribute count */
+ UINT8_TO_BE_STREAM(p_data, p_rsp->status);
+ *p_num = 0;
+ p_data++;
+ len = 2;
+ len_left -= 3;
+ }
+ else
+ {
+ p_data = p_start + p_pkt->len;
+ }
+
+
+ for (xx=0; (xx<p_rsp->attr_count) && (len_left>9); xx++)
+ {
+ (*p_num)++;
+ 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);
+ len_left -= 8;
+ if (p_rsp->p_attr_list[xx].name.str_len > len_left)
+ p_rsp->p_attr_list[xx].name.str_len = len_left;
+ ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.p_str, p_rsp->p_attr_list[xx].name.str_len);
+ len_left -= p_rsp->p_attr_list[xx].name.str_len;
+ len += (p_rsp->p_attr_list[xx].name.str_len + 8);
+ }
+
+ UINT16_TO_BE_STREAM(p_len, len);
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_search_rsp
+**
+** Description This function builds the Search response.
+**
+** This message goes through the Browsing channel and is
+** valid only when AVCT_BROWSE_INCLUDED compile option is TRUE
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+static tAVRC_STS avrc_bld_search_rsp (tAVRC_SEARCH_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ UINT8 *p_data, *p_start, *p_len;
+
+ AVRC_TRACE_API0("avrc_bld_search_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 + 1; /* pdu */
+
+ /* add fixed lenth - status(1) + uid_counter(2) + num_items(4) */
+ UINT16_TO_BE_STREAM(p_data, 7);
+ 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);
+ p_pkt->len = (p_data - p_start);
+ return AVRC_STS_NO_ERROR;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_play_item_rsp
+**
+** Description This function builds the Play Item response.
+**
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_play_item_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ AVRC_TRACE_API0("avrc_bld_play_item_rsp");
+ return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function avrc_bld_add_to_now_playing_rsp
+**
+** Description This function builds the Add to Now Playing response.
+**
+** Returns AVRC_STS_NO_ERROR, if the response is built successfully
+** Otherwise, the error code.
+**
+*******************************************************************************/
+static tAVRC_STS avrc_bld_add_to_now_playing_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
+{
+ AVRC_TRACE_API0("avrc_bld_add_to_now_playing_rsp");
+ return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
+}
+
+#endif /* AVRC_ADV_CTRL_INCLUDED=TRUE */
+
+/*******************************************************************************
+**
+** Function avrc_bld_init_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_rsp_buffer(tAVRC_RESPONSE *p_rsp)
+{
+ UINT16 offset, chnl = AVCT_DATA_CTRL, len=AVRC_META_CMD_POOL_SIZE;
+ BT_HDR *p_pkt=NULL;
+ UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu);
+
+ AVRC_TRACE_API3("avrc_bld_init_rsp_buffer: pdu=%x, opcode=%x/%x", p_rsp->pdu, opcode, p_rsp->rsp.opcode);
+ if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR && avrc_is_valid_opcode(p_rsp->rsp.opcode))
+ {
+ opcode = p_rsp->rsp.opcode;
+ AVRC_TRACE_API1("opcode=%x", opcode);
+ }
+
+ switch (opcode)
+ {
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ case AVRC_OP_BROWSE:
+ chnl = AVCT_DATA_BROWSE;
+ offset = AVCT_BROWSE_OFFSET;
+ len = AVRC_BROWSE_POOL_SIZE;
+ break;
+#endif /* AVCT_BROWSE_INCLUDED */
+
+ case AVRC_OP_PASS_THRU:
+ offset = AVRC_MSG_PASS_THRU_OFFSET;
+ break;
+
+ case AVRC_OP_VENDOR:
+ offset = AVRC_MSG_VENDOR_OFFSET;
+ if (p_rsp->pdu == AVRC_PDU_GET_ELEMENT_ATTR)
+ len = AVRC_BROWSE_POOL_SIZE;
+ break;
+ }
+
+ /* allocate and initialize the buffer */
+ p_pkt = (BT_HDR *)GKI_getbuf(len);
+ if (p_pkt)
+ {
+ UINT8 *p_data, *p_start;
+
+ p_pkt->layer_specific = chnl;
+ p_pkt->event = opcode;
+ p_pkt->offset = offset;
+ p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
+ p_start = p_data;
+
+ /* pass thru - group navigation - has a two byte op_id, so dont do it here */
+ if (opcode != AVRC_OP_PASS_THRU)
+ *p_data++ = p_rsp->pdu;
+
+ switch (opcode)
+ {
+ case AVRC_OP_VENDOR:
+ /* reserved 0, packet_type 0 */
+ UINT8_TO_BE_STREAM(p_data, 0);
+ /* continue to the next "case to add length */
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ case AVRC_OP_BROWSE:
+#endif
+ /* add fixed lenth - 0 */
+ UINT16_TO_BE_STREAM(p_data, 0);
+ break;
+ }
+
+ p_pkt->len = (p_data - p_start);
+ }
+ p_rsp->rsp.opcode = opcode;
+ return p_pkt;
+}
+
+/*******************************************************************************
+**
+** Function AVRC_BldResponse
+**
+** 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_BldResponse( 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 ((AVRC_ADV_CTRL_INCLUDED == TRUE) && (AVCT_BROWSE_INCLUDED == TRUE))
+ UINT8 *p;
+ UINT16 peer_mtu;
+#endif
+
+ if (!p_rsp || !pp_pkt)
+ {
+ AVRC_TRACE_API2("AVRC_BldResponse. Invalid parameters passed. 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_rsp_buffer(p_rsp)) == NULL)
+ {
+ AVRC_TRACE_API0("AVRC_BldResponse: Failed to initialize response buffer");
+ return AVRC_STS_INTERNAL_ERR;
+ }
+#if ((AVRC_ADV_CTRL_INCLUDED == TRUE) && (AVCT_BROWSE_INCLUDED == TRUE))
+ if ((*pp_pkt)->layer_specific == AVCT_DATA_BROWSE)
+ {
+ p = (UINT8 *)((*pp_pkt) + 1);
+ peer_mtu = AVCT_GetBrowseMtu(handle) - AVCT_HDR_LEN_SINGLE;
+ UINT16_TO_BE_STREAM(p, peer_mtu);
+ }
+#endif
+ alloc = TRUE;
+ }
+ status = AVRC_STS_NO_ERROR;
+ p_pkt = *pp_pkt;
+
+ AVRC_TRACE_API2("AVRC_BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
+ if (p_rsp->rsp.status != AVRC_STS_NO_ERROR)
+ {
+ return( avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt) );
+ }
+
+ switch (p_rsp->pdu)
+ {
+ case AVRC_PDU_NEXT_GROUP:
+ case AVRC_PDU_PREV_GROUP:
+ status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_CAPABILITIES:
+ status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_ATTR:
+ status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_VALUES:
+ status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
+ status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt);
+ break;
+
+ case AVRC_PDU_SET_PLAYER_APP_VALUE:
+ status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
+ status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
+ status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt);
+ break;
+
+ case AVRC_PDU_INFORM_DISPLAY_CHARSET:
+ status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
+ break;
+
+ case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
+ status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_ELEMENT_ATTR:
+ status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_PLAY_STATUS:
+ status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
+ break;
+
+ case AVRC_PDU_REGISTER_NOTIFICATION:
+ status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
+ break;
+
+ case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
+ status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
+ break;
+
+ case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
+ status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
+ break;
+
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+ case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
+ status = avrc_bld_set_abs_volume_rsp(&p_rsp->volume, p_pkt);
+ break;
+
+ case AVRC_PDU_SET_ADDRESSED_PLAYER: /* 0x60 */
+ status = avrc_bld_set_addr_player_rsp(&p_rsp->addr_player, p_pkt);
+ break;
+
+ case AVRC_PDU_PLAY_ITEM: /* 0x74 */
+ status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt);
+ break;
+
+ case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
+ status = avrc_bld_add_to_now_playing_rsp(&p_rsp->add_to_play, p_pkt);
+ break;
+
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ case AVRC_PDU_SET_BROWSED_PLAYER: /* 0x70 */
+ status = avrc_bld_set_browsed_player_rsp(&p_rsp->br_player, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
+ status = avrc_bld_get_folder_items_rsp(&p_rsp->get_items, p_pkt);
+ break;
+
+ case AVRC_PDU_CHANGE_PATH: /* 0x72 */
+ status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
+ break;
+
+ case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */
+ status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
+ break;
+
+ case AVRC_PDU_SEARCH: /* 0x80 */
+ status = avrc_bld_search_rsp(&p_rsp->search, p_pkt);
+ break;
+#endif
+#endif
+ }
+
+ if (alloc && (status != AVRC_STS_NO_ERROR) )
+ {
+ GKI_freebuf(p_pkt);
+ *pp_pkt = NULL;
+ }
+ AVRC_TRACE_API1("AVRC_BldResponse: returning %d", status);
+ return status;
+}
+
+#endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
+