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