1/******************************************************************************
2 *
3 *  Copyright (C) 2006-2013 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18#include <string.h>
19
20#include "avrc_api.h"
21#include "avrc_defs.h"
22#include "avrc_int.h"
23#include "bt_common.h"
24#include "bt_utils.h"
25#include "osi/include/osi.h"
26
27/*****************************************************************************
28 *  Global data
29 ****************************************************************************/
30
31#if (AVRC_METADATA_INCLUDED == TRUE)
32
33/*******************************************************************************
34 *
35 * Function         avrc_pars_vendor_rsp
36 *
37 * Description      This function parses the vendor specific commands defined by
38 *                  Bluetooth SIG
39 *
40 * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
41 *                  successfully.
42 *                  Otherwise, the error code defined by AVRCP 1.4
43 *
44 ******************************************************************************/
45static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
46                                      tAVRC_RESPONSE* p_result) {
47  tAVRC_STS status = AVRC_STS_NO_ERROR;
48  uint8_t* p;
49  uint16_t len;
50#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
51  uint8_t eventid = 0;
52#endif
53
54  /* Check the vendor data */
55  if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
56  if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
57
58  p = p_msg->p_vendor_data;
59  BE_STREAM_TO_UINT8(p_result->pdu, p);
60  p++; /* skip the reserved/packe_type byte */
61  BE_STREAM_TO_UINT16(len, p);
62  AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x", __func__,
63                   p_msg->hdr.ctype, p_result->pdu, len, len);
64  if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
65    p_result->rsp.status = *p;
66    return p_result->rsp.status;
67  }
68
69  switch (p_result->pdu) {
70/* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
71/* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
72
73#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
74    case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
75      if (len != 1)
76        status = AVRC_STS_INTERNAL_ERR;
77      else {
78        BE_STREAM_TO_UINT8(p_result->volume.volume, p);
79      }
80      break;
81#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
82
83    case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
84#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
85      BE_STREAM_TO_UINT8(eventid, p);
86      if (AVRC_EVT_VOLUME_CHANGE == eventid &&
87          (AVRC_RSP_CHANGED == p_msg->hdr.ctype ||
88           AVRC_RSP_INTERIM == p_msg->hdr.ctype ||
89           AVRC_RSP_REJ == p_msg->hdr.ctype ||
90           AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) {
91        p_result->reg_notif.status = p_msg->hdr.ctype;
92        p_result->reg_notif.event_id = eventid;
93        BE_STREAM_TO_UINT8(p_result->reg_notif.param.volume, p);
94      }
95      AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x",
96                       __func__, eventid, p_result->reg_notif.param.volume);
97#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
98      break;
99    default:
100      status = AVRC_STS_BAD_CMD;
101      break;
102  }
103
104  return status;
105}
106
107void avrc_parse_notification_rsp(uint8_t* p_stream,
108                                 tAVRC_REG_NOTIF_RSP* p_rsp) {
109  BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream);
110  switch (p_rsp->event_id) {
111    case AVRC_EVT_PLAY_STATUS_CHANGE:
112      BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream);
113      break;
114
115    case AVRC_EVT_TRACK_CHANGE:
116      BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8);
117      break;
118
119    case AVRC_EVT_APP_SETTING_CHANGE:
120      BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream);
121      for (int index = 0; index < p_rsp->param.player_setting.num_attr;
122           index++) {
123        BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index],
124                           p_stream);
125        BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index],
126                           p_stream);
127      }
128      break;
129
130    case AVRC_EVT_NOW_PLAYING_CHANGE:
131      break;
132
133    case AVRC_EVT_AVAL_PLAYERS_CHANGE:
134      break;
135
136    case AVRC_EVT_ADDR_PLAYER_CHANGE:
137      break;
138
139    case AVRC_EVT_UIDS_CHANGE:
140      break;
141
142    case AVRC_EVT_TRACK_REACHED_END:
143    case AVRC_EVT_TRACK_REACHED_START:
144    case AVRC_EVT_PLAY_POS_CHANGED:
145    case AVRC_EVT_BATTERY_STATUS_CHANGE:
146    case AVRC_EVT_SYSTEM_STATUS_CHANGE:
147    default:
148      break;
149  }
150}
151
152static tAVRC_STS avrc_pars_browse_rsp(tAVRC_MSG_BROWSE* p_msg,
153                                      tAVRC_RESPONSE* p_rsp) {
154  tAVRC_STS status = AVRC_STS_NO_ERROR;
155  uint8_t pdu;
156
157  if (p_msg->browse_len == 0) {
158    AVRC_TRACE_ERROR("%s length ", p_msg->browse_len);
159    return AVRC_STS_BAD_PARAM;
160  }
161
162  uint8_t* p = p_msg->p_browse_data;
163
164  /* read the pdu */
165  BE_STREAM_TO_UINT8(pdu, p);
166  uint16_t pkt_len;
167  /* read the entire packet len */
168  BE_STREAM_TO_UINT16(pkt_len, p);
169
170  AVRC_TRACE_DEBUG("%s pdu %d", __func__, pdu);
171
172  /* used to track how much we have read, if we cannot read anymore but the
173   * packet says so then we have a malformed packet. Also vice versa. */
174  uint16_t pkt_len_read = 0;
175
176  switch (pdu) {
177    case AVRC_PDU_GET_FOLDER_ITEMS: {
178      tAVRC_GET_ITEMS_RSP* get_item_rsp = &(p_rsp->get_items);
179      /* Copy back the PDU */
180      get_item_rsp->pdu = pdu;
181      /* read the status */
182      BE_STREAM_TO_UINT8(get_item_rsp->status, p);
183      /* read the UID counter */
184      BE_STREAM_TO_UINT16(get_item_rsp->uid_counter, p);
185      /* read the number of items */
186      BE_STREAM_TO_UINT16(get_item_rsp->item_count, p);
187      pkt_len_read += 5;
188
189      AVRC_TRACE_DEBUG(
190          "%s pdu %d status %d pkt_len %d uid counter %d item count %d",
191          __func__, get_item_rsp->pdu, get_item_rsp->status, pkt_len,
192          get_item_rsp->uid_counter, get_item_rsp->item_count);
193
194      if (get_item_rsp->status != AVRC_STS_NO_ERROR) {
195        AVRC_TRACE_WARNING("%s returning error %d", __func__,
196                           get_item_rsp->status);
197        return get_item_rsp->status;
198      }
199
200      /* get each of the items */
201      get_item_rsp->p_item_list = (tAVRC_ITEM*)osi_malloc(
202          get_item_rsp->item_count * (sizeof(tAVRC_ITEM)));
203      tAVRC_ITEM* curr_item = get_item_rsp->p_item_list;
204      for (int i = 0; i < get_item_rsp->item_count; i++) {
205        BE_STREAM_TO_UINT8(curr_item->item_type, p);
206        pkt_len_read += 1;
207        AVRC_TRACE_DEBUG("%s item type %d", __func__, curr_item->item_type);
208        switch (curr_item->item_type) {
209          case AVRC_ITEM_PLAYER: {
210            /* Handle player */
211            tAVRC_ITEM_PLAYER* player = &(curr_item->u.player);
212            uint8_t player_len;
213            BE_STREAM_TO_UINT16(player_len, p);
214            BE_STREAM_TO_UINT16(player->player_id, p);
215            BE_STREAM_TO_UINT8(player->major_type, p);
216            BE_STREAM_TO_UINT32(player->sub_type, p);
217            BE_STREAM_TO_UINT8(player->play_status, p);
218            BE_STREAM_TO_ARRAY(p, player->features, AVRC_FEATURE_MASK_SIZE);
219            pkt_len_read += (10 + AVRC_FEATURE_MASK_SIZE);
220
221            /* read str */
222            BE_STREAM_TO_UINT16(player->name.charset_id, p);
223            BE_STREAM_TO_UINT16(player->name.str_len, p);
224            player->name.p_str = (uint8_t*)osi_malloc(
225                (player->name.str_len + 1) * sizeof(uint8_t));
226            BE_STREAM_TO_ARRAY(p, player->name.p_str, player->name.str_len);
227            pkt_len_read += (4 + player->name.str_len);
228            AVRC_TRACE_DEBUG(
229                "%s type %d id %d mtype %d stype %d ps %d cs %d name len %d",
230                __func__, curr_item->item_type, player->player_id,
231                player->major_type, player->sub_type, player->play_status,
232                player->name.charset_id, player->name.str_len);
233          } break;
234
235          case AVRC_ITEM_FOLDER: {
236            tAVRC_ITEM_FOLDER* folder = &(curr_item->u.folder);
237            uint16_t folder_len;
238            BE_STREAM_TO_UINT16(folder_len, p);
239
240            BE_STREAM_TO_ARRAY(p, folder->uid, AVRC_UID_SIZE);
241            BE_STREAM_TO_UINT8(folder->type, p);
242            BE_STREAM_TO_UINT8(folder->playable, p);
243            pkt_len_read += (4 + AVRC_UID_SIZE);
244
245            /* read str, encoding to be handled by upper layers */
246            BE_STREAM_TO_UINT16(folder->name.charset_id, p);
247            BE_STREAM_TO_UINT16(folder->name.str_len, p);
248            folder->name.p_str = (uint8_t*)osi_malloc(
249                (folder->name.str_len + 1) * sizeof(uint8_t));
250            BE_STREAM_TO_ARRAY(p, folder->name.p_str, folder->name.str_len);
251            pkt_len_read += (4 + folder->name.str_len);
252            AVRC_TRACE_DEBUG("%s type %d playable %d cs %d name len %d",
253                             __func__, folder->type, folder->playable,
254                             folder->name.charset_id, folder->name.str_len);
255          } break;
256
257          case AVRC_ITEM_MEDIA: {
258            tAVRC_ITEM_MEDIA* media = &(curr_item->u.media);
259            uint8_t media_len;
260            BE_STREAM_TO_UINT16(media_len, p);
261            BE_STREAM_TO_ARRAY(p, media->uid, AVRC_UID_SIZE);
262            BE_STREAM_TO_UINT8(media->type, p);
263            pkt_len_read += (3 + AVRC_UID_SIZE);
264
265            /* read str, encoding to be handled by upper layers */
266            BE_STREAM_TO_UINT16(media->name.charset_id, p);
267            BE_STREAM_TO_UINT16(media->name.str_len, p);
268            media->name.p_str =
269                (uint8_t*)osi_malloc((media->name.str_len) * sizeof(uint8_t));
270            BE_STREAM_TO_ARRAY(p, media->name.p_str, media->name.str_len);
271
272            BE_STREAM_TO_UINT8(media->attr_count, p);
273            AVRC_TRACE_DEBUG("%s media type %d charset id %d len %d attr ct %d",
274                             __func__, media->type, media->name.charset_id,
275                             media->name.str_len, media->attr_count);
276            pkt_len_read += (5 + media->name.str_len);
277
278            media->p_attr_list = (tAVRC_ATTR_ENTRY*)osi_malloc(
279                media->attr_count * sizeof(tAVRC_ATTR_ENTRY));
280            for (int jk = 0; jk < media->attr_count; jk++) {
281              tAVRC_ATTR_ENTRY* attr_entry = &(media->p_attr_list[jk]);
282              BE_STREAM_TO_UINT32(attr_entry->attr_id, p);
283
284              /* Parse the name now */
285              BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
286              BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
287              attr_entry->name.p_str = (uint8_t*)osi_malloc(
288                  attr_entry->name.str_len * sizeof(uint8_t));
289              BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str,
290                                 attr_entry->name.str_len);
291              pkt_len_read += (8 + attr_entry->name.str_len);
292              AVRC_TRACE_DEBUG("%s media attr id %d cs %d name len %d",
293                               __func__, attr_entry->attr_id,
294                               attr_entry->name.charset_id,
295                               attr_entry->name.str_len);
296            }
297          } break;
298
299          default:
300            AVRC_TRACE_ERROR("%s item type not handled %d", __func__,
301                             curr_item->item_type);
302            return AVRC_STS_INTERNAL_ERR;
303        }
304
305        /* we check if we have overrun */
306        if (pkt_len_read > pkt_len) {
307          AVRC_TRACE_ERROR("%s overflow in read pkt_len %d pkt_len_read %d",
308                           __func__, pkt_len, pkt_len_read);
309          return AVRC_STS_BAD_CMD;
310        }
311        AVRC_TRACE_DEBUG("%s pkt_len %d pkt_len_read %d", __func__, pkt_len,
312                         pkt_len_read);
313
314        /* advance to populate the next item */
315        curr_item++;
316      }
317      break;
318    }
319
320    case AVRC_PDU_CHANGE_PATH: {
321      tAVRC_CHG_PATH_RSP* change_path_rsp = &(p_rsp->chg_path);
322      /* Copyback the PDU */
323      change_path_rsp->pdu = pdu;
324      /* Read the status */
325      BE_STREAM_TO_UINT8(change_path_rsp->status, p);
326      /* Read the number of items in folder */
327      BE_STREAM_TO_UINT32(change_path_rsp->num_items, p);
328      pkt_len_read += 5;
329
330      AVRC_TRACE_DEBUG("%s pdu %d status %d item count %d", __func__,
331                       change_path_rsp->pdu, change_path_rsp->status,
332                       change_path_rsp->num_items);
333      break;
334    }
335
336    case AVRC_PDU_SET_BROWSED_PLAYER: {
337      tAVRC_SET_BR_PLAYER_RSP* set_br_pl_rsp = &(p_rsp->br_player);
338      /* Copyback the PDU */
339      set_br_pl_rsp->pdu = pdu;
340
341      /* Read the status */
342      BE_STREAM_TO_UINT8(set_br_pl_rsp->status, p);
343
344      if (set_br_pl_rsp->status != AVRC_STS_NO_ERROR) {
345        AVRC_TRACE_ERROR(
346            "%s Stopping further parsing because player not browsable sts %d",
347            __func__, set_br_pl_rsp->status);
348        break;
349      }
350      BE_STREAM_TO_UINT16(set_br_pl_rsp->uid_counter, p);
351      BE_STREAM_TO_UINT32(set_br_pl_rsp->num_items, p);
352      BE_STREAM_TO_UINT16(set_br_pl_rsp->charset_id, p);
353      BE_STREAM_TO_UINT8(set_br_pl_rsp->folder_depth, p);
354      AVRC_TRACE_DEBUG(
355          "%s AVRC_PDU_SET_BROWSED_PLAYER status %d items %d cs %d depth %d",
356          __func__, set_br_pl_rsp->status, set_br_pl_rsp->num_items,
357          set_br_pl_rsp->charset_id, set_br_pl_rsp->folder_depth);
358      pkt_len_read += 10;
359
360      set_br_pl_rsp->p_folders = (tAVRC_NAME*)osi_malloc(
361          set_br_pl_rsp->num_items * sizeof(tAVRC_NAME));
362
363      /* Read each of the folder in the depth */
364      for (uint32_t i = 0; i < set_br_pl_rsp->folder_depth; i++) {
365        tAVRC_NAME* folder_name = &(set_br_pl_rsp->p_folders[i]);
366        BE_STREAM_TO_UINT16(folder_name->str_len, p);
367        AVRC_TRACE_DEBUG("%s AVRC_PDU_SET_BROWSED_PLAYER item: %d len: %d",
368                         __func__, i, folder_name->str_len);
369        folder_name->p_str =
370            (uint8_t*)osi_malloc((folder_name->str_len + 1) * sizeof(uint8_t));
371        BE_STREAM_TO_ARRAY(p, folder_name->p_str, folder_name->str_len);
372        pkt_len_read += (2 + folder_name->str_len);
373      }
374      break;
375    }
376
377    default:
378      AVRC_TRACE_ERROR("%s pdu %d not handled", __func__, pdu);
379  }
380
381  if (pkt_len != pkt_len_read) {
382    AVRC_TRACE_ERROR("%s finished pkt_len %d pkt_len_read %d", __func__,
383                     pkt_len, pkt_len_read);
384    return AVRC_STS_BAD_CMD;
385  }
386  return status;
387}
388
389/*******************************************************************************
390 *
391 * Function         avrc_ctrl_pars_vendor_rsp
392 *
393 * Description      This function parses the vendor specific commands defined by
394 *                  Bluetooth SIG
395 *
396 * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
397 *                  successfully.
398 *                  Otherwise, the error code defined by AVRCP 1.4
399 *
400 ******************************************************************************/
401static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
402                                           tAVRC_RESPONSE* p_result,
403                                           uint8_t* p_buf, uint16_t* buf_len) {
404  uint8_t* p = p_msg->p_vendor_data;
405  BE_STREAM_TO_UINT8(p_result->pdu, p);
406  p++; /* skip the reserved/packe_type byte */
407
408  uint16_t len;
409  BE_STREAM_TO_UINT16(len, p);
410  AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d", __func__, p_msg->hdr.ctype,
411                   p_result->pdu, len);
412  /* Todo: Issue in handling reject, check */
413  if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
414    p_result->rsp.status = *p;
415    return p_result->rsp.status;
416  }
417
418  /* TODO: Break the big switch into functions. */
419  switch (p_result->pdu) {
420    /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
421    /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
422
423    case AVRC_PDU_REGISTER_NOTIFICATION:
424      avrc_parse_notification_rsp(p, &p_result->reg_notif);
425      break;
426
427    case AVRC_PDU_GET_CAPABILITIES:
428      if (len == 0) {
429        p_result->get_caps.count = 0;
430        p_result->get_caps.capability_id = 0;
431        break;
432      }
433      BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p);
434      BE_STREAM_TO_UINT8(p_result->get_caps.count, p);
435      AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ", __func__,
436                       p_result->get_caps.capability_id,
437                       p_result->get_caps.count);
438      if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
439        for (int xx = 0; ((xx < p_result->get_caps.count) &&
440                          (xx < AVRC_CAP_MAX_NUM_COMP_ID));
441             xx++) {
442          BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p);
443        }
444      } else if (p_result->get_caps.capability_id ==
445                 AVRC_CAP_EVENTS_SUPPORTED) {
446        for (int xx = 0; ((xx < p_result->get_caps.count) &&
447                          (xx < AVRC_CAP_MAX_NUM_EVT_ID));
448             xx++) {
449          BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p);
450        }
451      }
452      break;
453
454    case AVRC_PDU_LIST_PLAYER_APP_ATTR:
455      if (len == 0) {
456        p_result->list_app_attr.num_attr = 0;
457        break;
458      }
459      BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p);
460      AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
461                       p_result->list_app_attr.num_attr);
462      for (int xx = 0; xx < p_result->list_app_attr.num_attr; xx++) {
463        BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p);
464      }
465      break;
466
467    case AVRC_PDU_LIST_PLAYER_APP_VALUES:
468      if (len == 0) {
469        p_result->list_app_values.num_val = 0;
470        break;
471      }
472      BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p);
473      AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
474                       p_result->list_app_values.num_val);
475      for (int xx = 0; xx < p_result->list_app_values.num_val; xx++) {
476        BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p);
477      }
478      break;
479
480    case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: {
481      if (len == 0) {
482        p_result->get_cur_app_val.num_val = 0;
483        break;
484      }
485      BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p);
486      tAVRC_APP_SETTING* app_sett = (tAVRC_APP_SETTING*)osi_malloc(
487          p_result->get_cur_app_val.num_val * sizeof(tAVRC_APP_SETTING));
488      AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
489                       p_result->get_cur_app_val.num_val);
490      for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++) {
491        BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p);
492        BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p);
493      }
494      p_result->get_cur_app_val.p_vals = app_sett;
495    } break;
496
497    case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: {
498      tAVRC_APP_SETTING_TEXT* p_setting_text;
499      uint8_t num_attrs;
500
501      if (len == 0) {
502        p_result->get_app_attr_txt.num_attr = 0;
503        break;
504      }
505      BE_STREAM_TO_UINT8(num_attrs, p);
506      AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
507                       p_result->get_app_attr_txt.num_attr);
508      p_result->get_app_attr_txt.num_attr = num_attrs;
509      p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(
510          num_attrs * sizeof(tAVRC_APP_SETTING_TEXT));
511      for (int xx = 0; xx < num_attrs; xx++) {
512        BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p);
513        BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id,
514                            p);
515        BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p);
516        if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0) {
517          uint8_t* p_str = (uint8_t*)osi_malloc(
518              p_result->get_app_attr_txt.p_attrs[xx].str_len);
519          BE_STREAM_TO_ARRAY(p, p_str,
520                             p_result->get_app_attr_txt.p_attrs[xx].str_len);
521          p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str;
522        } else {
523          p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL;
524        }
525      }
526    } break;
527
528    case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
529      tAVRC_APP_SETTING_TEXT* p_setting_text;
530      uint8_t num_vals;
531
532      if (len == 0) {
533        p_result->get_app_val_txt.num_attr = 0;
534        break;
535      }
536      BE_STREAM_TO_UINT8(num_vals, p);
537      p_result->get_app_val_txt.num_attr = num_vals;
538      AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
539                       p_result->get_app_val_txt.num_attr);
540
541      p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(
542          num_vals * sizeof(tAVRC_APP_SETTING_TEXT));
543      for (int i = 0; i < num_vals; i++) {
544        BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p);
545        BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p);
546        BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p);
547        if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) {
548          uint8_t* p_str = (uint8_t*)osi_malloc(
549              p_result->get_app_val_txt.p_attrs[i].str_len);
550          BE_STREAM_TO_ARRAY(p, p_str,
551                             p_result->get_app_val_txt.p_attrs[i].str_len);
552          p_result->get_app_val_txt.p_attrs[i].p_str = p_str;
553        } else {
554          p_result->get_app_val_txt.p_attrs[i].p_str = NULL;
555        }
556      }
557    } break;
558
559    case AVRC_PDU_SET_PLAYER_APP_VALUE:
560      /* nothing comes as part of this rsp */
561      break;
562
563    case AVRC_PDU_GET_ELEMENT_ATTR: {
564      uint8_t num_attrs;
565
566      if (len <= 0) {
567        p_result->get_attrs.num_attrs = 0;
568        break;
569      }
570      BE_STREAM_TO_UINT8(num_attrs, p);
571      p_result->get_attrs.num_attrs = num_attrs;
572      if (num_attrs) {
573        tAVRC_ATTR_ENTRY* p_attrs =
574            (tAVRC_ATTR_ENTRY*)osi_malloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY));
575        for (int i = 0; i < num_attrs; i++) {
576          BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p);
577          BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p);
578          BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
579          if (p_attrs[i].name.str_len > 0) {
580            p_attrs[i].name.p_str =
581                (uint8_t*)osi_malloc(p_attrs[i].name.str_len);
582            BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str,
583                               p_attrs[i].name.str_len);
584          }
585        }
586        p_result->get_attrs.p_attrs = p_attrs;
587      }
588    } break;
589
590    case AVRC_PDU_GET_PLAY_STATUS:
591      if (len == 0) {
592        break;
593      }
594      BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
595      BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
596      BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
597      break;
598
599    case AVRC_PDU_SET_ADDRESSED_PLAYER:
600      if (len != 1) {
601        AVRC_TRACE_ERROR("%s pdu: %d len %d", __func__, p_result->pdu, len);
602        return AVRC_STS_BAD_CMD;
603      }
604      BE_STREAM_TO_UINT8(p_result->rsp.status, p);
605      break;
606
607    default:
608      return AVRC_STS_BAD_CMD;
609  }
610  return AVRC_STS_NO_ERROR;
611}
612
613/*******************************************************************************
614 *
615 * Function         AVRC_Ctrl_ParsResponse
616 *
617 * Description      This function is a parse response for AVRCP Controller.
618 *
619 * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
620 *                  successfully.
621 *                  Otherwise, the error code defined by AVRCP 1.4
622 *
623 ******************************************************************************/
624tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
625                                 uint8_t* p_buf, uint16_t* buf_len) {
626  tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
627  if (p_msg && p_result) {
628    switch (p_msg->hdr.opcode) {
629      case AVRC_OP_VENDOR: /*  0x00    Vendor-dependent commands */
630        status =
631            avrc_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf, buf_len);
632        break;
633
634      case AVRC_OP_BROWSE: /* 0xff Browse commands */
635        status = avrc_pars_browse_rsp(&p_msg->browse, p_result);
636        break;
637
638      default:
639        AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
640        break;
641    }
642    p_result->rsp.opcode = p_msg->hdr.opcode;
643    p_result->rsp.status = status;
644  }
645  return status;
646}
647
648/*******************************************************************************
649 *
650 * Function         AVRC_ParsResponse
651 *
652 * Description      This function is a superset of AVRC_ParsMetadata to parse
653 *                  the response.
654 *
655 * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
656 *                  successfully.
657 *                  Otherwise, the error code defined by AVRCP 1.4
658 *
659 ******************************************************************************/
660tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
661                            UNUSED_ATTR uint8_t* p_buf,
662                            UNUSED_ATTR uint16_t buf_len) {
663  tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
664  uint16_t id;
665
666  if (p_msg && p_result) {
667    switch (p_msg->hdr.opcode) {
668      case AVRC_OP_VENDOR: /*  0x00    Vendor-dependent commands */
669        status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
670        break;
671
672      case AVRC_OP_PASS_THRU: /*  0x7C    panel subunit opcode */
673        status = avrc_pars_pass_thru(&p_msg->pass, &id);
674        if (status == AVRC_STS_NO_ERROR) {
675          p_result->pdu = (uint8_t)id;
676        }
677        break;
678
679      default:
680        AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
681        break;
682    }
683    p_result->rsp.opcode = p_msg->hdr.opcode;
684    p_result->rsp.status = status;
685  }
686  return status;
687}
688#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
689