Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e692cb19 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "AVRCP: Fix get metadata attribute responses"

parents b02bcd15 ea429616
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -1138,26 +1138,26 @@ void bta_av_sm_execute(tBTA_AV_CB* p_cb, uint16_t event, tBTA_AV_DATA* p_data) {
 *
 ******************************************************************************/
bool bta_av_hdl_event(BT_HDR* p_msg) {
  uint16_t event = p_msg->event;
  uint16_t first_event = BTA_AV_FIRST_NSM_EVT;

  if (event > BTA_AV_LAST_EVT) {
  if (p_msg->event > BTA_AV_LAST_EVT) {
    return true; /* to free p_msg */
  }

  if (event >= first_event) {
  if (p_msg->event >= BTA_AV_FIRST_NSM_EVT) {
#if (BTA_AV_DEBUG == TRUE)
    APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
    APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)", p_msg->event,
                       bta_av_evt_code(p_msg->event));
#else
    APPL_TRACE_VERBOSE("AV nsm event=0x%x", event);
    APPL_TRACE_VERBOSE("AV nsm event=0x%x", p_msg->event);
#endif
    /* non state machine events */
    (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT])((tBTA_AV_DATA*)p_msg);
  } else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT) {
    (*bta_av_nsm_act[p_msg->event - BTA_AV_FIRST_NSM_EVT])(
        (tBTA_AV_DATA*) p_msg);
  } else if (p_msg->event >= BTA_AV_FIRST_SM_EVT
      && p_msg->event <= BTA_AV_LAST_SM_EVT) {
#if (BTA_AV_DEBUG == TRUE)
    APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
    APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)", p_msg->event,
                       bta_av_evt_code(p_msg->event));
#else
    APPL_TRACE_VERBOSE("AV sm event=0x%x", event);
    APPL_TRACE_VERBOSE("AV sm event=0x%x", p_msg->event);
#endif
    /* state machine events */
    bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*) p_msg);
+77 −69
Original line number Diff line number Diff line
@@ -1388,6 +1388,65 @@ static uint8_t opcode_from_pdu(uint8_t pdu) {
  return opcode;
}

/***************************************************************************
 * Function:  fill_attribute_id_array
 *
 * - Argument:
 *     cmd_attribute_number         input attribute number from AVRCP command
 *     cmd_attribute_id_array       input attribute list from AVRCP command
 *     out_array_size               allocated size of out attribute id array
 *     out_attribute_id_array       output attribute list resolved here
 *
 * - Description:
 *     Resolve attribute id array as defined by the AVRCP specification.
 *
 * - Returns:
 *     The number of attributes filled in
 *
 ***************************************************************************/
static uint8_t fill_attribute_id_array(
    uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array,
    size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) {
  /* Reset attribute array */
  memset(out_attribute_id_array, 0, out_array_size);
  /* Default case for cmd_attribute_number == 0xFF, No attribute */
  uint8_t out_attribute_number = 0;
  if (cmd_attribute_number == 0) {
    /* All attributes */
    out_attribute_number =
        out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID ?
            out_array_size : AVRC_MAX_NUM_MEDIA_ATTR_ID;
    for (int i = 0; i < out_attribute_number; i++) {
      out_attribute_id_array[i] = (btrc_media_attr_t) (i + 1);
    }
  } else if (cmd_attribute_number != 0xFF) {
    /* Attribute List */
    out_attribute_number = 0;
    int filled_id_count = 0;
    for (int i = 0; (i < cmd_attribute_number)
            && (out_attribute_number < out_array_size)
            && (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID); i++) {
      /* Fill only valid entries */
      if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) {
        /* Skip the duplicate entries */
        for (filled_id_count = 0; filled_id_count < out_attribute_number;
            filled_id_count++) {
          if (out_attribute_id_array[filled_id_count]
              == cmd_attribute_id_array[i])
            break;
        }
        /* New ID */
        if (filled_id_count == out_attribute_number) {
          out_attribute_id_array[out_attribute_number] =
              (btrc_media_attr_t) cmd_attribute_id_array[i];
          out_attribute_number++;
        }
      }
    }
  }
  return out_attribute_number;
}

