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