1 /******************************************************************************
2  *
3  *  Copyright 2003-2016 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 
25 #include "osi/include/log.h"
26 
27 /*****************************************************************************
28  *  Global data
29  ****************************************************************************/
30 
31 /*******************************************************************************
32  *
33  * Function         avrc_ctrl_pars_vendor_cmd
34  *
35  * Description      This function parses the vendor specific commands defined by
36  *                  Bluetooth SIG for AVRCP Conroller.
37  *
38  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
39  *                  successfully.
40  *                  Otherwise, the error code defined by AVRCP 1.4
41  *
42  ******************************************************************************/
avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result)43 static tAVRC_STS avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
44                                            tAVRC_COMMAND* p_result) {
45   tAVRC_STS status = AVRC_STS_NO_ERROR;
46 
47   uint8_t* p = p_msg->p_vendor_data;
48   p_result->pdu = *p++;
49   AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
50   if (!AVRC_IsValidAvcType(p_result->pdu, p_msg->hdr.ctype)) {
51     AVRC_TRACE_DEBUG("%s detects wrong AV/C type!", __func__);
52     status = AVRC_STS_BAD_CMD;
53   }
54 
55   p++; /* skip the reserved byte */
56   uint16_t len;
57   BE_STREAM_TO_UINT16(len, p);
58   if ((len + 4) != (p_msg->vendor_len)) {
59     status = AVRC_STS_INTERNAL_ERR;
60   }
61 
62   if (status != AVRC_STS_NO_ERROR) return status;
63 
64   switch (p_result->pdu) {
65     case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
66       if (len != 1)
67         status = AVRC_STS_INTERNAL_ERR;
68       else {
69         BE_STREAM_TO_UINT8(p_result->volume.volume, p);
70         p_result->volume.volume = AVRC_MAX_VOLUME & p_result->volume.volume;
71       }
72       break;
73     }
74     case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
75       if (len < 5) return AVRC_STS_INTERNAL_ERR;
76 
77       BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
78       BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
79 
80       if (p_result->reg_notif.event_id == 0 ||
81           p_result->reg_notif.event_id > AVRC_NUM_NOTIF_EVENTS) {
82         android_errorWriteLog(0x534e4554, "181860042");
83         status = AVRC_STS_BAD_PARAM;
84       }
85       break;
86     default:
87       status = AVRC_STS_BAD_CMD;
88       break;
89   }
90   return status;
91 }
92 
93 /*******************************************************************************
94  *
95  * Function         avrc_pars_vendor_cmd
96  *
97  * Description      This function parses the vendor specific commands defined by
98  *                  Bluetooth SIG
99  *
100  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
101  *                  successfully.
102  *                  Otherwise, the error code defined by AVRCP 1.4
103  *
104  ******************************************************************************/
avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)105 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
106                                       tAVRC_COMMAND* p_result, uint8_t* p_buf,
107                                       uint16_t buf_len) {
108   tAVRC_STS status = AVRC_STS_NO_ERROR;
109   uint8_t* p;
110   uint16_t len;
111   uint8_t xx, yy;
112   uint8_t* p_u8;
113   uint16_t* p_u16;
114   uint32_t u32, u32_2, *p_u32;
115   tAVRC_APP_SETTING* p_app_set;
116   uint16_t size_needed;
117 
118   /* Check the vendor data */
119   if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
120   if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
121 
122   p = p_msg->p_vendor_data;
123   p_result->pdu = *p++;
124   AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
125   if (!AVRC_IsValidAvcType(p_result->pdu, p_msg->hdr.ctype)) {
126     AVRC_TRACE_DEBUG("%s detects wrong AV/C type(0x%x)!", __func__,
127                      p_msg->hdr.ctype);
128     status = AVRC_STS_BAD_CMD;
129   }
130 
131   p++; /* skip the reserved byte */
132   BE_STREAM_TO_UINT16(len, p);
133   if ((len + 4) != (p_msg->vendor_len)) {
134     AVRC_TRACE_ERROR("%s incorrect length :%d, %d", __func__, len,
135                      p_msg->vendor_len);
136     status = AVRC_STS_INTERNAL_ERR;
137   }
138 
139   if (status != AVRC_STS_NO_ERROR) return status;
140 
141   switch (p_result->pdu) {
142     case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */
143       p_result->get_caps.capability_id = *p++;
144       if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
145         status = AVRC_STS_BAD_PARAM;
146       else if (len != 1)
147         return AVRC_STS_INTERNAL_ERR;
148       break;
149 
150     case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
151       /* no additional parameters */
152       if (len != 0) return AVRC_STS_INTERNAL_ERR;
153       break;
154 
155     case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
156       if (len == 0) return AVRC_STS_INTERNAL_ERR;
157       p_result->list_app_values.attr_id = *p++;
158       if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
159         status = AVRC_STS_BAD_PARAM;
160       else if (len != 1)
161         status = AVRC_STS_INTERNAL_ERR;
162       break;
163 
164     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
165     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
166       if (len == 0) return AVRC_STS_INTERNAL_ERR;
167       BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_attr, p);
168       if (len != (p_result->get_cur_app_val.num_attr + 1)) {
169         status = AVRC_STS_INTERNAL_ERR;
170         break;
171       }
172 
173       if (p_result->get_cur_app_val.num_attr > AVRC_MAX_APP_ATTR_SIZE) {
174         android_errorWriteLog(0x534e4554, "63146237");
175         p_result->get_cur_app_val.num_attr = AVRC_MAX_APP_ATTR_SIZE;
176       }
177 
178       p_u8 = p_result->get_cur_app_val.attrs;
179       for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
180         /* only report the valid player app attributes */
181         if (AVRC_IsValidPlayerAttr(*p)) p_u8[yy++] = *p;
182         p++;
183       }
184       p_result->get_cur_app_val.num_attr = yy;
185       if (yy == 0) {
186         status = AVRC_STS_BAD_PARAM;
187       }
188       break;
189 
190     case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
191       if (len == 0) return AVRC_STS_INTERNAL_ERR;
192       BE_STREAM_TO_UINT8(p_result->set_app_val.num_val, p);
193       size_needed = sizeof(tAVRC_APP_SETTING);
194       if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
195         p_result->set_app_val.p_vals = (tAVRC_APP_SETTING*)p_buf;
196         p_app_set = p_result->set_app_val.p_vals;
197         for (xx = 0;
198              ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed));
199              xx++) {
200           p_app_set[xx].attr_id = *p++;
201           p_app_set[xx].attr_val = *p++;
202           if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id,
203                                                  p_app_set[xx].attr_val))
204             status = AVRC_STS_BAD_PARAM;
205         }
206         if (xx != p_result->set_app_val.num_val) {
207           AVRC_TRACE_ERROR(
208               "%s AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig "
209               "num_val:%d",
210               __func__, xx, p_result->set_app_val.num_val);
211           p_result->set_app_val.num_val = xx;
212         }
213       } else {
214         AVRC_TRACE_ERROR(
215             "%s AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len",
216             __func__);
217         status = AVRC_STS_INTERNAL_ERR;
218       }
219       break;
220 
221     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
222       if (len < 3)
223         return AVRC_STS_INTERNAL_ERR;
224       else {
225         BE_STREAM_TO_UINT8(p_result->get_app_val_txt.attr_id, p);
226         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
227           status = AVRC_STS_BAD_PARAM;
228         else {
229           BE_STREAM_TO_UINT8(p_result->get_app_val_txt.num_val, p);
230           if ((len - 2 /* attr_id & num_val */) !=
231               p_result->get_app_val_txt.num_val)
232             status = AVRC_STS_INTERNAL_ERR;
233           else {
234             if (p_result->get_app_val_txt.num_val > AVRC_MAX_APP_ATTR_SIZE) {
235               android_errorWriteLog(0x534e4554, "63146237");
236               p_result->get_app_val_txt.num_val = AVRC_MAX_APP_ATTR_SIZE;
237             }
238 
239             p_u8 = p_result->get_app_val_txt.vals;
240             for (xx = 0; xx < p_result->get_app_val_txt.num_val; xx++) {
241               p_u8[xx] = *p++;
242               if (!avrc_is_valid_player_attrib_value(
243                       p_result->get_app_val_txt.attr_id, p_u8[xx])) {
244                 status = AVRC_STS_BAD_PARAM;
245                 break;
246               }
247             }
248           }
249         }
250       }
251       break;
252 
253     case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
254       if (len < 3)
255         return AVRC_STS_INTERNAL_ERR;
256       else {
257         BE_STREAM_TO_UINT8(p_result->inform_charset.num_id, p);
258         if ((len - 1 /* num_id */) != p_result->inform_charset.num_id * 2)
259           status = AVRC_STS_INTERNAL_ERR;
260         else {
261           p_u16 = p_result->inform_charset.charsets;
262           if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE)
263             p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
264           for (xx = 0; xx < p_result->inform_charset.num_id; xx++) {
265             BE_STREAM_TO_UINT16(p_u16[xx], p);
266           }
267         }
268       }
269       break;
270 
271     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
272       if (len != 1)
273         return AVRC_STS_INTERNAL_ERR;
274       else {
275         p_result->inform_battery_status.battery_status = *p++;
276         if (!AVRC_IS_VALID_BATTERY_STATUS(
277                 p_result->inform_battery_status.battery_status))
278           status = AVRC_STS_BAD_PARAM;
279       }
280       break;
281 
282     case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
283       if (len < 9)                  /* UID/8 and num_attr/1 */
284         return AVRC_STS_INTERNAL_ERR;
285       else {
286         BE_STREAM_TO_UINT32(u32, p);
287         BE_STREAM_TO_UINT32(u32_2, p);
288         if (u32 == 0 && u32_2 == 0) {
289           BE_STREAM_TO_UINT8(p_result->get_elem_attrs.num_attr, p);
290           if ((len - 9 /* UID/8 and num_attr/1 */) !=
291               (p_result->get_elem_attrs.num_attr * 4))
292             status = AVRC_STS_INTERNAL_ERR;
293           else {
294             p_u32 = p_result->get_elem_attrs.attrs;
295             if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE)
296               p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
297             for (xx = 0; xx < p_result->get_elem_attrs.num_attr; xx++) {
298               BE_STREAM_TO_UINT32(p_u32[xx], p);
299             }
300           }
301         } else
302           status = AVRC_STS_NOT_FOUND;
303       }
304       break;
305 
306     case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
307       /* no additional parameters */
308       if (len != 0) return AVRC_STS_INTERNAL_ERR;
309       break;
310 
311     case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
312       if (len != 5)
313         return AVRC_STS_INTERNAL_ERR;
314       else {
315         BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
316         if (!AVRC_IS_VALID_EVENT_ID(p_result->reg_notif.event_id)) {
317           android_errorWriteLog(0x534e4554, "168802990");
318           AVRC_TRACE_ERROR("%s: Invalid event id: %d", __func__,
319                            p_result->reg_notif.event_id);
320           return AVRC_STS_BAD_PARAM;
321         }
322 
323         BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
324       }
325       break;
326 
327     case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
328       if (len != 1)
329         return AVRC_STS_INTERNAL_ERR;
330       else
331         p_result->volume.volume = *p++;
332       break;
333 
334     case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
335       if (len != 1) {
336         return AVRC_STS_INTERNAL_ERR;
337       }
338       BE_STREAM_TO_UINT8(p_result->continu.target_pdu, p);
339       break;
340 
341     case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
342       if (len != 1) {
343         return AVRC_STS_INTERNAL_ERR;
344       }
345       BE_STREAM_TO_UINT8(p_result->abort.target_pdu, p);
346       break;
347 
348     case AVRC_PDU_SET_ADDRESSED_PLAYER: /* 0x60 */
349       if (len != 2) {
350         AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER length is incorrect:%d",
351                          len);
352         return AVRC_STS_INTERNAL_ERR;
353       }
354       BE_STREAM_TO_UINT16(p_result->addr_player.player_id, p);
355       break;
356 
357     case AVRC_PDU_PLAY_ITEM:          /* 0x74 */
358     case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
359       if (len != (AVRC_UID_SIZE + 3)) return AVRC_STS_INTERNAL_ERR;
360       BE_STREAM_TO_UINT8(p_result->play_item.scope, p);
361       if (p_result->play_item.scope > AVRC_SCOPE_NOW_PLAYING) {
362         status = AVRC_STS_BAD_SCOPE;
363       }
364       BE_STREAM_TO_ARRAY(p, p_result->play_item.uid, AVRC_UID_SIZE);
365       BE_STREAM_TO_UINT16(p_result->play_item.uid_counter, p);
366       break;
367 
368     default:
369       status = AVRC_STS_BAD_CMD;
370       break;
371   }
372 
373   return status;
374 }
375 
376 /*******************************************************************************
377  *
378  * Function         AVRC_Ctrl_ParsCommand
379  *
380  * Description      This function is used to parse cmds received for CTRL
381  *                  Currently it is for SetAbsVolume and Volume Change
382  *                  Notification.
383  *
384  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
385  *                  successfully.
386  *                  Otherwise, the error code defined by AVRCP 1.4
387  *
388  ******************************************************************************/
AVRC_Ctrl_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result)389 tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) {
390   tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
391 
392   if (p_msg && p_result) {
393     switch (p_msg->hdr.opcode) {
394       case AVRC_OP_VENDOR: /*  0x00    Vendor-dependent commands */
395         status = avrc_ctrl_pars_vendor_cmd(&p_msg->vendor, p_result);
396         break;
397 
398       default:
399         AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
400         break;
401     }
402     p_result->cmd.opcode = p_msg->hdr.opcode;
403     p_result->cmd.status = status;
404   }
405   AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
406   return status;
407 }
408 
409 #define RETURN_STATUS_IF_FALSE(_status_, _b_, _msg_, ...) \
410   if (!(_b_)) {                                           \
411     AVRC_TRACE_DEBUG(_msg_, ##__VA_ARGS__);               \
412     return _status_;                                      \
413   }
414 
415 /*******************************************************************************
416  *
417  * Function         avrc_pars_browsing_cmd
418  *
419  * Description      This function parses the commands that go through the
420  *                  browsing channel
421  *
422  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
423  *                  successfully.
424  *                  Otherwise, the error code defined by AVRCP+1
425  *
426  ******************************************************************************/
avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)427 static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
428                                         tAVRC_COMMAND* p_result, uint8_t* p_buf,
429                                         uint16_t buf_len) {
430   tAVRC_STS status = AVRC_STS_NO_ERROR;
431   uint8_t* p = p_msg->p_browse_data;
432   int count;
433 
434   uint16_t min_len = 3;
435   RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
436                          "msg too short");
437 
438   p_result->pdu = *p++;
439   AVRC_TRACE_DEBUG("avrc_pars_browsing_cmd() pdu:0x%x", p_result->pdu);
440   /* skip over len */
441   p += 2;
442 
443   switch (p_result->pdu) {
444     case AVRC_PDU_SET_BROWSED_PLAYER: /* 0x70 */
445       min_len += 2;
446       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
447                              "msg too short");
448 
449       // For current implementation all players are browsable.
450       BE_STREAM_TO_UINT16(p_result->br_player.player_id, p);
451       break;
452 
453     case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
454 
455       min_len += 10;
456       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
457                              "msg too short");
458 
459       STREAM_TO_UINT8(p_result->get_items.scope, p);
460       // To be modified later here (Scope) when all browsing commands are
461       // supported
462       if (p_result->get_items.scope > AVRC_SCOPE_NOW_PLAYING) {
463         status = AVRC_STS_BAD_SCOPE;
464       }
465       BE_STREAM_TO_UINT32(p_result->get_items.start_item, p);
466       BE_STREAM_TO_UINT32(p_result->get_items.end_item, p);
467       if (p_result->get_items.start_item > p_result->get_items.end_item) {
468         status = AVRC_STS_BAD_RANGE;
469       }
470       STREAM_TO_UINT8(p_result->get_items.attr_count, p);
471       p_result->get_items.p_attr_list = NULL;
472       if (p_result->get_items.attr_count && p_buf &&
473           (p_result->get_items.attr_count != AVRC_FOLDER_ITEM_COUNT_NONE)) {
474         p_result->get_items.p_attr_list = (uint32_t*)p_buf;
475         count = p_result->get_items.attr_count;
476         if (buf_len < (count << 2))
477           p_result->get_items.attr_count = count = (buf_len >> 2);
478         for (int idx = 0; idx < count; idx++) {
479           min_len += 4;
480           RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
481                                  (p_msg->browse_len >= min_len),
482                                  "msg too short");
483 
484           BE_STREAM_TO_UINT32(p_result->get_items.p_attr_list[idx], p);
485         }
486       }
487       break;
488 
489     case AVRC_PDU_CHANGE_PATH: /* 0x72 */
490       min_len += 11;
491       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
492                              "msg too short");
493 
494       BE_STREAM_TO_UINT16(p_result->chg_path.uid_counter, p);
495       BE_STREAM_TO_UINT8(p_result->chg_path.direction, p);
496       if (p_result->chg_path.direction != AVRC_DIR_UP &&
497           p_result->chg_path.direction != AVRC_DIR_DOWN) {
498         status = AVRC_STS_BAD_DIR;
499       }
500       BE_STREAM_TO_ARRAY(p, p_result->chg_path.folder_uid, AVRC_UID_SIZE);
501       break;
502 
503     case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */
504       min_len += 12;
505       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
506                              "msg too short");
507 
508       BE_STREAM_TO_UINT8(p_result->get_attrs.scope, p);
509 
510       if (p_result->get_attrs.scope > AVRC_SCOPE_NOW_PLAYING) {
511         status = AVRC_STS_BAD_SCOPE;
512         break;
513       }
514       BE_STREAM_TO_ARRAY(p, p_result->get_attrs.uid, AVRC_UID_SIZE);
515       BE_STREAM_TO_UINT16(p_result->get_attrs.uid_counter, p);
516       BE_STREAM_TO_UINT8(p_result->get_attrs.attr_count, p);
517       p_result->get_attrs.p_attr_list = NULL;
518       if (p_result->get_attrs.attr_count && p_buf) {
519         p_result->get_attrs.p_attr_list = (uint32_t*)p_buf;
520         count = p_result->get_attrs.attr_count;
521         if (buf_len < (count << 2))
522           p_result->get_attrs.attr_count = count = (buf_len >> 2);
523         for (int idx = 0, count = 0; idx < p_result->get_attrs.attr_count;
524              idx++) {
525           min_len += 4;
526           RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
527                                  (p_msg->browse_len >= min_len),
528                                  "msg too short");
529 
530           BE_STREAM_TO_UINT32(p_result->get_attrs.p_attr_list[count], p);
531           if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(
532                   p_result->get_attrs.p_attr_list[count])) {
533             count++;
534           }
535         }
536 
537         if (p_result->get_attrs.attr_count != count && count == 0)
538           status = AVRC_STS_BAD_PARAM;
539         else
540           p_result->get_attrs.attr_count = count;
541       }
542       break;
543 
544     case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: /* 0x75 */
545       ++min_len;
546       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
547                              "msg too short");
548 
549       BE_STREAM_TO_UINT8(p_result->get_num_of_items.scope, p);
550       if (p_result->get_num_of_items.scope > AVRC_SCOPE_NOW_PLAYING) {
551         status = AVRC_STS_BAD_SCOPE;
552       }
553       break;
554 
555     case AVRC_PDU_SEARCH: /* 0x80 */
556       min_len += 4;
557       RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
558                              "msg too short");
559 
560       BE_STREAM_TO_UINT16(p_result->search.string.charset_id, p);
561       BE_STREAM_TO_UINT16(p_result->search.string.str_len, p);
562       p_result->search.string.p_str = p_buf;
563       if (p_buf) {
564         if (p_result->search.string.str_len > buf_len) {
565           p_result->search.string.str_len = buf_len;
566         } else {
567           android_errorWriteLog(0x534e4554, "63146237");
568         }
569         min_len += p_result->search.string.str_len;
570         RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
571                                "msg too short");
572 
573         BE_STREAM_TO_ARRAY(p, p_buf, p_result->search.string.str_len);
574       } else {
575         status = AVRC_STS_INTERNAL_ERR;
576       }
577       break;
578 
579     default:
580       status = AVRC_STS_BAD_CMD;
581       break;
582   }
583   return status;
584 }
585 
586 /*******************************************************************************
587  *
588  * Function         AVRC_ParsCommand
589  *
590  * Description      This function is a superset of AVRC_ParsMetadata to parse
591  *                  the command.
592  *
593  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
594  *                  successfully.
595  *                  Otherwise, the error code defined by AVRCP 1.4
596  *
597  ******************************************************************************/
AVRC_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)598 tAVRC_STS AVRC_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result,
599                            uint8_t* p_buf, uint16_t buf_len) {
600   tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
601   uint16_t id;
602 
603   if (p_msg && p_result) {
604     switch (p_msg->hdr.opcode) {
605       case AVRC_OP_VENDOR: /*  0x00    Vendor-dependent commands */
606         status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
607         break;
608 
609       case AVRC_OP_PASS_THRU: /*  0x7C    panel subunit opcode */
610         status = avrc_pars_pass_thru(&p_msg->pass, &id);
611         if (status == AVRC_STS_NO_ERROR) {
612           p_result->pdu = (uint8_t)id;
613         }
614         break;
615 
616       case AVRC_OP_BROWSE:
617         status =
618             avrc_pars_browsing_cmd(&p_msg->browse, p_result, p_buf, buf_len);
619         break;
620 
621       default:
622         AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
623         break;
624     }
625     p_result->cmd.opcode = p_msg->hdr.opcode;
626     p_result->cmd.status = status;
627   }
628   AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
629   return status;
630 }
631