/*******************************************************************************
 *
 * Function         btif_rc_upstreams_evt
@@ -1424,51 +1483,17 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd,
    } break;
    case AVRC_PDU_GET_ELEMENT_ATTR: {
      btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
      uint8_t num_attr;
      memset(&element_attrs, 0, sizeof(element_attrs));
      if (pavrc_cmd->get_elem_attrs.num_attr == 0) {
        /* CT requests for all attributes */
        int attr_cnt;
        num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
        for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) {
          element_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1);
        }
      } else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF) {
        /* 0xff indicates, no attributes requested - reject */
      uint8_t num_attr = fill_attribute_id_array(
          pavrc_cmd->get_elem_attrs.num_attr,
          (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs,
          BTRC_MAX_ELEM_ATTR_SIZE, element_attrs);
      if (num_attr == 0) {
        BTIF_TRACE_ERROR(
            "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES",
            __func__);
        send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
                             AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
        return;
      } else {
        int attr_cnt, filled_attr_count;

        num_attr = 0;
        /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
         * hence HAL definition limits the attributes to
         * AVRC_MAX_NUM_MEDIA_ATTR_ID.
         * Fill only valid entries.
         */
        for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
                           (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID);
             attr_cnt++) {
          if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
              (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <=
               AVRC_MAX_NUM_MEDIA_ATTR_ID)) {
            /* Skip the duplicate entries : PTS sends duplicate entries for
             * Fragment cases
             */
            for (filled_attr_count = 0; filled_attr_count < num_attr;
                 filled_attr_count++) {
              if (element_attrs[filled_attr_count] ==
                  pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
                break;
            }
            if (filled_attr_count == num_attr) {
              element_attrs[num_attr] =
                  (btrc_media_attr_t)pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
              num_attr++;
            }
          }
        }
      }
      fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev);
      HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs,
@@ -1595,41 +1620,24 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd,

    case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
      btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
      uint8_t num_attr;
      uint8_t scope;
      uint16_t uid_counter;

      scope = pavrc_cmd->get_attrs.scope;
      uid_counter = pavrc_cmd->get_attrs.uid_counter;
      memset(&item_attrs, 0, sizeof(item_attrs));

      if (pavrc_cmd->get_attrs.attr_count == 0xFF) {
      uint8_t num_attr = fill_attribute_id_array(
          pavrc_cmd->get_elem_attrs.num_attr,
          (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs,
          BTRC_MAX_ELEM_ATTR_SIZE, item_attrs);
      if (num_attr == 0) {
        BTIF_TRACE_ERROR(
            "%s: No attributes are requested in GET_ITEM_ATTRIBUTES", __func__);
        /* 0xff indicates, no attributes requested - reject this */
            "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES",
            __func__);
        send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
                             AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
        return;
      }

      if (pavrc_cmd->get_attrs.attr_count == 0) {
        /* CT requests for all attributes */
        int attr_cnt;
        num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
        for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++) {
          item_attrs[attr_cnt] = (btrc_media_attr_t)(attr_cnt + 1);
        }
      } else {
        num_attr = pavrc_cmd->get_attrs.attr_count;
        memcpy(item_attrs, pavrc_cmd->get_attrs.p_attr_list,
               sizeof(uint32_t) * pavrc_cmd->get_attrs.attr_count);
      }
      fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev);
      BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__,
                       num_attr);
      HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, scope,
                pavrc_cmd->get_attrs.uid, uid_counter, num_attr, item_attrs,
                &rc_addr);
      HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
                pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter,
                num_attr, item_attrs, &rc_addr);
    } break;

    case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: {
+168 −87
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 *  limitations under the License.
 *
 ******************************************************************************/
#include <assert.h>
#include <string.h>

#include "bt_common.h"
@@ -445,6 +446,111 @@ static tAVRC_STS avrc_bld_inform_battery_status_rsp (UNUSED_ATTR tAVRC_RSP *p_rs
    return AVRC_STS_NO_ERROR;
}

static void avrc_build_attribute_entries(int num_attrs,
                                         tAVRC_ATTR_ENTRY* p_attrs,
                                         int remaining_buffer_capacity,
                                         uint8_t** pp_data,
                                         uint8_t* p_attribute_count) {
    AVRC_TRACE_DEBUG("%s num_attrs: %d, remaining_buffer_capacity: %d",
                     __func__, num_attrs, remaining_buffer_capacity);
    uint8_t* p_data = *pp_data;
    /* Fill in the Attribute ID, Character Set, Length and Values */
    for (int index = 0; index < num_attrs; index++) {
        AVRC_TRACE_DEBUG("%s attr id[%d]: %d",
                         __func__, index, p_attrs[index].attr_id);
        assert(AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id));
        if (!p_attrs[index].name.p_str) {
            p_attrs[index].name.str_len = 0;
        }
        /* 8 is the size of attr_id, char set and str_len */
        remaining_buffer_capacity -= 8;
        if (remaining_buffer_capacity < 0) {
            AVRC_TRACE_WARNING(
                    "%s not enough buffer space for attr_id[%d]: %d,"
                    " skipping %d attributes",
                    __func__, index, p_attrs[index].attr_id, num_attrs - index);
            break;
        }
        if (remaining_buffer_capacity < p_attrs[index].name.str_len) {
            AVRC_TRACE_WARNING("%s not enough buffer space for attr_id[%d]: %d,"
                               " truncating attribute",
                               __func__, index, p_attrs[index].attr_id);
            p_attrs[index].name.str_len = remaining_buffer_capacity;
            remaining_buffer_capacity = 0;
        }
        remaining_buffer_capacity -= p_attrs[index].name.str_len;
        UINT32_TO_BE_STREAM(p_data, p_attrs[index].attr_id);
        UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.charset_id);
        UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.str_len);
        ARRAY_TO_BE_STREAM(p_data, p_attrs[index].name.p_str,
                           p_attrs[index].name.str_len);
        (*p_attribute_count)++;
    }
    *pp_data = p_data;
    AVRC_TRACE_DEBUG("%s filled attributes, remaining_buffer_capacity: %d",
                     __func__, num_attrs, remaining_buffer_capacity);
}

