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