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