/*******************************************************************************
**
** 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_ATTRS_RSP *p_rsp,
                                              BT_HDR *p_pkt) {
    AVRC_TRACE_API("%s", __func__);
    if (!p_rsp->p_attrs) {
        AVRC_TRACE_ERROR("%s NULL p_attrs", __func__);
        return AVRC_STS_BAD_PARAM;
    }
    /* Figure out how much we have left in current buffer */
    int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE
                                    - BT_HDR_SIZE - p_pkt->offset;
    if (remaining_buffer_capacity < 5) {
      AVRC_TRACE_ERROR("%s not enough buffer for packet header",
        remaining_buffer_capacity);
      return AVRC_STS_INTERNAL_ERR;
    }
    /* Get to the beginning of PDU */
    uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset;
    /* Skip PDU ID and Reserved byte to get pointer to Parameter Length */
    uint8_t *p_data, *p_parameter_len;
    p_data = p_parameter_len = p_pdu_start + 2;
    /* Parse parameter length */
    uint16_t parameter_len;
    BE_STREAM_TO_UINT16(parameter_len, p_data);
    /* Get pointer to Attribute Count */
    uint8_t *p_attribute_count = p_data;
    /* Initialize field values when Parameter Length is 0 */
    if (parameter_len == 0) {
        *p_attribute_count = 0;
        p_data++;
    } else {
        // TODO: Why do we need this case?
        p_data = p_pdu_start + p_pkt->len;
    }
    remaining_buffer_capacity -= p_data - p_pdu_start;;
    if (remaining_buffer_capacity < 0) {
         AVRC_TRACE_ERROR("%s not enough buffer capacity for response");
         return AVRC_STS_BAD_PARAM;
    }
    /* Fill in the Attribute ID, Character Set, Length and Values */
    avrc_build_attribute_entries(p_rsp->num_attrs,
                               p_rsp->p_attrs,
                               remaining_buffer_capacity,
                               &p_data, p_attribute_count);
    parameter_len = p_data - p_attribute_count;
    UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
    p_pkt->len = (p_data - p_pdu_start);
    return AVRC_STS_NO_ERROR;
}

