1 /******************************************************************************
2 *
3 * Copyright 2003-2016 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 "avrc_api.h"
21 #include "avrc_defs.h"
22 #include "avrc_int.h"
23 #include "bt_common.h"
24
25 #include "osi/include/log.h"
26
27 /*****************************************************************************
28 * Global data
29 ****************************************************************************/
30
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
39 * successfully.
40 * Otherwise, the error code defined by AVRCP 1.4
41 *
42 ******************************************************************************/
avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result)43 static tAVRC_STS avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
44 tAVRC_COMMAND* p_result) {
45 tAVRC_STS status = AVRC_STS_NO_ERROR;
46
47 uint8_t* p = p_msg->p_vendor_data;
48 p_result->pdu = *p++;
49 AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
50 if (!AVRC_IsValidAvcType(p_result->pdu, p_msg->hdr.ctype)) {
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_t len;
57 BE_STREAM_TO_UINT16(len, p);
58 if ((len + 4) != (p_msg->vendor_len)) {
59 status = AVRC_STS_INTERNAL_ERR;
60 }
61
62 if (status != AVRC_STS_NO_ERROR) return status;
63
64 switch (p_result->pdu) {
65 case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
66 if (len != 1)
67 status = AVRC_STS_INTERNAL_ERR;
68 else {
69 BE_STREAM_TO_UINT8(p_result->volume.volume, p);
70 p_result->volume.volume = AVRC_MAX_VOLUME & p_result->volume.volume;
71 }
72 break;
73 }
74 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
75 if (len < 5) return AVRC_STS_INTERNAL_ERR;
76
77 BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
78 BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
79
80 if (p_result->reg_notif.event_id == 0 ||
81 p_result->reg_notif.event_id > AVRC_NUM_NOTIF_EVENTS) {
82 android_errorWriteLog(0x534e4554, "181860042");
83 status = AVRC_STS_BAD_PARAM;
84 }
85 break;
86 default:
87 status = AVRC_STS_BAD_CMD;
88 break;
89 }
90 return status;
91 }
92
93 /*******************************************************************************
94 *
95 * Function avrc_pars_vendor_cmd
96 *
97 * Description This function parses the vendor specific commands defined by
98 * Bluetooth SIG
99 *
100 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
101 * successfully.
102 * Otherwise, the error code defined by AVRCP 1.4
103 *
104 ******************************************************************************/
avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)105 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
106 tAVRC_COMMAND* p_result, uint8_t* p_buf,
107 uint16_t buf_len) {
108 tAVRC_STS status = AVRC_STS_NO_ERROR;
109 uint8_t* p;
110 uint16_t len;
111 uint8_t xx, yy;
112 uint8_t* p_u8;
113 uint16_t* p_u16;
114 uint32_t u32, u32_2, *p_u32;
115 tAVRC_APP_SETTING* p_app_set;
116 uint16_t size_needed;
117
118 /* Check the vendor data */
119 if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
120 if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
121
122 if (p_msg->vendor_len < 4) {
123 android_errorWriteLog(0x534e4554, "168712382");
124 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least 4",
125 __func__, p_msg->vendor_len);
126 return AVRC_STS_INTERNAL_ERR;
127 }
128
129 p = p_msg->p_vendor_data;
130 p_result->pdu = *p++;
131 AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
132 if (!AVRC_IsValidAvcType(p_result->pdu, p_msg->hdr.ctype)) {
133 AVRC_TRACE_DEBUG("%s detects wrong AV/C type(0x%x)!", __func__,
134 p_msg->hdr.ctype);
135 status = AVRC_STS_BAD_CMD;
136 }
137
138 p++; /* skip the reserved byte */
139 BE_STREAM_TO_UINT16(len, p);
140 if ((len + 4) != (p_msg->vendor_len)) {
141 AVRC_TRACE_ERROR("%s incorrect length :%d, %d", __func__, len,
142 p_msg->vendor_len);
143 status = AVRC_STS_INTERNAL_ERR;
144 }
145
146 if (status != AVRC_STS_NO_ERROR) return status;
147
148 switch (p_result->pdu) {
149 case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */
150 p_result->get_caps.capability_id = *p++;
151 if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
152 status = AVRC_STS_BAD_PARAM;
153 else if (len != 1)
154 return AVRC_STS_INTERNAL_ERR;
155 break;
156
157 case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
158 /* no additional parameters */
159 if (len != 0) return AVRC_STS_INTERNAL_ERR;
160 break;
161
162 case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
163 if (len == 0) return AVRC_STS_INTERNAL_ERR;
164 p_result->list_app_values.attr_id = *p++;
165 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
166 status = AVRC_STS_BAD_PARAM;
167 else if (len != 1)
168 status = AVRC_STS_INTERNAL_ERR;
169 break;
170
171 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
172 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
173 if (len == 0) return AVRC_STS_INTERNAL_ERR;
174 BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_attr, p);
175 if (len != (p_result->get_cur_app_val.num_attr + 1)) {
176 status = AVRC_STS_INTERNAL_ERR;
177 break;
178 }
179
180 if (p_result->get_cur_app_val.num_attr > AVRC_MAX_APP_ATTR_SIZE) {
181 android_errorWriteLog(0x534e4554, "63146237");
182 p_result->get_cur_app_val.num_attr = AVRC_MAX_APP_ATTR_SIZE;
183 }
184
185 p_u8 = p_result->get_cur_app_val.attrs;
186 for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
187 /* only report the valid player app attributes */
188 if (AVRC_IsValidPlayerAttr(*p)) p_u8[yy++] = *p;
189 p++;
190 }
191 p_result->get_cur_app_val.num_attr = yy;
192 if (yy == 0) {
193 status = AVRC_STS_BAD_PARAM;
194 }
195 break;
196
197 case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
198 if (len == 0) return AVRC_STS_INTERNAL_ERR;
199 BE_STREAM_TO_UINT8(p_result->set_app_val.num_val, p);
200 size_needed = sizeof(tAVRC_APP_SETTING);
201 if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
202 p_result->set_app_val.p_vals = (tAVRC_APP_SETTING*)p_buf;
203 p_app_set = p_result->set_app_val.p_vals;
204 for (xx = 0;
205 ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed));
206 xx++) {
207 p_app_set[xx].attr_id = *p++;
208 p_app_set[xx].attr_val = *p++;
209 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id,
210 p_app_set[xx].attr_val))
211 status = AVRC_STS_BAD_PARAM;
212 }
213 if (xx != p_result->set_app_val.num_val) {
214 AVRC_TRACE_ERROR(
215 "%s AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig "
216 "num_val:%d",
217 __func__, xx, p_result->set_app_val.num_val);
218 p_result->set_app_val.num_val = xx;
219 }
220 } else {
221 AVRC_TRACE_ERROR(
222 "%s AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len",
223 __func__);
224 status = AVRC_STS_INTERNAL_ERR;
225 }
226 break;
227
228 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
229 if (len < 3)
230 return AVRC_STS_INTERNAL_ERR;
231 else {
232 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.attr_id, p);
233 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
234 status = AVRC_STS_BAD_PARAM;
235 else {
236 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.num_val, p);
237 if ((len - 2 /* attr_id & num_val */) !=
238 p_result->get_app_val_txt.num_val)
239 status = AVRC_STS_INTERNAL_ERR;
240 else {
241 if (p_result->get_app_val_txt.num_val > AVRC_MAX_APP_ATTR_SIZE) {
242 android_errorWriteLog(0x534e4554, "63146237");
243 p_result->get_app_val_txt.num_val = AVRC_MAX_APP_ATTR_SIZE;
244 }
245
246 p_u8 = p_result->get_app_val_txt.vals;
247 for (xx = 0; xx < p_result->get_app_val_txt.num_val; xx++) {
248 p_u8[xx] = *p++;
249 if (!avrc_is_valid_player_attrib_value(
250 p_result->get_app_val_txt.attr_id, p_u8[xx])) {
251 status = AVRC_STS_BAD_PARAM;
252 break;
253 }
254 }
255 }
256 }
257 }
258 break;
259
260 case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
261 if (len < 3)
262 return AVRC_STS_INTERNAL_ERR;
263 else {
264 BE_STREAM_TO_UINT8(p_result->inform_charset.num_id, p);
265 if ((len - 1 /* num_id */) != p_result->inform_charset.num_id * 2)
266 status = AVRC_STS_INTERNAL_ERR;
267 else {
268 p_u16 = p_result->inform_charset.charsets;
269 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE)
270 p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
271 for (xx = 0; xx < p_result->inform_charset.num_id; xx++) {
272 BE_STREAM_TO_UINT16(p_u16[xx], p);
273 }
274 }
275 }
276 break;
277
278 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
279 if (len != 1)
280 return AVRC_STS_INTERNAL_ERR;
281 else {
282 p_result->inform_battery_status.battery_status = *p++;
283 if (!AVRC_IS_VALID_BATTERY_STATUS(
284 p_result->inform_battery_status.battery_status))
285 status = AVRC_STS_BAD_PARAM;
286 }
287 break;
288
289 case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
290 if (len < 9) /* UID/8 and num_attr/1 */
291 return AVRC_STS_INTERNAL_ERR;
292 else {
293 BE_STREAM_TO_UINT32(u32, p);
294 BE_STREAM_TO_UINT32(u32_2, p);
295 if (u32 == 0 && u32_2 == 0) {
296 BE_STREAM_TO_UINT8(p_result->get_elem_attrs.num_attr, p);
297 if ((len - 9 /* UID/8 and num_attr/1 */) !=
298 (p_result->get_elem_attrs.num_attr * 4))
299 status = AVRC_STS_INTERNAL_ERR;
300 else {
301 p_u32 = p_result->get_elem_attrs.attrs;
302 if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE)
303 p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
304 for (xx = 0; xx < p_result->get_elem_attrs.num_attr; xx++) {
305 BE_STREAM_TO_UINT32(p_u32[xx], p);
306 }
307 }
308 } else
309 status = AVRC_STS_NOT_FOUND;
310 }
311 break;
312
313 case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
314 /* no additional parameters */
315 if (len != 0) return AVRC_STS_INTERNAL_ERR;
316 break;
317
318 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
319 if (len != 5)
320 return AVRC_STS_INTERNAL_ERR;
321 else {
322 BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
323 if (!AVRC_IS_VALID_EVENT_ID(p_result->reg_notif.event_id)) {
324 android_errorWriteLog(0x534e4554, "168802990");
325 AVRC_TRACE_ERROR("%s: Invalid event id: %d", __func__,
326 p_result->reg_notif.event_id);
327 return AVRC_STS_BAD_PARAM;
328 }
329
330 BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
331 }
332 break;
333
334 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
335 if (len != 1)
336 return AVRC_STS_INTERNAL_ERR;
337 else
338 p_result->volume.volume = *p++;
339 break;
340
341 case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
342 if (len != 1) {
343 return AVRC_STS_INTERNAL_ERR;
344 }
345 BE_STREAM_TO_UINT8(p_result->continu.target_pdu, p);
346 break;
347
348 case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
349 if (len != 1) {
350 return AVRC_STS_INTERNAL_ERR;
351 }
352 BE_STREAM_TO_UINT8(p_result->abort.target_pdu, p);
353 break;
354
355 case AVRC_PDU_SET_ADDRESSED_PLAYER: /* 0x60 */
356 if (len != 2) {
357 AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER length is incorrect:%d",
358 len);
359 return AVRC_STS_INTERNAL_ERR;
360 }
361 BE_STREAM_TO_UINT16(p_result->addr_player.player_id, p);
362 break;
363
364 case AVRC_PDU_PLAY_ITEM: /* 0x74 */
365 case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
366 if (len != (AVRC_UID_SIZE + 3)) return AVRC_STS_INTERNAL_ERR;
367 BE_STREAM_TO_UINT8(p_result->play_item.scope, p);
368 if (p_result->play_item.scope > AVRC_SCOPE_NOW_PLAYING) {
369 status = AVRC_STS_BAD_SCOPE;
370 }
371 BE_STREAM_TO_ARRAY(p, p_result->play_item.uid, AVRC_UID_SIZE);
372 BE_STREAM_TO_UINT16(p_result->play_item.uid_counter, p);
373 break;
374
375 default:
376 status = AVRC_STS_BAD_CMD;
377 break;
378 }
379
380 return status;
381 }
382
383 /*******************************************************************************
384 *
385 * Function AVRC_Ctrl_ParsCommand
386 *
387 * Description This function is used to parse cmds received for CTRL
388 * Currently it is for SetAbsVolume and Volume Change
389 * Notification.
390 *
391 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
392 * successfully.
393 * Otherwise, the error code defined by AVRCP 1.4
394 *
395 ******************************************************************************/
AVRC_Ctrl_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result)396 tAVRC_STS AVRC_Ctrl_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result) {
397 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
398
399 if (p_msg && p_result) {
400 switch (p_msg->hdr.opcode) {
401 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
402 status = avrc_ctrl_pars_vendor_cmd(&p_msg->vendor, p_result);
403 break;
404
405 default:
406 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
407 break;
408 }
409 p_result->cmd.opcode = p_msg->hdr.opcode;
410 p_result->cmd.status = status;
411 }
412 AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
413 return status;
414 }
415
416 #define RETURN_STATUS_IF_FALSE(_status_, _b_, _msg_, ...) \
417 if (!(_b_)) { \
418 AVRC_TRACE_DEBUG(_msg_, ##__VA_ARGS__); \
419 return _status_; \
420 }
421
422 /*******************************************************************************
423 *
424 * Function avrc_pars_browsing_cmd
425 *
426 * Description This function parses the commands that go through the
427 * browsing channel
428 *
429 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
430 * successfully.
431 * Otherwise, the error code defined by AVRCP+1
432 *
433 ******************************************************************************/
avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)434 static tAVRC_STS avrc_pars_browsing_cmd(tAVRC_MSG_BROWSE* p_msg,
435 tAVRC_COMMAND* p_result, uint8_t* p_buf,
436 uint16_t buf_len) {
437 tAVRC_STS status = AVRC_STS_NO_ERROR;
438 uint8_t* p = p_msg->p_browse_data;
439 int count;
440
441 uint16_t min_len = 3;
442 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
443 "msg too short");
444
445 p_result->pdu = *p++;
446 AVRC_TRACE_DEBUG("avrc_pars_browsing_cmd() pdu:0x%x", p_result->pdu);
447 /* skip over len */
448 p += 2;
449
450 switch (p_result->pdu) {
451 case AVRC_PDU_SET_BROWSED_PLAYER: /* 0x70 */
452 min_len += 2;
453 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
454 "msg too short");
455
456 // For current implementation all players are browsable.
457 BE_STREAM_TO_UINT16(p_result->br_player.player_id, p);
458 break;
459
460 case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
461
462 min_len += 10;
463 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
464 "msg too short");
465
466 STREAM_TO_UINT8(p_result->get_items.scope, p);
467 // To be modified later here (Scope) when all browsing commands are
468 // supported
469 if (p_result->get_items.scope > AVRC_SCOPE_NOW_PLAYING) {
470 status = AVRC_STS_BAD_SCOPE;
471 }
472 BE_STREAM_TO_UINT32(p_result->get_items.start_item, p);
473 BE_STREAM_TO_UINT32(p_result->get_items.end_item, p);
474 if (p_result->get_items.start_item > p_result->get_items.end_item) {
475 status = AVRC_STS_BAD_RANGE;
476 }
477 STREAM_TO_UINT8(p_result->get_items.attr_count, p);
478 p_result->get_items.p_attr_list = NULL;
479 if (p_result->get_items.attr_count && p_buf &&
480 (p_result->get_items.attr_count != AVRC_FOLDER_ITEM_COUNT_NONE)) {
481 p_result->get_items.p_attr_list = (uint32_t*)p_buf;
482 count = p_result->get_items.attr_count;
483 if (buf_len < (count << 2))
484 p_result->get_items.attr_count = count = (buf_len >> 2);
485 for (int idx = 0; idx < count; idx++) {
486 min_len += 4;
487 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
488 (p_msg->browse_len >= min_len),
489 "msg too short");
490
491 BE_STREAM_TO_UINT32(p_result->get_items.p_attr_list[idx], p);
492 }
493 }
494 break;
495
496 case AVRC_PDU_CHANGE_PATH: /* 0x72 */
497 min_len += 11;
498 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
499 "msg too short");
500
501 BE_STREAM_TO_UINT16(p_result->chg_path.uid_counter, p);
502 BE_STREAM_TO_UINT8(p_result->chg_path.direction, p);
503 if (p_result->chg_path.direction != AVRC_DIR_UP &&
504 p_result->chg_path.direction != AVRC_DIR_DOWN) {
505 status = AVRC_STS_BAD_DIR;
506 }
507 BE_STREAM_TO_ARRAY(p, p_result->chg_path.folder_uid, AVRC_UID_SIZE);
508 break;
509
510 case AVRC_PDU_GET_ITEM_ATTRIBUTES: /* 0x73 */
511 min_len += 12;
512 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
513 "msg too short");
514
515 BE_STREAM_TO_UINT8(p_result->get_attrs.scope, p);
516
517 if (p_result->get_attrs.scope > AVRC_SCOPE_NOW_PLAYING) {
518 status = AVRC_STS_BAD_SCOPE;
519 break;
520 }
521 BE_STREAM_TO_ARRAY(p, p_result->get_attrs.uid, AVRC_UID_SIZE);
522 BE_STREAM_TO_UINT16(p_result->get_attrs.uid_counter, p);
523 BE_STREAM_TO_UINT8(p_result->get_attrs.attr_count, p);
524 p_result->get_attrs.p_attr_list = NULL;
525 if (p_result->get_attrs.attr_count && p_buf) {
526 p_result->get_attrs.p_attr_list = (uint32_t*)p_buf;
527 count = p_result->get_attrs.attr_count;
528 if (buf_len < (count << 2))
529 p_result->get_attrs.attr_count = count = (buf_len >> 2);
530 for (int idx = 0, count = 0; idx < p_result->get_attrs.attr_count;
531 idx++) {
532 min_len += 4;
533 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD,
534 (p_msg->browse_len >= min_len),
535 "msg too short");
536
537 BE_STREAM_TO_UINT32(p_result->get_attrs.p_attr_list[count], p);
538 if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(
539 p_result->get_attrs.p_attr_list[count])) {
540 count++;
541 }
542 }
543
544 if (p_result->get_attrs.attr_count != count && count == 0)
545 status = AVRC_STS_BAD_PARAM;
546 else
547 p_result->get_attrs.attr_count = count;
548 }
549 break;
550
551 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: /* 0x75 */
552 ++min_len;
553 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
554 "msg too short");
555
556 BE_STREAM_TO_UINT8(p_result->get_num_of_items.scope, p);
557 if (p_result->get_num_of_items.scope > AVRC_SCOPE_NOW_PLAYING) {
558 status = AVRC_STS_BAD_SCOPE;
559 }
560 break;
561
562 case AVRC_PDU_SEARCH: /* 0x80 */
563 min_len += 4;
564 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
565 "msg too short");
566
567 BE_STREAM_TO_UINT16(p_result->search.string.charset_id, p);
568 BE_STREAM_TO_UINT16(p_result->search.string.str_len, p);
569 p_result->search.string.p_str = p_buf;
570 if (p_buf) {
571 if (p_result->search.string.str_len > buf_len) {
572 p_result->search.string.str_len = buf_len;
573 } else {
574 android_errorWriteLog(0x534e4554, "63146237");
575 }
576 min_len += p_result->search.string.str_len;
577 RETURN_STATUS_IF_FALSE(AVRC_STS_BAD_CMD, (p_msg->browse_len >= min_len),
578 "msg too short");
579
580 BE_STREAM_TO_ARRAY(p, p_buf, p_result->search.string.str_len);
581 } else {
582 status = AVRC_STS_INTERNAL_ERR;
583 }
584 break;
585
586 default:
587 status = AVRC_STS_BAD_CMD;
588 break;
589 }
590 return status;
591 }
592
593 /*******************************************************************************
594 *
595 * Function AVRC_ParsCommand
596 *
597 * Description This function is a superset of AVRC_ParsMetadata to parse
598 * the command.
599 *
600 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
601 * successfully.
602 * Otherwise, the error code defined by AVRCP 1.4
603 *
604 ******************************************************************************/
AVRC_ParsCommand(tAVRC_MSG * p_msg,tAVRC_COMMAND * p_result,uint8_t * p_buf,uint16_t buf_len)605 tAVRC_STS AVRC_ParsCommand(tAVRC_MSG* p_msg, tAVRC_COMMAND* p_result,
606 uint8_t* p_buf, uint16_t buf_len) {
607 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
608 uint16_t id;
609
610 if (p_msg && p_result) {
611 switch (p_msg->hdr.opcode) {
612 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
613 status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
614 break;
615
616 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */
617 status = avrc_pars_pass_thru(&p_msg->pass, &id);
618 if (status == AVRC_STS_NO_ERROR) {
619 p_result->pdu = (uint8_t)id;
620 }
621 break;
622
623 case AVRC_OP_BROWSE:
624 status =
625 avrc_pars_browsing_cmd(&p_msg->browse, p_result, p_buf, buf_len);
626 break;
627
628 default:
629 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
630 break;
631 }
632 p_result->cmd.opcode = p_msg->hdr.opcode;
633 p_result->cmd.status = status;
634 }
635 AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status);
636 return status;
637 }
638