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