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