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