/*******************************************************************************
**
** Function         avrc_bld_get_play_status_rsp
@@ -1093,10 +1199,9 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_

/*******************************************************************************
**
** Function         avrc_bld_get_attrs_rsp
** Function         avrc_bld_get_item_attrs_rsp
**
** Description      This function builds the Get Item Attributes or
**                  Get Element Attributes response,
** Description      This function builds the GetItemAttributes response,
**
**                  The Get Item Attributes message goes through the
**                  Browsing channel (already specified in the |p_pkt|)
@@ -1106,93 +1211,66 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_
**                  Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
{
    uint8_t   *p_data, *p_start;
    uint8_t   *p_len;
    uint16_t  len_left;
    uint8_t   *p_num;
    uint16_t  mtu;

static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp,
                                              BT_HDR *p_pkt) {
    AVRC_TRACE_API("%s", __func__);
    /* calculate the buffer size needed and validate the parameters */
    if (!p_rsp || !p_rsp->p_attrs)
    {
        AVRC_TRACE_ERROR("NULL p_attrs");
        return AVRC_STS_BAD_PARAM;
    }

    /* check the length before adding the attr to the message */
    uint16_t len = 2;
    for (uint8_t xx = 0; xx < p_rsp->num_attrs; xx++)
    {
        if(p_rsp->p_attrs[xx].name.p_str == 0 ||
            !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id))
        {
            AVRC_TRACE_ERROR("[%d] NULL p_attrs str or bad attr_id:%d", xx,
                p_rsp->p_attrs[xx].attr_id);
    if (!p_rsp->p_attrs) {
        AVRC_TRACE_ERROR("%s NULL p_attrs", __func__);
        return AVRC_STS_BAD_PARAM;
    }
        len += (p_rsp->p_attrs[xx].name.str_len + 8);
    }
    len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE;
    p_data = (uint8_t *)(p_pkt + 1);
    /* Figure out how much we have left in current buffer */
    int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE
                                    - p_pkt->offset;
    /* Get to the beginning of data section in buffer */
    uint8_t *p_data = (uint8_t *)(p_pkt + 1);
    /* Get the MTU size that is filled in earlier */
    uint16_t mtu;
    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_DEBUG("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/1st timer/attr cnt & len */
    {
    if (remaining_buffer_capacity > mtu) {
        remaining_buffer_capacity = mtu;
    }
    AVRC_TRACE_DEBUG("%s remaining_buffer_capacity:%d, mtu:%d",
                     remaining_buffer_capacity, mtu);
    if (remaining_buffer_capacity < 5) {
      AVRC_TRACE_ERROR("%s not enough buffer for packet header",
                       remaining_buffer_capacity);
      return AVRC_STS_INTERNAL_ERR;
    }
    if (len > len_left)
    {
        AVRC_TRACE_ERROR("The 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_t *)(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 (uint8_t xx = 0; (xx < p_rsp->num_attrs) && (len_left > 9); xx++)
    {
        (*p_num)++;
        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);
        len_left -= 8;
        if (p_rsp->p_attrs[xx].name.str_len > len_left)
            p_rsp->p_attrs[xx].name.str_len = len_left;
        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str,
            p_rsp->p_attrs[xx].name.str_len);
        len_left -= p_rsp->p_attrs[xx].name.str_len;
        len += (p_rsp->p_attrs[xx].name.str_len + 8);
    /* Get to the beginning of PDU */
    uint8_t *p_pdu_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset;
    /* Skip PDU ID to get pointer to Parameter length */
    uint8_t *p_parameter_len;
    p_data = p_parameter_len = p_pdu_start + 1;
    /* Parse existing parameter length */
    uint16_t parameter_len;
    BE_STREAM_TO_UINT16(parameter_len, p_data);
    /* Skip one byte to Number of Attributes */
    uint8_t *p_status = p_data++;
    uint8_t *p_attribute_count = p_data++;
    if (parameter_len == 0) {
        /* First time, initialize the status byte */
        *p_status = p_rsp->status;
        if (p_rsp->status != AVRC_STS_NO_ERROR) {
            // TODO(siyuanh): This is a hack
            parameter_len = 1;
            UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
            p_pkt->len = p_status - p_pdu_start;
            return AVRC_STS_NO_ERROR;
        }

    UINT16_TO_BE_STREAM(p_len, len);
    p_pkt->len = (p_data - p_start);
        *p_attribute_count = 0;
    } else {
        // TODO(siyuanh): Why do wee need this case?
        p_data = p_pdu_start + p_pkt->len;
    }
    remaining_buffer_capacity -= p_data - p_pdu_start;
    /* Fill in the Attribute ID, Character Set, Length and Values */
    avrc_build_attribute_entries(p_rsp->num_attrs,
                               p_rsp->p_attrs,
                               remaining_buffer_capacity,
                               &p_data, p_attribute_count);
    parameter_len = p_data - p_status;
    UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
    p_pkt->len = p_data - p_pdu_start;
    return AVRC_STS_NO_ERROR;
}

@@ -1469,8 +1547,7 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p
        break;

    case AVRC_PDU_GET_ELEMENT_ATTR:
    case AVRC_PDU_GET_ITEM_ATTRIBUTES:
        status = avrc_bld_get_attrs_rsp(&p_rsp->get_attrs, p_pkt);
        status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt);
        break;

    case AVRC_PDU_GET_PLAY_STATUS:
@@ -1517,11 +1594,15 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p
        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;

    case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
        status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt);
        break;

    case AVRC_PDU_SEARCH:                      /* 0x80 */
    case AVRC_PDU_SEARCH:
       status = avrc_bld_search_rsp(&p_rsp->search, p_pkt);
       break;
    }