Home | History | Annotate | Download | only in avrc
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2006-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 
     29 
     30 #if (AVRC_METADATA_INCLUDED == TRUE)
     31 /*******************************************************************************
     32 **
     33 ** Function         avrc_bld_next_cmd
     34 **
     35 ** Description      This function builds the Request Continue or Abort command.
     36 **
     37 ** Returns          AVRC_STS_NO_ERROR, if the command is built successfully
     38 **                  Otherwise, the error code.
     39 **
     40 *******************************************************************************/
     41 static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt)
     42 {
     43     UINT8   *p_data, *p_start;
     44 
     45     AVRC_TRACE_API("avrc_bld_next_cmd");
     46 
     47     /* get the existing length, if any, and also the num attributes */
     48     p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
     49     p_data = p_start + 2; /* pdu + rsvd */
     50 
     51     /* add fixed lenth 1 - pdu_id (1) */
     52     UINT16_TO_BE_STREAM(p_data, 1);
     53     UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
     54     p_pkt->len = (p_data - p_start);
     55 
     56     return AVRC_STS_NO_ERROR;
     57 }
     58 
     59 /*****************************************************************************
     60 **  the following commands are introduced in AVRCP 1.4
     61 *****************************************************************************/
     62 
     63 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
     64 /*******************************************************************************
     65 **
     66 ** Function         avrc_bld_set_abs_volume_cmd
     67 **
     68 ** Description      This function builds the Set Absolute Volume command.
     69 **
     70 ** Returns          AVRC_STS_NO_ERROR, if the command is built successfully
     71 **                  Otherwise, the error code.
     72 **
     73 *******************************************************************************/
     74 static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HDR *p_pkt)
     75 {
     76     UINT8   *p_data, *p_start;
     77 
     78     AVRC_TRACE_API("avrc_bld_set_abs_volume_cmd");
     79     /* get the existing length, if any, and also the num attributes */
     80     p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
     81     p_data = p_start + 2; /* pdu + rsvd */
     82     /* add fixed lenth 1 - volume (1) */
     83     UINT16_TO_BE_STREAM(p_data, 1);
     84     UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
     85     p_pkt->len = (p_data - p_start);
     86     return AVRC_STS_NO_ERROR;
     87 }
     88 
     89 /*******************************************************************************
     90 **
     91 ** Function         avrc_bld_vol_change_notfn
     92 **
     93 ** Description      This function builds the register notification for volume change.
     94 **
     95 ** Returns          AVRC_STS_NO_ERROR, if the command is built successfully
     96 **                  Otherwise, the error code.
     97 **
     98 *******************************************************************************/
     99 static tAVRC_STS avrc_bld_vol_change_notfn(BT_HDR * p_pkt)
    100 {
    101     UINT8   *p_data, *p_start;
    102 
    103     AVRC_TRACE_API("avrc_bld_vol_change");
    104     /* get the existing length, if any, and also the num attributes */
    105     // Set the notify value
    106     p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    107     p_data = p_start + 2; /* pdu + rsvd */
    108     /* add fixed length 5 -*/
    109     UINT16_TO_BE_STREAM(p_data, 5);
    110     UINT8_TO_BE_STREAM(p_data,AVRC_EVT_VOLUME_CHANGE);
    111     UINT32_TO_BE_STREAM(p_data, 0);
    112     p_pkt->len = (p_data - p_start);
    113     return AVRC_STS_NO_ERROR;
    114 }
    115 #endif
    116 
    117 /*******************************************************************************
    118 **
    119 ** Function         avrc_bld_init_cmd_buffer
    120 **
    121 ** Description      This function initializes the command buffer based on PDU
    122 **
    123 ** Returns          NULL, if no GKI buffer or failure to build the message.
    124 **                  Otherwise, the GKI buffer that contains the initialized message.
    125 **
    126 *******************************************************************************/
    127 static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd)
    128 {
    129     UINT16 offset = 0, chnl = AVCT_DATA_CTRL, len=AVRC_META_CMD_POOL_SIZE;
    130     BT_HDR *p_pkt=NULL;
    131     UINT8  opcode;
    132 
    133     opcode = avrc_opcode_from_pdu(p_cmd->pdu);
    134     AVRC_TRACE_API("avrc_bld_init_cmd_buffer: pdu=%x, opcode=%x", p_cmd->pdu, opcode);
    135 
    136     switch (opcode)
    137     {
    138     case AVRC_OP_PASS_THRU:
    139         offset  = AVRC_MSG_PASS_THRU_OFFSET;
    140         break;
    141 
    142     case AVRC_OP_VENDOR:
    143         offset  = AVRC_MSG_VENDOR_OFFSET;
    144         break;
    145     }
    146 
    147     /* allocate and initialize the buffer */
    148     p_pkt = (BT_HDR *)GKI_getbuf(len);
    149     if (p_pkt)
    150     {
    151         UINT8 *p_data, *p_start;
    152 
    153         p_pkt->layer_specific = chnl;
    154         p_pkt->event    = opcode;
    155         p_pkt->offset   = offset;
    156         p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
    157         p_start = p_data;
    158 
    159         /* pass thru - group navigation - has a two byte op_id, so dont do it here */
    160         if (opcode != AVRC_OP_PASS_THRU)
    161             *p_data++ = p_cmd->pdu;
    162 
    163         switch (opcode)
    164         {
    165         case AVRC_OP_VENDOR:
    166             /* reserved 0, packet_type 0 */
    167             UINT8_TO_BE_STREAM(p_data, 0);
    168             /* continue to the next "case to add length */
    169             /* add fixed lenth - 0 */
    170             UINT16_TO_BE_STREAM(p_data, 0);
    171             break;
    172         }
    173 
    174         p_pkt->len = (p_data - p_start);
    175     }
    176     p_cmd->cmd.opcode = opcode;
    177     return p_pkt;
    178 }
    179 
    180 /*******************************************************************************
    181 **
    182 ** Function         AVRC_BldCommand
    183 **
    184 ** Description      This function builds the given AVRCP command to the given
    185 **                  GKI buffer
    186 **
    187 ** Returns          AVRC_STS_NO_ERROR, if the command is built successfully
    188 **                  Otherwise, the error code.
    189 **
    190 *******************************************************************************/
    191 tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt)
    192 {
    193     tAVRC_STS status = AVRC_STS_BAD_PARAM;
    194     BT_HDR  *p_pkt;
    195     BOOLEAN alloc = FALSE;
    196 
    197     AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu, p_cmd->cmd.status);
    198     if (!p_cmd || !pp_pkt)
    199     {
    200         AVRC_TRACE_API("AVRC_BldCommand. Invalid parameters passed. p_cmd=%p, pp_pkt=%p",
    201             p_cmd, pp_pkt);
    202         return AVRC_STS_BAD_PARAM;
    203     }
    204 
    205     if (*pp_pkt == NULL)
    206     {
    207         if ((*pp_pkt = avrc_bld_init_cmd_buffer(p_cmd)) == NULL)
    208         {
    209             AVRC_TRACE_API("AVRC_BldCommand: Failed to initialize command buffer");
    210             return AVRC_STS_INTERNAL_ERR;
    211         }
    212         alloc = TRUE;
    213     }
    214     status = AVRC_STS_NO_ERROR;
    215     p_pkt = *pp_pkt;
    216 
    217     switch (p_cmd->pdu)
    218     {
    219     case AVRC_PDU_REQUEST_CONTINUATION_RSP:     /*        0x40 */
    220         status = avrc_bld_next_cmd(&p_cmd->continu, p_pkt);
    221         break;
    222 
    223     case AVRC_PDU_ABORT_CONTINUATION_RSP:       /*          0x41 */
    224         status = avrc_bld_next_cmd(&p_cmd->abort, p_pkt);
    225         break;
    226 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
    227     case AVRC_PDU_SET_ABSOLUTE_VOLUME:         /* 0x50 */
    228         status = avrc_bld_set_abs_volume_cmd(&p_cmd->volume, p_pkt);
    229         break;
    230 #endif
    231 
    232     case AVRC_PDU_REGISTER_NOTIFICATION:      /* 0x31 */
    233 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
    234         if(AVRC_EVT_VOLUME_CHANGE==p_cmd->reg_notif.event_id)
    235            status=avrc_bld_vol_change_notfn(p_pkt);
    236 #endif
    237         break;
    238 
    239     }
    240 
    241     if (alloc && (status != AVRC_STS_NO_ERROR) )
    242     {
    243         GKI_freebuf(p_pkt);
    244         *pp_pkt = NULL;
    245     }
    246     AVRC_TRACE_API("AVRC_BldCommand: returning %d", status);
    247     return status;
    248 }
    249 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
    250 
    251