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