1/****************************************************************************** 2 * 3 * Copyright (C) 2006-2013 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 "bt_utils.h" 25#include "osi/include/osi.h" 26 27/***************************************************************************** 28 * Global data 29 ****************************************************************************/ 30 31#if (AVRC_METADATA_INCLUDED == TRUE) 32 33/******************************************************************************* 34 * 35 * Function avrc_pars_vendor_rsp 36 * 37 * Description This function parses the vendor specific commands defined by 38 * Bluetooth SIG 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 ******************************************************************************/ 45static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, 46 tAVRC_RESPONSE* p_result) { 47 tAVRC_STS status = AVRC_STS_NO_ERROR; 48 uint8_t* p; 49 uint16_t len; 50#if (AVRC_ADV_CTRL_INCLUDED == TRUE) 51 uint8_t eventid = 0; 52#endif 53 54 /* Check the vendor data */ 55 if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR; 56 if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR; 57 58 p = p_msg->p_vendor_data; 59 BE_STREAM_TO_UINT8(p_result->pdu, p); 60 p++; /* skip the reserved/packe_type byte */ 61 BE_STREAM_TO_UINT16(len, p); 62 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x", __func__, 63 p_msg->hdr.ctype, p_result->pdu, len, len); 64 if (p_msg->hdr.ctype == AVRC_RSP_REJ) { 65 p_result->rsp.status = *p; 66 return p_result->rsp.status; 67 } 68 69 switch (p_result->pdu) { 70/* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 71/* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 72 73#if (AVRC_ADV_CTRL_INCLUDED == TRUE) 74 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */ 75 if (len != 1) 76 status = AVRC_STS_INTERNAL_ERR; 77 else { 78 BE_STREAM_TO_UINT8(p_result->volume.volume, p); 79 } 80 break; 81#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */ 82 83 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ 84#if (AVRC_ADV_CTRL_INCLUDED == TRUE) 85 BE_STREAM_TO_UINT8(eventid, p); 86 if (AVRC_EVT_VOLUME_CHANGE == eventid && 87 (AVRC_RSP_CHANGED == p_msg->hdr.ctype || 88 AVRC_RSP_INTERIM == p_msg->hdr.ctype || 89 AVRC_RSP_REJ == p_msg->hdr.ctype || 90 AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) { 91 p_result->reg_notif.status = p_msg->hdr.ctype; 92 p_result->reg_notif.event_id = eventid; 93 BE_STREAM_TO_UINT8(p_result->reg_notif.param.volume, p); 94 } 95 AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x", 96 __func__, eventid, p_result->reg_notif.param.volume); 97#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */ 98 break; 99 default: 100 status = AVRC_STS_BAD_CMD; 101 break; 102 } 103 104 return status; 105} 106 107void avrc_parse_notification_rsp(uint8_t* p_stream, 108 tAVRC_REG_NOTIF_RSP* p_rsp) { 109 BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream); 110 switch (p_rsp->event_id) { 111 case AVRC_EVT_PLAY_STATUS_CHANGE: 112 BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream); 113 break; 114 115 case AVRC_EVT_TRACK_CHANGE: 116 BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8); 117 break; 118 119 case AVRC_EVT_APP_SETTING_CHANGE: 120 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream); 121 for (int index = 0; index < p_rsp->param.player_setting.num_attr; 122 index++) { 123 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index], 124 p_stream); 125 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index], 126 p_stream); 127 } 128 break; 129 130 case AVRC_EVT_NOW_PLAYING_CHANGE: 131 break; 132 133 case AVRC_EVT_AVAL_PLAYERS_CHANGE: 134 break; 135 136 case AVRC_EVT_ADDR_PLAYER_CHANGE: 137 break; 138 139 case AVRC_EVT_UIDS_CHANGE: 140 break; 141 142 case AVRC_EVT_TRACK_REACHED_END: 143 case AVRC_EVT_TRACK_REACHED_START: 144 case AVRC_EVT_PLAY_POS_CHANGED: 145 case AVRC_EVT_BATTERY_STATUS_CHANGE: 146 case AVRC_EVT_SYSTEM_STATUS_CHANGE: 147 default: 148 break; 149 } 150} 151 152static tAVRC_STS avrc_pars_browse_rsp(tAVRC_MSG_BROWSE* p_msg, 153 tAVRC_RESPONSE* p_rsp) { 154 tAVRC_STS status = AVRC_STS_NO_ERROR; 155 uint8_t pdu; 156 157 if (p_msg->browse_len == 0) { 158 AVRC_TRACE_ERROR("%s length ", p_msg->browse_len); 159 return AVRC_STS_BAD_PARAM; 160 } 161 162 uint8_t* p = p_msg->p_browse_data; 163 164 /* read the pdu */ 165 BE_STREAM_TO_UINT8(pdu, p); 166 uint16_t pkt_len; 167 /* read the entire packet len */ 168 BE_STREAM_TO_UINT16(pkt_len, p); 169 170 AVRC_TRACE_DEBUG("%s pdu %d", __func__, pdu); 171 172 /* used to track how much we have read, if we cannot read anymore but the 173 * packet says so then we have a malformed packet. Also vice versa. */ 174 uint16_t pkt_len_read = 0; 175 176 switch (pdu) { 177 case AVRC_PDU_GET_FOLDER_ITEMS: { 178 tAVRC_GET_ITEMS_RSP* get_item_rsp = &(p_rsp->get_items); 179 /* Copy back the PDU */ 180 get_item_rsp->pdu = pdu; 181 /* read the status */ 182 BE_STREAM_TO_UINT8(get_item_rsp->status, p); 183 /* read the UID counter */ 184 BE_STREAM_TO_UINT16(get_item_rsp->uid_counter, p); 185 /* read the number of items */ 186 BE_STREAM_TO_UINT16(get_item_rsp->item_count, p); 187 pkt_len_read += 5; 188 189 AVRC_TRACE_DEBUG( 190 "%s pdu %d status %d pkt_len %d uid counter %d item count %d", 191 __func__, get_item_rsp->pdu, get_item_rsp->status, pkt_len, 192 get_item_rsp->uid_counter, get_item_rsp->item_count); 193 194 if (get_item_rsp->status != AVRC_STS_NO_ERROR) { 195 AVRC_TRACE_WARNING("%s returning error %d", __func__, 196 get_item_rsp->status); 197 return get_item_rsp->status; 198 } 199 200 /* get each of the items */ 201 get_item_rsp->p_item_list = (tAVRC_ITEM*)osi_malloc( 202 get_item_rsp->item_count * (sizeof(tAVRC_ITEM))); 203 tAVRC_ITEM* curr_item = get_item_rsp->p_item_list; 204 for (int i = 0; i < get_item_rsp->item_count; i++) { 205 BE_STREAM_TO_UINT8(curr_item->item_type, p); 206 pkt_len_read += 1; 207 AVRC_TRACE_DEBUG("%s item type %d", __func__, curr_item->item_type); 208 switch (curr_item->item_type) { 209 case AVRC_ITEM_PLAYER: { 210 /* Handle player */ 211 tAVRC_ITEM_PLAYER* player = &(curr_item->u.player); 212 uint8_t player_len; 213 BE_STREAM_TO_UINT16(player_len, p); 214 BE_STREAM_TO_UINT16(player->player_id, p); 215 BE_STREAM_TO_UINT8(player->major_type, p); 216 BE_STREAM_TO_UINT32(player->sub_type, p); 217 BE_STREAM_TO_UINT8(player->play_status, p); 218 BE_STREAM_TO_ARRAY(p, player->features, AVRC_FEATURE_MASK_SIZE); 219 pkt_len_read += (10 + AVRC_FEATURE_MASK_SIZE); 220 221 /* read str */ 222 BE_STREAM_TO_UINT16(player->name.charset_id, p); 223 BE_STREAM_TO_UINT16(player->name.str_len, p); 224 player->name.p_str = (uint8_t*)osi_malloc( 225 (player->name.str_len + 1) * sizeof(uint8_t)); 226 BE_STREAM_TO_ARRAY(p, player->name.p_str, player->name.str_len); 227 pkt_len_read += (4 + player->name.str_len); 228 AVRC_TRACE_DEBUG( 229 "%s type %d id %d mtype %d stype %d ps %d cs %d name len %d", 230 __func__, curr_item->item_type, player->player_id, 231 player->major_type, player->sub_type, player->play_status, 232 player->name.charset_id, player->name.str_len); 233 } break; 234 235 case AVRC_ITEM_FOLDER: { 236 tAVRC_ITEM_FOLDER* folder = &(curr_item->u.folder); 237 uint16_t folder_len; 238 BE_STREAM_TO_UINT16(folder_len, p); 239 240 BE_STREAM_TO_ARRAY(p, folder->uid, AVRC_UID_SIZE); 241 BE_STREAM_TO_UINT8(folder->type, p); 242 BE_STREAM_TO_UINT8(folder->playable, p); 243 pkt_len_read += (4 + AVRC_UID_SIZE); 244 245 /* read str, encoding to be handled by upper layers */ 246 BE_STREAM_TO_UINT16(folder->name.charset_id, p); 247 BE_STREAM_TO_UINT16(folder->name.str_len, p); 248 folder->name.p_str = (uint8_t*)osi_malloc( 249 (folder->name.str_len + 1) * sizeof(uint8_t)); 250 BE_STREAM_TO_ARRAY(p, folder->name.p_str, folder->name.str_len); 251 pkt_len_read += (4 + folder->name.str_len); 252 AVRC_TRACE_DEBUG("%s type %d playable %d cs %d name len %d", 253 __func__, folder->type, folder->playable, 254 folder->name.charset_id, folder->name.str_len); 255 } break; 256 257 case AVRC_ITEM_MEDIA: { 258 tAVRC_ITEM_MEDIA* media = &(curr_item->u.media); 259 uint8_t media_len; 260 BE_STREAM_TO_UINT16(media_len, p); 261 BE_STREAM_TO_ARRAY(p, media->uid, AVRC_UID_SIZE); 262 BE_STREAM_TO_UINT8(media->type, p); 263 pkt_len_read += (3 + AVRC_UID_SIZE); 264 265 /* read str, encoding to be handled by upper layers */ 266 BE_STREAM_TO_UINT16(media->name.charset_id, p); 267 BE_STREAM_TO_UINT16(media->name.str_len, p); 268 media->name.p_str = 269 (uint8_t*)osi_malloc((media->name.str_len) * sizeof(uint8_t)); 270 BE_STREAM_TO_ARRAY(p, media->name.p_str, media->name.str_len); 271 272 BE_STREAM_TO_UINT8(media->attr_count, p); 273 AVRC_TRACE_DEBUG("%s media type %d charset id %d len %d attr ct %d", 274 __func__, media->type, media->name.charset_id, 275 media->name.str_len, media->attr_count); 276 pkt_len_read += (5 + media->name.str_len); 277 278 media->p_attr_list = (tAVRC_ATTR_ENTRY*)osi_malloc( 279 media->attr_count * sizeof(tAVRC_ATTR_ENTRY)); 280 for (int jk = 0; jk < media->attr_count; jk++) { 281 tAVRC_ATTR_ENTRY* attr_entry = &(media->p_attr_list[jk]); 282 BE_STREAM_TO_UINT32(attr_entry->attr_id, p); 283 284 /* Parse the name now */ 285 BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p); 286 BE_STREAM_TO_UINT16(attr_entry->name.str_len, p); 287 attr_entry->name.p_str = (uint8_t*)osi_malloc( 288 attr_entry->name.str_len * sizeof(uint8_t)); 289 BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str, 290 attr_entry->name.str_len); 291 pkt_len_read += (8 + attr_entry->name.str_len); 292 AVRC_TRACE_DEBUG("%s media attr id %d cs %d name len %d", 293 __func__, attr_entry->attr_id, 294 attr_entry->name.charset_id, 295 attr_entry->name.str_len); 296 } 297 } break; 298 299 default: 300 AVRC_TRACE_ERROR("%s item type not handled %d", __func__, 301 curr_item->item_type); 302 return AVRC_STS_INTERNAL_ERR; 303 } 304 305 /* we check if we have overrun */ 306 if (pkt_len_read > pkt_len) { 307 AVRC_TRACE_ERROR("%s overflow in read pkt_len %d pkt_len_read %d", 308 __func__, pkt_len, pkt_len_read); 309 return AVRC_STS_BAD_CMD; 310 } 311 AVRC_TRACE_DEBUG("%s pkt_len %d pkt_len_read %d", __func__, pkt_len, 312 pkt_len_read); 313 314 /* advance to populate the next item */ 315 curr_item++; 316 } 317 break; 318 } 319 320 case AVRC_PDU_CHANGE_PATH: { 321 tAVRC_CHG_PATH_RSP* change_path_rsp = &(p_rsp->chg_path); 322 /* Copyback the PDU */ 323 change_path_rsp->pdu = pdu; 324 /* Read the status */ 325 BE_STREAM_TO_UINT8(change_path_rsp->status, p); 326 /* Read the number of items in folder */ 327 BE_STREAM_TO_UINT32(change_path_rsp->num_items, p); 328 pkt_len_read += 5; 329 330 AVRC_TRACE_DEBUG("%s pdu %d status %d item count %d", __func__, 331 change_path_rsp->pdu, change_path_rsp->status, 332 change_path_rsp->num_items); 333 break; 334 } 335 336 case AVRC_PDU_SET_BROWSED_PLAYER: { 337 tAVRC_SET_BR_PLAYER_RSP* set_br_pl_rsp = &(p_rsp->br_player); 338 /* Copyback the PDU */ 339 set_br_pl_rsp->pdu = pdu; 340 341 /* Read the status */ 342 BE_STREAM_TO_UINT8(set_br_pl_rsp->status, p); 343 344 if (set_br_pl_rsp->status != AVRC_STS_NO_ERROR) { 345 AVRC_TRACE_ERROR( 346 "%s Stopping further parsing because player not browsable sts %d", 347 __func__, set_br_pl_rsp->status); 348 break; 349 } 350 BE_STREAM_TO_UINT16(set_br_pl_rsp->uid_counter, p); 351 BE_STREAM_TO_UINT32(set_br_pl_rsp->num_items, p); 352 BE_STREAM_TO_UINT16(set_br_pl_rsp->charset_id, p); 353 BE_STREAM_TO_UINT8(set_br_pl_rsp->folder_depth, p); 354 AVRC_TRACE_DEBUG( 355 "%s AVRC_PDU_SET_BROWSED_PLAYER status %d items %d cs %d depth %d", 356 __func__, set_br_pl_rsp->status, set_br_pl_rsp->num_items, 357 set_br_pl_rsp->charset_id, set_br_pl_rsp->folder_depth); 358 pkt_len_read += 10; 359 360 set_br_pl_rsp->p_folders = (tAVRC_NAME*)osi_malloc( 361 set_br_pl_rsp->num_items * sizeof(tAVRC_NAME)); 362 363 /* Read each of the folder in the depth */ 364 for (uint32_t i = 0; i < set_br_pl_rsp->folder_depth; i++) { 365 tAVRC_NAME* folder_name = &(set_br_pl_rsp->p_folders[i]); 366 BE_STREAM_TO_UINT16(folder_name->str_len, p); 367 AVRC_TRACE_DEBUG("%s AVRC_PDU_SET_BROWSED_PLAYER item: %d len: %d", 368 __func__, i, folder_name->str_len); 369 folder_name->p_str = 370 (uint8_t*)osi_malloc((folder_name->str_len + 1) * sizeof(uint8_t)); 371 BE_STREAM_TO_ARRAY(p, folder_name->p_str, folder_name->str_len); 372 pkt_len_read += (2 + folder_name->str_len); 373 } 374 break; 375 } 376 377 default: 378 AVRC_TRACE_ERROR("%s pdu %d not handled", __func__, pdu); 379 } 380 381 if (pkt_len != pkt_len_read) { 382 AVRC_TRACE_ERROR("%s finished pkt_len %d pkt_len_read %d", __func__, 383 pkt_len, pkt_len_read); 384 return AVRC_STS_BAD_CMD; 385 } 386 return status; 387} 388 389/******************************************************************************* 390 * 391 * Function avrc_ctrl_pars_vendor_rsp 392 * 393 * Description This function parses the vendor specific commands defined by 394 * Bluetooth SIG 395 * 396 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed 397 * successfully. 398 * Otherwise, the error code defined by AVRCP 1.4 399 * 400 ******************************************************************************/ 401static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, 402 tAVRC_RESPONSE* p_result, 403 uint8_t* p_buf, uint16_t* buf_len) { 404 uint8_t* p = p_msg->p_vendor_data; 405 BE_STREAM_TO_UINT8(p_result->pdu, p); 406 p++; /* skip the reserved/packe_type byte */ 407 408 uint16_t len; 409 BE_STREAM_TO_UINT16(len, p); 410 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d", __func__, p_msg->hdr.ctype, 411 p_result->pdu, len); 412 /* Todo: Issue in handling reject, check */ 413 if (p_msg->hdr.ctype == AVRC_RSP_REJ) { 414 p_result->rsp.status = *p; 415 return p_result->rsp.status; 416 } 417 418 /* TODO: Break the big switch into functions. */ 419 switch (p_result->pdu) { 420 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 421 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 422 423 case AVRC_PDU_REGISTER_NOTIFICATION: 424 avrc_parse_notification_rsp(p, &p_result->reg_notif); 425 break; 426 427 case AVRC_PDU_GET_CAPABILITIES: 428 if (len == 0) { 429 p_result->get_caps.count = 0; 430 p_result->get_caps.capability_id = 0; 431 break; 432 } 433 BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p); 434 BE_STREAM_TO_UINT8(p_result->get_caps.count, p); 435 AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ", __func__, 436 p_result->get_caps.capability_id, 437 p_result->get_caps.count); 438 if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) { 439 for (int xx = 0; ((xx < p_result->get_caps.count) && 440 (xx < AVRC_CAP_MAX_NUM_COMP_ID)); 441 xx++) { 442 BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p); 443 } 444 } else if (p_result->get_caps.capability_id == 445 AVRC_CAP_EVENTS_SUPPORTED) { 446 for (int xx = 0; ((xx < p_result->get_caps.count) && 447 (xx < AVRC_CAP_MAX_NUM_EVT_ID)); 448 xx++) { 449 BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p); 450 } 451 } 452 break; 453 454 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 455 if (len == 0) { 456 p_result->list_app_attr.num_attr = 0; 457 break; 458 } 459 BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p); 460 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, 461 p_result->list_app_attr.num_attr); 462 for (int xx = 0; xx < p_result->list_app_attr.num_attr; xx++) { 463 BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p); 464 } 465 break; 466 467 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 468 if (len == 0) { 469 p_result->list_app_values.num_val = 0; 470 break; 471 } 472 BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p); 473 AVRC_TRACE_DEBUG("%s value count = %d ", __func__, 474 p_result->list_app_values.num_val); 475 for (int xx = 0; xx < p_result->list_app_values.num_val; xx++) { 476 BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p); 477 } 478 break; 479 480 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: { 481 if (len == 0) { 482 p_result->get_cur_app_val.num_val = 0; 483 break; 484 } 485 BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p); 486 tAVRC_APP_SETTING* app_sett = (tAVRC_APP_SETTING*)osi_malloc( 487 p_result->get_cur_app_val.num_val * sizeof(tAVRC_APP_SETTING)); 488 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, 489 p_result->get_cur_app_val.num_val); 490 for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++) { 491 BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p); 492 BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p); 493 } 494 p_result->get_cur_app_val.p_vals = app_sett; 495 } break; 496 497 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: { 498 tAVRC_APP_SETTING_TEXT* p_setting_text; 499 uint8_t num_attrs; 500 501 if (len == 0) { 502 p_result->get_app_attr_txt.num_attr = 0; 503 break; 504 } 505 BE_STREAM_TO_UINT8(num_attrs, p); 506 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, 507 p_result->get_app_attr_txt.num_attr); 508 p_result->get_app_attr_txt.num_attr = num_attrs; 509 p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc( 510 num_attrs * sizeof(tAVRC_APP_SETTING_TEXT)); 511 for (int xx = 0; xx < num_attrs; xx++) { 512 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p); 513 BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id, 514 p); 515 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p); 516 if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0) { 517 uint8_t* p_str = (uint8_t*)osi_malloc( 518 p_result->get_app_attr_txt.p_attrs[xx].str_len); 519 BE_STREAM_TO_ARRAY(p, p_str, 520 p_result->get_app_attr_txt.p_attrs[xx].str_len); 521 p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str; 522 } else { 523 p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL; 524 } 525 } 526 } break; 527 528 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: { 529 tAVRC_APP_SETTING_TEXT* p_setting_text; 530 uint8_t num_vals; 531 532 if (len == 0) { 533 p_result->get_app_val_txt.num_attr = 0; 534 break; 535 } 536 BE_STREAM_TO_UINT8(num_vals, p); 537 p_result->get_app_val_txt.num_attr = num_vals; 538 AVRC_TRACE_DEBUG("%s value count = %d ", __func__, 539 p_result->get_app_val_txt.num_attr); 540 541 p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc( 542 num_vals * sizeof(tAVRC_APP_SETTING_TEXT)); 543 for (int i = 0; i < num_vals; i++) { 544 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p); 545 BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p); 546 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p); 547 if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) { 548 uint8_t* p_str = (uint8_t*)osi_malloc( 549 p_result->get_app_val_txt.p_attrs[i].str_len); 550 BE_STREAM_TO_ARRAY(p, p_str, 551 p_result->get_app_val_txt.p_attrs[i].str_len); 552 p_result->get_app_val_txt.p_attrs[i].p_str = p_str; 553 } else { 554 p_result->get_app_val_txt.p_attrs[i].p_str = NULL; 555 } 556 } 557 } break; 558 559 case AVRC_PDU_SET_PLAYER_APP_VALUE: 560 /* nothing comes as part of this rsp */ 561 break; 562 563 case AVRC_PDU_GET_ELEMENT_ATTR: { 564 uint8_t num_attrs; 565 566 if (len <= 0) { 567 p_result->get_attrs.num_attrs = 0; 568 break; 569 } 570 BE_STREAM_TO_UINT8(num_attrs, p); 571 p_result->get_attrs.num_attrs = num_attrs; 572 if (num_attrs) { 573 tAVRC_ATTR_ENTRY* p_attrs = 574 (tAVRC_ATTR_ENTRY*)osi_malloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY)); 575 for (int i = 0; i < num_attrs; i++) { 576 BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p); 577 BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p); 578 BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p); 579 if (p_attrs[i].name.str_len > 0) { 580 p_attrs[i].name.p_str = 581 (uint8_t*)osi_malloc(p_attrs[i].name.str_len); 582 BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str, 583 p_attrs[i].name.str_len); 584 } 585 } 586 p_result->get_attrs.p_attrs = p_attrs; 587 } 588 } break; 589 590 case AVRC_PDU_GET_PLAY_STATUS: 591 if (len == 0) { 592 break; 593 } 594 BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p); 595 BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p); 596 BE_STREAM_TO_UINT8(p_result->get_play_status.status, p); 597 break; 598 599 case AVRC_PDU_SET_ADDRESSED_PLAYER: 600 if (len != 1) { 601 AVRC_TRACE_ERROR("%s pdu: %d len %d", __func__, p_result->pdu, len); 602 return AVRC_STS_BAD_CMD; 603 } 604 BE_STREAM_TO_UINT8(p_result->rsp.status, p); 605 break; 606 607 default: 608 return AVRC_STS_BAD_CMD; 609 } 610 return AVRC_STS_NO_ERROR; 611} 612 613/******************************************************************************* 614 * 615 * Function AVRC_Ctrl_ParsResponse 616 * 617 * Description This function is a parse response for AVRCP Controller. 618 * 619 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed 620 * successfully. 621 * Otherwise, the error code defined by AVRCP 1.4 622 * 623 ******************************************************************************/ 624tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result, 625 uint8_t* p_buf, uint16_t* buf_len) { 626 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 627 if (p_msg && p_result) { 628 switch (p_msg->hdr.opcode) { 629 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 630 status = 631 avrc_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf, buf_len); 632 break; 633 634 case AVRC_OP_BROWSE: /* 0xff Browse commands */ 635 status = avrc_pars_browse_rsp(&p_msg->browse, p_result); 636 break; 637 638 default: 639 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 640 break; 641 } 642 p_result->rsp.opcode = p_msg->hdr.opcode; 643 p_result->rsp.status = status; 644 } 645 return status; 646} 647 648/******************************************************************************* 649 * 650 * Function AVRC_ParsResponse 651 * 652 * Description This function is a superset of AVRC_ParsMetadata to parse 653 * the response. 654 * 655 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed 656 * successfully. 657 * Otherwise, the error code defined by AVRCP 1.4 658 * 659 ******************************************************************************/ 660tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result, 661 UNUSED_ATTR uint8_t* p_buf, 662 UNUSED_ATTR uint16_t buf_len) { 663 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 664 uint16_t id; 665 666 if (p_msg && p_result) { 667 switch (p_msg->hdr.opcode) { 668 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 669 status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result); 670 break; 671 672 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */ 673 status = avrc_pars_pass_thru(&p_msg->pass, &id); 674 if (status == AVRC_STS_NO_ERROR) { 675 p_result->pdu = (uint8_t)id; 676 } 677 break; 678 679 default: 680 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 681 break; 682 } 683 p_result->rsp.opcode = p_msg->hdr.opcode; 684 p_result->rsp.status = status; 685 } 686 return status; 687} 688#endif /* (AVRC_METADATA_INCLUDED == TRUE) */ 689