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