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  ******************************************************************************/
avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result)45 static 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 
avrc_parse_notification_rsp(uint8_t * p_stream,tAVRC_REG_NOTIF_RSP * p_rsp)107 void 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 
avrc_pars_browse_rsp(tAVRC_MSG_BROWSE * p_msg,tAVRC_RESPONSE * p_rsp)152 static 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  ******************************************************************************/
avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)401 static 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  ******************************************************************************/
AVRC_Ctrl_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)624 tAVRC_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  ******************************************************************************/
AVRC_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,UNUSED_ATTR uint8_t * p_buf,UNUSED_ATTR uint16_t buf_len)660 tAVRC_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