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 *******************************************************************************/
avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result)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 *******************************************************************************/
avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result,UINT8 * p_buf,UINT16 buf_len)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 *******************************************************************************/
AVRC_Ctrl_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result)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 *******************************************************************************/
AVRC_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result,UINT8 * p_buf,UINT16 buf_len)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