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