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