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*******************************************************************************/
42static 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*******************************************************************************/
102static 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*******************************************************************************/
354tAVRC_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*******************************************************************************/
388tAVRC_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