Home | History | Annotate | Download | only in avrc
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2003-2013 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 "gki.h"
     21 #include "avrc_api.h"
     22 #include "avrc_defs.h"
     23 #include "avrc_int.h"
     24 
     25 /*****************************************************************************
     26 **  Global data
     27 *****************************************************************************/
     28 #if (AVRC_METADATA_INCLUDED == TRUE)
     29 
     30 /*******************************************************************************
     31 **
     32 ** Function         avrc_pars_vendor_cmd
     33 **
     34 ** Description      This function parses the vendor specific commands defined by
     35 **                  Bluetooth SIG
     36 **
     37 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
     38 **                  Otherwise, the error code defined by AVRCP 1.4
     39 **
     40 *******************************************************************************/
     41 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result,
     42                                       UINT8 *p_buf, UINT16 buf_len)
     43 {
     44     tAVRC_STS  status = AVRC_STS_NO_ERROR;
     45     UINT8   *p = p_msg->p_vendor_data;
     46     UINT16  len;
     47     UINT8   xx, yy;
     48     UINT8   *p_u8;
     49     UINT16  *p_u16;
     50     UINT32  u32, u32_2, *p_u32;
     51     tAVRC_APP_SETTING       *p_app_set;
     52     UINT16  size_needed;
     53 
     54     p_result->pdu = *p++;
     55     AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() pdu:0x%x", p_result->pdu);
     56     if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype))
     57     {
     58         AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() detects wrong AV/C type!");
     59         status = AVRC_STS_BAD_CMD;
     60     }
     61 
     62     p++; /* skip the reserved byte */
     63     BE_STREAM_TO_UINT16 (len, p);
     64     if ((len+4) != (p_msg->vendor_len))
     65     {
     66         status = AVRC_STS_INTERNAL_ERR;
     67     }
     68 
     69     if (status != AVRC_STS_NO_ERROR)
     70         return status;
     71 
     72     switch (p_result->pdu)
     73     {
     74     case AVRC_PDU_GET_CAPABILITIES:         /* 0x10 */
     75         p_result->get_caps.capability_id = *p++;
     76         if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
     77             status = AVRC_STS_BAD_PARAM;
     78         else if (len != 1)
     79             status = AVRC_STS_INTERNAL_ERR;
     80         break;
     81 
     82     case AVRC_PDU_LIST_PLAYER_APP_ATTR:     /* 0x11 */
     83         /* no additional parameters */
     84         if (len != 0)
     85             status = AVRC_STS_INTERNAL_ERR;
     86         break;
     87 
     88     case AVRC_PDU_LIST_PLAYER_APP_VALUES:   /* 0x12 */
     89         p_result->list_app_values.attr_id = *p++;
     90         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
     91             status = AVRC_STS_BAD_PARAM;
     92         else if (len != 1)
     93             status = AVRC_STS_INTERNAL_ERR;
     94         break;
     95 
     96     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
     97     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
     98         BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
     99         if (len != (p_result->get_cur_app_val.num_attr+1))
    100         {
    101             status = AVRC_STS_INTERNAL_ERR;
    102             break;
    103         }
    104         p_u8 = p_result->get_cur_app_val.attrs;
    105         for (xx=0, yy=0; xx< p_result->get_cur_app_val.num_attr; xx++)
    106         {
    107             /* only report the valid player app attributes */
    108             if (AVRC_IsValidPlayerAttr(*p))
    109                 p_u8[yy++] = *p;
    110             p++;
    111         }
    112         p_result->get_cur_app_val.num_attr = yy;
    113         if (yy == 0)
    114         {
    115             status = AVRC_STS_BAD_PARAM;
    116         }
    117         break;
    118 
    119     case AVRC_PDU_SET_PLAYER_APP_VALUE:     /* 0x14 */
    120         BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
    121         size_needed = sizeof(tAVRC_APP_SETTING);
    122         if (p_buf && (len == ((p_result->set_app_val.num_val<<1) + 1)))
    123         {
    124             p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
    125             p_app_set = p_result->set_app_val.p_vals;
    126             for (xx=0; ((xx< p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++)
    127             {
    128                 p_app_set[xx].attr_id = *p++;
    129                 p_app_set[xx].attr_val = *p++;
    130                 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val))
    131                     status = AVRC_STS_BAD_PARAM;
    132             }
    133             if (xx != p_result->set_app_val.num_val)
    134             {
    135                 AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
    136                     xx, p_result->set_app_val.num_val);
    137                 p_result->set_app_val.num_val = xx;
    138             }
    139         }
    140         else
    141         {
    142             AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
    143             status = AVRC_STS_INTERNAL_ERR;
    144         }
    145         break;
    146 
    147     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */
    148         if (len < 3)
    149             status = AVRC_STS_INTERNAL_ERR;
    150         else
    151         {
    152             BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p);
    153             if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
    154                 status = AVRC_STS_BAD_PARAM;
    155             else
    156             {
    157                 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p);
    158                 if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val)
    159                     status = AVRC_STS_INTERNAL_ERR;
    160                 else
    161                 {
    162                     p_u8 = p_result->get_app_val_txt.vals;
    163                     for (xx=0; xx< p_result->get_app_val_txt.num_val; xx++)
    164                     {
    165                         p_u8[xx] = *p++;
    166                         if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id,
    167                             p_u8[xx]))
    168                         {
    169                             status = AVRC_STS_BAD_PARAM;
    170                             break;
    171                         }
    172                     }
    173                 }
    174             }
    175         }
    176         break;
    177 
    178     case AVRC_PDU_INFORM_DISPLAY_CHARSET:  /* 0x17 */
    179         if (len < 3)
    180             status = AVRC_STS_INTERNAL_ERR;
    181         else
    182         {
    183             BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p);
    184             if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2)
    185                 status = AVRC_STS_INTERNAL_ERR;
    186             else
    187             {
    188                 p_u16 = p_result->inform_charset.charsets;
    189                 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE)
    190                     p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
    191                 for (xx=0; xx< p_result->inform_charset.num_id; xx++)
    192                 {
    193                     BE_STREAM_TO_UINT16 (p_u16[xx], p);
    194                 }
    195             }
    196         }
    197         break;
    198 
    199     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */
    200         if (len != 1)
    201             status = AVRC_STS_INTERNAL_ERR;
    202         else
    203         {
    204             p_result->inform_battery_status.battery_status = *p++;
    205             if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status))
    206                 status = AVRC_STS_BAD_PARAM;
    207         }
    208         break;
    209 
    210     case AVRC_PDU_GET_ELEMENT_ATTR:         /* 0x20 */
    211         if (len < 9) /* UID/8 and num_attr/1 */
    212             status = AVRC_STS_INTERNAL_ERR;
    213         else
    214         {
    215             BE_STREAM_TO_UINT32 (u32, p);
    216             BE_STREAM_TO_UINT32 (u32_2, p);
    217             if (u32== 0 && u32_2 == 0)
    218             {
    219                 BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p);
    220                 if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4))
    221                     status = AVRC_STS_INTERNAL_ERR;
    222                 else
    223                 {
    224                     p_u32 = p_result->get_elem_attrs.attrs;
    225                     if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE)
    226                         p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
    227                     for (xx=0; xx< p_result->get_elem_attrs.num_attr; xx++)
    228                     {
    229                         BE_STREAM_TO_UINT32 (p_u32[xx], p);
    230                     }
    231                 }
    232             }
    233             else
    234                 status = AVRC_STS_NOT_FOUND;
    235         }
    236         break;
    237 
    238     case AVRC_PDU_GET_PLAY_STATUS:          /* 0x30 */
    239         /* no additional parameters */
    240         if (len != 0)
    241             status = AVRC_STS_INTERNAL_ERR;
    242         break;
    243 
    244     case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
    245         if (len != 5)
    246             status = AVRC_STS_INTERNAL_ERR;
    247         else
    248         {
    249             BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
    250             BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
    251         }
    252         break;
    253 
    254     case AVRC_PDU_SET_ABSOLUTE_VOLUME:
    255     {
    256         if(len!=1)
    257             status = AVRC_STS_INTERNAL_ERR;
    258         break;
    259     }
    260 
    261     /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
    262     /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
    263 
    264     default:
    265         status = AVRC_STS_BAD_CMD;
    266         break;
    267     }
    268 
    269     return status;
    270 }
    271 
    272 /*******************************************************************************
    273 **
    274 ** Function         AVRC_ParsCommand
    275 **
    276 ** Description      This function is a superset of AVRC_ParsMetadata to parse the command.
    277 **
    278 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
    279 **                  Otherwise, the error code defined by AVRCP 1.4
    280 **
    281 *******************************************************************************/
    282 tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len)
    283 {
    284     tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
    285     UINT16  id;
    286 
    287     if (p_msg && p_result)
    288     {
    289         switch (p_msg->hdr.opcode)
    290         {
    291         case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
    292             status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
    293             break;
    294 
    295         case AVRC_OP_PASS_THRU:  /*  0x7C    panel subunit opcode */
    296             status = avrc_pars_pass_thru(&p_msg->pass, &id);
    297             if (status == AVRC_STS_NO_ERROR)
    298             {
    299                 p_result->pdu = (UINT8)id;
    300             }
    301             break;
    302 
    303         default:
    304             AVRC_TRACE_ERROR("AVRC_ParsCommand() unknown opcode:0x%x", p_msg->hdr.opcode);
    305             break;
    306         }
    307         p_result->cmd.opcode = p_msg->hdr.opcode;
    308         p_result->cmd.status = status;
    309     }
    310     AVRC_TRACE_DEBUG("AVRC_ParsCommand() return status:0x%x", status);
    311     return status;
    312 }
    313 
    314 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
    315 
    316