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