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 "bt_common.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 #if (AVRC_CTLR_INCLUDED == TRUE)
     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 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, tAVRC_COMMAND *p_result)
     43 {
     44     tAVRC_STS  status = AVRC_STS_NO_ERROR;
     45 
     46     UINT8   *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     {
     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  len;
     57     BE_STREAM_TO_UINT16 (len, p);
     58     if ((len+4) != (p_msg->vendor_len))
     59     {
     60         status = AVRC_STS_INTERNAL_ERR;
     61     }
     62 
     63     if (status != AVRC_STS_NO_ERROR)
     64         return status;
     65 
     66     switch (p_result->pdu)
     67     {
     68         case AVRC_PDU_SET_ABSOLUTE_VOLUME:
     69         {
     70             if(len!=1)
     71                 status = AVRC_STS_INTERNAL_ERR;
     72             else
     73             {
     74                 BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
     75                 p_result->volume.volume = AVRC_MAX_VOLUME & p_result->volume.volume;
     76             }
     77             break;
     78         }
     79         case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
     80             BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
     81             BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
     82             break;
     83         default:
     84             status = AVRC_STS_BAD_CMD;
     85             break;
     86     }
     87     return status;
     88 }
     89 #endif
     90 
     91 /*******************************************************************************
     92 **
     93 ** Function         avrc_pars_vendor_cmd
     94 **
     95 ** Description      This function parses the vendor specific commands defined by
     96 **                  Bluetooth SIG
     97 **
     98 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
     99 **                  Otherwise, the error code defined by AVRCP 1.4
    100 **
    101 *******************************************************************************/
    102 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result,
    103                                       UINT8 *p_buf, UINT16 buf_len)
    104 {
    105     tAVRC_STS  status = AVRC_STS_NO_ERROR;
    106     UINT8   *p;
    107     UINT16  len;
    108     UINT8   xx, yy;
    109     UINT8   *p_u8;
    110     UINT16  *p_u16;
    111     UINT32  u32, u32_2, *p_u32;
    112     tAVRC_APP_SETTING       *p_app_set;
    113     UINT16  size_needed;
    114 
    115     /* Check the vendor data */
    116     if (p_msg->vendor_len == 0)
    117         return AVRC_STS_NO_ERROR;
    118     if (p_msg->p_vendor_data == NULL)
    119         return AVRC_STS_INTERNAL_ERR;
    120 
    121     p = p_msg->p_vendor_data;
    122     p_result->pdu = *p++;
    123     AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
    124     if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype))
    125     {
    126         AVRC_TRACE_DEBUG("%s detects wrong AV/C type!", __func__);
    127         status = AVRC_STS_BAD_CMD;
    128     }
    129 
    130     p++; /* skip the reserved byte */
    131     BE_STREAM_TO_UINT16 (len, p);
    132     if ((len+4) != (p_msg->vendor_len))
    133     {
    134         status = AVRC_STS_INTERNAL_ERR;
    135     }
    136 
    137     if (status != AVRC_STS_NO_ERROR)
    138         return status;
    139 
    140     switch (p_result->pdu)
    141     {
    142     case AVRC_PDU_GET_CAPABILITIES:         /* 0x10 */
    143         p_result->get_caps.capability_id = *p++;
    144         if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
    145             status = AVRC_STS_BAD_PARAM;
    146         else if (len != 1)
    147             status = AVRC_STS_INTERNAL_ERR;
    148         break;
    149 
    150     case AVRC_PDU_LIST_PLAYER_APP_ATTR:     /* 0x11 */
    151         /* no additional parameters */
    152         if (len != 0)
    153             status = AVRC_STS_INTERNAL_ERR;
    154         break;
    155 
    156     case AVRC_PDU_LIST_PLAYER_APP_VALUES:   /* 0x12 */
    157         p_result->list_app_values.attr_id = *p++;
    158         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
    159             status = AVRC_STS_BAD_PARAM;
    160         else if (len != 1)
    161             status = AVRC_STS_INTERNAL_ERR;
    162         break;
    163 
    164     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
    165     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
    166         BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
    167         if (len != (p_result->get_cur_app_val.num_attr+1))
    168         {
    169             status = AVRC_STS_INTERNAL_ERR;
    170             break;
    171         }
    172         p_u8 = p_result->get_cur_app_val.attrs;
    173         for (xx=0, yy=0; xx< p_result->get_cur_app_val.num_attr; xx++)
    174         {
    175             /* only report the valid player app attributes */
    176             if (AVRC_IsValidPlayerAttr(*p))
    177                 p_u8[yy++] = *p;
    178             p++;
    179         }
    180         p_result->get_cur_app_val.num_attr = yy;
    181         if (yy == 0)
    182         {
    183             status = AVRC_STS_BAD_PARAM;
    184         }
    185         break;
    186 
    187     case AVRC_PDU_SET_PLAYER_APP_VALUE:     /* 0x14 */
    188         BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
    189         size_needed = sizeof(tAVRC_APP_SETTING);
    190         if (p_buf && (len == ((p_result->set_app_val.num_val<<1) + 1)))
    191         {
    192             p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
    193             p_app_set = p_result->set_app_val.p_vals;
    194             for (xx=0; ((xx< p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++)
    195             {
    196                 p_app_set[xx].attr_id = *p++;
    197                 p_app_set[xx].attr_val = *p++;
    198                 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val))
    199                     status = AVRC_STS_BAD_PARAM;
    200             }
    201             if (xx != p_result->set_app_val.num_val)
    202             {
    203                 AVRC_TRACE_ERROR(
    204                     "%s AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
    205                     __func__, xx, p_result->set_app_val.num_val);
    206                 p_result->set_app_val.num_val = xx;
    207             }
    208         }
    209         else
    210         {
    211             AVRC_TRACE_ERROR("%s AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len",
    212                              __func__);
    213             status = AVRC_STS_INTERNAL_ERR;
    214         }
    215         break;
    216 
    217     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */
    218         if (len < 3)
    219             status = AVRC_STS_INTERNAL_ERR;
    220         else
    221         {
    222             BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p);
    223             if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
    224                 status = AVRC_STS_BAD_PARAM;
    225             else
    226             {
    227                 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p);
    228                 if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val)
    229                     status = AVRC_STS_INTERNAL_ERR;
    230                 else
    231                 {
    232                     p_u8 = p_result->get_app_val_txt.vals;
    233                     for (xx=0; xx< p_result->get_app_val_txt.num_val; xx++)
    234                     {
    235                         p_u8[xx] = *p++;
    236                         if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id,
    237                             p_u8[xx]))
    238                         {
    239                             status = AVRC_STS_BAD_PARAM;
    240                             break;
    241                         }
    242                     }
    243                 }
    244             }
    245         }
    246         break;
    247 
    248     case AVRC_PDU_INFORM_DISPLAY_CHARSET:  /* 0x17 */
    249         if (len < 3)
    250             status = AVRC_STS_INTERNAL_ERR;
    251         else
    252         {
    253             BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p);
    254             if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2)
    255                 status = AVRC_STS_INTERNAL_ERR;
    256             else
    257             {
    258                 p_u16 = p_result->inform_charset.charsets;
    259                 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE)
    260                     p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
    261                 for (xx=0; xx< p_result->inform_charset.num_id; xx++)
    262                 {
    263                     BE_STREAM_TO_UINT16 (p_u16[xx], p);
    264                 }
    265             }
    266         }
    267         break;
    268 
    269     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */
    270         if (len != 1)
    271             status = AVRC_STS_INTERNAL_ERR;
    272         else
    273         {
    274             p_result->inform_battery_status.battery_status = *p++;
    275             if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status))
    276                 status = AVRC_STS_BAD_PARAM;
    277         }
    278         break;
    279 
    280     case AVRC_PDU_GET_ELEMENT_ATTR:         /* 0x20 */
    281         if (len < 9) /* UID/8 and num_attr/1 */
    282             status = AVRC_STS_INTERNAL_ERR;
    283         else
    284         {
    285             BE_STREAM_TO_UINT32 (u32, p);
    286             BE_STREAM_TO_UINT32 (u32_2, p);
    287             if (u32== 0 && u32_2 == 0)
    288             {
    289                 BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p);
    290                 if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4))
    291                     status = AVRC_STS_INTERNAL_ERR;
    292                 else
    293                 {
    294                     p_u32 = p_result->get_elem_attrs.attrs;
    295                     if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE)
    296                         p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
    297                     for (xx=0; xx< p_result->get_elem_attrs.num_attr; xx++)
    298                     {
    299                         BE_STREAM_TO_UINT32 (p_u32[xx], p);
    300                     }
    301                 }
    302             }
    303             else
    304                 status = AVRC_STS_NOT_FOUND;
    305         }
    306         break;
    307 
    308     case AVRC_PDU_GET_PLAY_STATUS:          /* 0x30 */
    309         /* no additional parameters */
    310         if (len != 0)
    311             status = AVRC_STS_INTERNAL_ERR;
    312         break;
    313 
    314     case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
    315         if (len != 5)
    316             status = AVRC_STS_INTERNAL_ERR;
    317         else
    318         {
    319             BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
    320             BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
    321         }
    322         break;
    323 
    324     case AVRC_PDU_SET_ABSOLUTE_VOLUME:
    325     {
    326         if(len!=1)
    327             status = AVRC_STS_INTERNAL_ERR;
    328         break;
    329     }
    330 
    331     /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
    332     /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
    333 
    334     default:
    335         status = AVRC_STS_BAD_CMD;
    336         break;
    337     }
    338 
    339     return status;
    340 }
    341 
    342 #if (AVRC_CTLR_INCLUDED == TRUE)
    343 /*******************************************************************************
    344 **
    345 ** Function         AVRC_Ctrl_ParsCommand
    346 **
    347 ** Description      This function is used to parse cmds received for CTRL
    348 **                  Currently it is for SetAbsVolume and Volume Change Notification..
    349 **
    350 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
    351 **                  Otherwise, the error code defined by AVRCP 1.4
    352 **
    353 *******************************************************************************/
    354 tAVRC_STS AVRC_Ctrl_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result)
    355 {
    356     tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
    357 
    358     if (p_msg && p_result)
    359     {
    360         switch (p_msg->hdr.opcode)
    361         {
    362         case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
    363             status = avrc_ctrl_pars_vendor_cmd(&p_msg->vendor, p_result);
    364             break;
    365 
    366         default:
    367             AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
    368             break;
    369         }
    370         p_result->cmd.opcode = p_msg->hdr.opcode;
    371         p_result->cmd.status = status;
    372     }
    373     AVRC_TRACE_DEBUG("%s return status:0x%x", __FUNCTION__, status);
    374     return status;
    375 }
    376 #endif
    377 
    378 /*******************************************************************************
    379 **
    380 ** Function         AVRC_ParsCommand
    381 **
    382 ** Description      This function is a superset of AVRC_ParsMetadata to parse the command.
    383 **
    384 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
    385 **                  Otherwise, the error code defined by AVRCP 1.4
    386 **
    387 *******************************************************************************/
    388 tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len)
    389 {
    390     tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
    391     UINT16  id;
    392 
    393     if (p_msg && p_result)
    394     {
    395         switch (p_msg->hdr.opcode)
    396         {
    397         case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
    398             status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
    399             break;
    400 
    401         case AVRC_OP_PASS_THRU:  /*  0x7C    panel subunit opcode */
    402             status = avrc_pars_pass_thru(&p_msg->pass, &id);
    403             if (status == AVRC_STS_NO_ERROR)
    404             {
    405                 p_result->pdu = (UINT8)id;
    406             }
    407             break;
    408 
    409         default:
    410             AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
    411             break;
    412         }
    413         p_result->cmd.opcode = p_msg->hdr.opcode;
    414         p_result->cmd.status = status;
    415     }
    416     AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
    417     return status;
    418 }
    419 
    420 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
    421 
    422