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