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 <base/logging.h> 19 #include <string.h> 20 21 #include "avrc_api.h" 22 #include "avrc_defs.h" 23 #include "avrc_int.h" 24 #include "bt_common.h" 25 #include "bt_utils.h" 26 #include "osi/include/osi.h" 27 28 /***************************************************************************** 29 * Global data 30 ****************************************************************************/ 31 #if (AVRC_METADATA_INCLUDED == TRUE) 32 #define AVRC_ITEM_PLAYER_IS_VALID(_p_player) \ 33 ((_p_player)->name.p_str && \ 34 ((_p_player)->major_type & AVRC_MJ_TYPE_INVALID) == 0 && \ 35 ((_p_player)->sub_type & AVRC_SUB_TYPE_INVALID) == 0 && \ 36 (((_p_player)->play_status <= AVRC_PLAYSTATE_REV_SEEK) || \ 37 ((_p_player)->play_status == AVRC_PLAYSTATE_ERROR))) 38 39 /* 17 = item_type(1) + item len(2) + min item (14) */ 40 #define AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP 17 41 42 /******************************************************************************* 43 * 44 * Function avrc_bld_get_capability_rsp 45 * 46 * Description This function builds the Get Capability response. 47 * 48 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 49 * Otherwise, the error code. 50 * 51 ******************************************************************************/ 52 static tAVRC_STS avrc_bld_get_capability_rsp(tAVRC_GET_CAPS_RSP* p_rsp, 53 BT_HDR* p_pkt) { 54 uint8_t *p_data, *p_start, *p_len, *p_count; 55 uint16_t len = 0; 56 uint8_t xx; 57 uint32_t* p_company_id; 58 uint8_t* p_event_id; 59 tAVRC_STS status = AVRC_STS_NO_ERROR; 60 61 if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) { 62 AVRC_TRACE_ERROR("%s bad parameter. p_rsp: %x", __func__, p_rsp); 63 status = AVRC_STS_BAD_PARAM; 64 return status; 65 } 66 67 AVRC_TRACE_API("%s", __func__); 68 /* get the existing length, if any, and also the num attributes */ 69 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 70 p_data = p_len = p_start + 2; /* pdu + rsvd */ 71 72 BE_STREAM_TO_UINT16(len, p_data); 73 UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id); 74 p_count = p_data; 75 76 if (len == 0) { 77 *p_count = p_rsp->count; 78 p_data++; 79 len = 2; /* move past the capability_id and count */ 80 } else { 81 p_data = p_start + p_pkt->len; 82 *p_count += p_rsp->count; 83 } 84 85 if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) { 86 p_company_id = p_rsp->param.company_id; 87 for (xx = 0; xx < p_rsp->count; xx++) { 88 UINT24_TO_BE_STREAM(p_data, p_company_id[xx]); 89 } 90 len += p_rsp->count * 3; 91 } else { 92 p_event_id = p_rsp->param.event_id; 93 *p_count = 0; 94 for (xx = 0; xx < p_rsp->count; xx++) { 95 if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) { 96 (*p_count)++; 97 UINT8_TO_BE_STREAM(p_data, p_event_id[xx]); 98 } 99 } 100 len += (*p_count); 101 } 102 UINT16_TO_BE_STREAM(p_len, len); 103 p_pkt->len = (p_data - p_start); 104 status = AVRC_STS_NO_ERROR; 105 106 return status; 107 } 108 109 /******************************************************************************* 110 * 111 * Function avrc_bld_list_app_settings_attr_rsp 112 * 113 * Description This function builds the List Application Settings Attribute 114 * response. 115 * 116 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 117 * Otherwise, the error code. 118 * 119 ******************************************************************************/ 120 static tAVRC_STS avrc_bld_list_app_settings_attr_rsp( 121 tAVRC_LIST_APP_ATTR_RSP* p_rsp, BT_HDR* p_pkt) { 122 uint8_t *p_data, *p_start, *p_len, *p_num; 123 uint16_t len = 0; 124 uint8_t xx; 125 126 AVRC_TRACE_API("%s", __func__); 127 /* get the existing length, if any, and also the num attributes */ 128 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 129 p_data = p_len = p_start + 2; /* pdu + rsvd */ 130 131 BE_STREAM_TO_UINT16(len, p_data); 132 p_num = p_data; 133 if (len == 0) { 134 /* first time initialize the attribute count */ 135 *p_num = 0; 136 p_data++; 137 } else { 138 p_data = p_start + p_pkt->len; 139 } 140 141 for (xx = 0; xx < p_rsp->num_attr; xx++) { 142 if (AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) { 143 (*p_num)++; 144 UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]); 145 } 146 } 147 148 len = *p_num + 1; 149 UINT16_TO_BE_STREAM(p_len, len); 150 p_pkt->len = (p_data - p_start); 151 152 return AVRC_STS_NO_ERROR; 153 } 154 155 /******************************************************************************* 156 * 157 * Function avrc_bld_list_app_settings_values_rsp 158 * 159 * Description This function builds the List Application Setting Values 160 * response. 161 * 162 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 163 * Otherwise, the error code. 164 * 165 ******************************************************************************/ 166 static tAVRC_STS avrc_bld_list_app_settings_values_rsp( 167 tAVRC_LIST_APP_VALUES_RSP* p_rsp, BT_HDR* p_pkt) { 168 uint8_t *p_data, *p_start, *p_len, *p_num; 169 uint8_t xx; 170 uint16_t len; 171 172 AVRC_TRACE_API("%s", __func__); 173 174 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 175 p_data = p_len = p_start + 2; /* pdu + rsvd */ 176 177 /* get the existing length, if any, and also the num attributes */ 178 BE_STREAM_TO_UINT16(len, p_data); 179 p_num = p_data; 180 /* first time initialize the attribute count */ 181 if (len == 0) { 182 *p_num = p_rsp->num_val; 183 p_data++; 184 } else { 185 p_data = p_start + p_pkt->len; 186 *p_num += p_rsp->num_val; 187 } 188 189 for (xx = 0; xx < p_rsp->num_val; xx++) { 190 UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]); 191 } 192 193 len = *p_num + 1; 194 UINT16_TO_BE_STREAM(p_len, len); 195 p_pkt->len = (p_data - p_start); 196 return AVRC_STS_NO_ERROR; 197 } 198 199 /******************************************************************************* 200 * 201 * Function avrc_bld_get_cur_app_setting_value_rsp 202 * 203 * Description This function builds the Get Current Application Setting 204 * Value response. 205 * 206 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 207 * Otherwise, the error code. 208 * 209 ******************************************************************************/ 210 static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp( 211 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp, BT_HDR* p_pkt) { 212 uint8_t *p_data, *p_start, *p_len, *p_count; 213 uint16_t len; 214 uint8_t xx; 215 216 if (!p_rsp->p_vals) { 217 AVRC_TRACE_ERROR("%s NULL parameter", __func__); 218 return AVRC_STS_BAD_PARAM; 219 } 220 221 AVRC_TRACE_API("%s", __func__); 222 /* get the existing length, if any, and also the num attributes */ 223 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 224 p_data = p_len = p_start + 2; /* pdu + rsvd */ 225 226 BE_STREAM_TO_UINT16(len, p_data); 227 p_count = p_data; 228 if (len == 0) { 229 /* first time initialize the attribute count */ 230 *p_count = 0; 231 p_data++; 232 } else { 233 p_data = p_start + p_pkt->len; 234 } 235 236 for (xx = 0; xx < p_rsp->num_val; xx++) { 237 if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, 238 p_rsp->p_vals[xx].attr_val)) { 239 (*p_count)++; 240 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id); 241 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val); 242 } 243 } 244 len = ((*p_count) << 1) + 1; 245 UINT16_TO_BE_STREAM(p_len, len); 246 p_pkt->len = (p_data - p_start); 247 248 return AVRC_STS_NO_ERROR; 249 } 250 251 /******************************************************************************* 252 * 253 * Function avrc_bld_set_app_setting_value_rsp 254 * 255 * Description This function builds the Set Application Setting Value 256 * response. 257 * 258 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 259 * Otherwise, the error code. 260 * 261 ******************************************************************************/ 262 static tAVRC_STS avrc_bld_set_app_setting_value_rsp( 263 UNUSED_ATTR tAVRC_RSP* p_rsp, UNUSED_ATTR BT_HDR* p_pkt) { 264 /* nothing to be added. */ 265 AVRC_TRACE_API("%s", __func__); 266 return AVRC_STS_NO_ERROR; 267 } 268 269 /******************************************************************************* 270 * 271 * Function avrc_bld_app_setting_text_rsp 272 * 273 * Description This function builds the Get Application Settings Attribute 274 * Text or Get Application Settings Value Text response. 275 * 276 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 277 * Otherwise, the error code. 278 * 279 ******************************************************************************/ 280 static tAVRC_STS avrc_bld_app_setting_text_rsp( 281 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp, BT_HDR* p_pkt) { 282 uint8_t *p_data, *p_start, *p_len, *p_count; 283 uint16_t len, len_left; 284 uint8_t xx; 285 tAVRC_STS sts = AVRC_STS_NO_ERROR; 286 uint8_t num_added = 0; 287 288 if (!p_rsp->p_attrs) { 289 AVRC_TRACE_ERROR("%s NULL parameter", __func__); 290 return AVRC_STS_BAD_PARAM; 291 } 292 /* get the existing length, if any, and also the num attributes */ 293 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 294 p_data = p_len = p_start + 2; /* pdu + rsvd */ 295 296 /* 297 * NOTE: The buffer is allocated within avrc_bld_init_rsp_buffer(), and is 298 * always of size BT_DEFAULT_BUFFER_SIZE. 299 */ 300 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset - p_pkt->len; 301 302 BE_STREAM_TO_UINT16(len, p_data); 303 p_count = p_data; 304 305 if (len == 0) { 306 *p_count = 0; 307 p_data++; 308 } else { 309 p_data = p_start + p_pkt->len; 310 } 311 312 for (xx = 0; xx < p_rsp->num_attr; xx++) { 313 if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { 314 AVRC_TRACE_ERROR("%s out of room (str_len:%d, left:%d)", __func__, xx, 315 p_rsp->p_attrs[xx].str_len, len_left); 316 p_rsp->num_attr = num_added; 317 sts = AVRC_STS_INTERNAL_ERR; 318 break; 319 } 320 if (!p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str) { 321 AVRC_TRACE_ERROR("%s NULL attr text[%d]", __func__, xx); 322 continue; 323 } 324 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); 325 UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id); 326 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len); 327 ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, 328 p_rsp->p_attrs[xx].str_len); 329 (*p_count)++; 330 num_added++; 331 } 332 len = p_data - p_count; 333 UINT16_TO_BE_STREAM(p_len, len); 334 p_pkt->len = (p_data - p_start); 335 336 return sts; 337 } 338 339 /******************************************************************************* 340 * 341 * Function avrc_bld_get_app_setting_attr_text_rsp 342 * 343 * Description This function builds the Get Application Setting Attribute 344 * Text response. 345 * 346 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 347 * Otherwise, the error code. 348 * 349 ******************************************************************************/ 350 static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp( 351 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp, BT_HDR* p_pkt) { 352 AVRC_TRACE_API("%s", __func__); 353 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt); 354 } 355 356 /******************************************************************************* 357 * 358 * Function avrc_bld_get_app_setting_value_text_rsp 359 * 360 * Description This function builds the Get Application Setting Value Text 361 * response. 362 * 363 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 364 * Otherwise, the error code. 365 * 366 ******************************************************************************/ 367 static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp( 368 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp, BT_HDR* p_pkt) { 369 AVRC_TRACE_API("%s", __func__); 370 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt); 371 } 372 373 /******************************************************************************* 374 * 375 * Function avrc_bld_inform_charset_rsp 376 * 377 * Description This function builds the Inform Displayable Character Set 378 * response. 379 * 380 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 381 * Otherwise, the error code. 382 * 383 ******************************************************************************/ 384 static tAVRC_STS avrc_bld_inform_charset_rsp(UNUSED_ATTR tAVRC_RSP* p_rsp, 385 UNUSED_ATTR BT_HDR* p_pkt) { 386 /* nothing to be added. */ 387 AVRC_TRACE_API("%s", __func__); 388 return AVRC_STS_NO_ERROR; 389 } 390 391 /******************************************************************************* 392 * 393 * Function avrc_bld_inform_battery_status_rsp 394 * 395 * Description This function builds the Inform Battery Status 396 * response. 397 * 398 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 399 * Otherwise, the error code. 400 * 401 ******************************************************************************/ 402 static tAVRC_STS avrc_bld_inform_battery_status_rsp( 403 UNUSED_ATTR tAVRC_RSP* p_rsp, UNUSED_ATTR BT_HDR* p_pkt) { 404 /* nothing to be added. */ 405 AVRC_TRACE_API("%s", __func__); 406 return AVRC_STS_NO_ERROR; 407 } 408 409 static void avrc_build_attribute_entries(int num_attrs, 410 tAVRC_ATTR_ENTRY* p_attrs, 411 int remaining_buffer_capacity, 412 uint8_t** pp_data, 413 uint8_t* p_attribute_count) { 414 AVRC_TRACE_DEBUG("%s num_attrs: %d, remaining_buffer_capacity: %d", __func__, 415 num_attrs, remaining_buffer_capacity); 416 uint8_t* p_data = *pp_data; 417 /* Fill in the Attribute ID, Character Set, Length and Values */ 418 for (int index = 0; index < num_attrs; index++) { 419 AVRC_TRACE_DEBUG("%s attr id[%d]: %d", __func__, index, 420 p_attrs[index].attr_id); 421 CHECK(AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id)); 422 if (!p_attrs[index].name.p_str) { 423 p_attrs[index].name.str_len = 0; 424 } 425 /* 8 is the size of attr_id, char set and str_len */ 426 remaining_buffer_capacity -= 8; 427 if (remaining_buffer_capacity < 0) { 428 AVRC_TRACE_WARNING( 429 "%s not enough buffer space for attr_id[%d]: %d," 430 " skipping %d attributes", 431 __func__, index, p_attrs[index].attr_id, num_attrs - index); 432 break; 433 } 434 if (remaining_buffer_capacity < p_attrs[index].name.str_len) { 435 AVRC_TRACE_WARNING( 436 "%s not enough buffer space for attr_id[%d]: %d," 437 " truncating attribute", 438 __func__, index, p_attrs[index].attr_id); 439 p_attrs[index].name.str_len = remaining_buffer_capacity; 440 remaining_buffer_capacity = 0; 441 } 442 remaining_buffer_capacity -= p_attrs[index].name.str_len; 443 UINT32_TO_BE_STREAM(p_data, p_attrs[index].attr_id); 444 UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.charset_id); 445 UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.str_len); 446 ARRAY_TO_BE_STREAM(p_data, p_attrs[index].name.p_str, 447 p_attrs[index].name.str_len); 448 (*p_attribute_count)++; 449 } 450 *pp_data = p_data; 451 AVRC_TRACE_DEBUG("%s filled attributes, remaining_buffer_capacity: %d", 452 __func__, num_attrs, remaining_buffer_capacity); 453 } 454 455 /******************************************************************************* 456 * 457 * Function avrc_bld_get_elem_attrs_rsp 458 * 459 * Description This function builds the Get Element Attributes 460 * response. 461 * 462 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 463 * Otherwise, the error code. 464 * 465 ******************************************************************************/ 466 static tAVRC_STS avrc_bld_get_elem_attrs_rsp(tAVRC_GET_ATTRS_RSP* p_rsp, 467 BT_HDR* p_pkt) { 468 AVRC_TRACE_API("%s", __func__); 469 if (!p_rsp->p_attrs) { 470 AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); 471 return AVRC_STS_BAD_PARAM; 472 } 473 /* Figure out how much we have left in current buffer */ 474 int remaining_buffer_capacity = 475 BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; 476 if (remaining_buffer_capacity < 5) { 477 AVRC_TRACE_ERROR("%s not enough buffer for packet header", 478 remaining_buffer_capacity); 479 return AVRC_STS_INTERNAL_ERR; 480 } 481 /* Get to the beginning of PDU */ 482 uint8_t* p_pdu_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 483 /* Skip PDU ID and Reserved byte to get pointer to Parameter Length */ 484 uint8_t *p_data, *p_parameter_len; 485 p_data = p_parameter_len = p_pdu_start + 2; 486 /* Parse parameter length */ 487 uint16_t parameter_len; 488 BE_STREAM_TO_UINT16(parameter_len, p_data); 489 /* Get pointer to Attribute Count */ 490 uint8_t* p_attribute_count = p_data; 491 /* Initialize field values when Parameter Length is 0 */ 492 if (parameter_len == 0) { 493 *p_attribute_count = 0; 494 p_data++; 495 } else { 496 // TODO: Why do we need this case? 497 p_data = p_pdu_start + p_pkt->len; 498 } 499 remaining_buffer_capacity -= p_data - p_pdu_start; 500 ; 501 if (remaining_buffer_capacity < 0) { 502 AVRC_TRACE_ERROR("%s not enough buffer capacity for response"); 503 return AVRC_STS_BAD_PARAM; 504 } 505 /* Fill in the Attribute ID, Character Set, Length and Values */ 506 avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, 507 remaining_buffer_capacity, &p_data, 508 p_attribute_count); 509 parameter_len = p_data - p_attribute_count; 510 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); 511 p_pkt->len = (p_data - p_pdu_start); 512 return AVRC_STS_NO_ERROR; 513 } 514 515 /******************************************************************************* 516 * 517 * Function avrc_bld_get_play_status_rsp 518 * 519 * Description This function builds the Get Play Status 520 * response. 521 * 522 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 523 * Otherwise, the error code. 524 * 525 ******************************************************************************/ 526 static tAVRC_STS avrc_bld_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP* p_rsp, 527 BT_HDR* p_pkt) { 528 uint8_t *p_data, *p_start; 529 530 AVRC_TRACE_API("%s", __func__); 531 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 532 p_data = p_start + 2; 533 534 /* add fixed lenth - song len(4) + song position(4) + status(1) */ 535 UINT16_TO_BE_STREAM(p_data, 9); 536 UINT32_TO_BE_STREAM(p_data, p_rsp->song_len); 537 UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos); 538 UINT8_TO_BE_STREAM(p_data, p_rsp->play_status); 539 p_pkt->len = (p_data - p_start); 540 541 return AVRC_STS_NO_ERROR; 542 } 543 544 /******************************************************************************* 545 * 546 * Function avrc_bld_notify_rsp 547 * 548 * Description This function builds the Notification response. 549 * 550 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 551 * Otherwise, the error code. 552 * 553 ******************************************************************************/ 554 static tAVRC_STS avrc_bld_notify_rsp(tAVRC_REG_NOTIF_RSP* p_rsp, 555 BT_HDR* p_pkt) { 556 uint8_t *p_data, *p_start; 557 uint8_t* p_len; 558 uint16_t len = 0; 559 uint8_t xx; 560 tAVRC_STS status = AVRC_STS_NO_ERROR; 561 562 AVRC_TRACE_API("%s event_id %d", __func__, p_rsp->event_id); 563 564 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 565 p_data = p_len = p_start + 2; /* pdu + rsvd */ 566 p_data += 2; 567 568 UINT8_TO_BE_STREAM(p_data, p_rsp->event_id); 569 switch (p_rsp->event_id) { 570 case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */ 571 /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always true */ 572 if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) || 573 (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR)) { 574 UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status); 575 len = 2; 576 } else { 577 AVRC_TRACE_ERROR("%s bad play state", __func__); 578 status = AVRC_STS_BAD_PARAM; 579 } 580 break; 581 582 case AVRC_EVT_TRACK_CHANGE: /* 0x02 */ 583 ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE); 584 len = (uint8_t)(AVRC_UID_SIZE + 1); 585 break; 586 587 case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */ 588 case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */ 589 case AVRC_EVT_NOW_PLAYING_CHANGE: /* 0x09 */ 590 case AVRC_EVT_AVAL_PLAYERS_CHANGE: /* 0x0a */ 591 len = 1; 592 break; 593 594 case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */ 595 UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos); 596 len = 5; 597 break; 598 599 case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */ 600 if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) { 601 UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status); 602 len = 2; 603 } else { 604 AVRC_TRACE_ERROR("%s bad battery status", __func__); 605 status = AVRC_STS_BAD_PARAM; 606 } 607 break; 608 609 case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */ 610 if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) { 611 UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status); 612 len = 2; 613 } else { 614 AVRC_TRACE_ERROR("%s bad system status", __func__); 615 status = AVRC_STS_BAD_PARAM; 616 } 617 break; 618 619 case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */ 620 if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) 621 p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS; 622 623 if (p_rsp->param.player_setting.num_attr > 0) { 624 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr); 625 len = 2; 626 for (xx = 0; xx < p_rsp->param.player_setting.num_attr; xx++) { 627 if (avrc_is_valid_player_attrib_value( 628 p_rsp->param.player_setting.attr_id[xx], 629 p_rsp->param.player_setting.attr_value[xx])) { 630 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]); 631 UINT8_TO_BE_STREAM(p_data, 632 p_rsp->param.player_setting.attr_value[xx]); 633 } else { 634 AVRC_TRACE_ERROR("%s bad player app seeting attribute or value", 635 __func__); 636 status = AVRC_STS_BAD_PARAM; 637 break; 638 } 639 len += 2; 640 } 641 } else 642 status = AVRC_STS_BAD_PARAM; 643 break; 644 645 case AVRC_EVT_VOLUME_CHANGE: /* 0x0d */ 646 len = 2; 647 UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume)); 648 break; 649 650 case AVRC_EVT_ADDR_PLAYER_CHANGE: /* 0x0b */ 651 UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.player_id); 652 UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.uid_counter); 653 len = 5; 654 break; 655 656 case AVRC_EVT_UIDS_CHANGE: /* 0x0c */ 657 UINT16_TO_BE_STREAM(p_data, p_rsp->param.uid_counter); /* uid counter */ 658 len = 3; 659 break; 660 661 default: 662 status = AVRC_STS_BAD_PARAM; 663 AVRC_TRACE_ERROR("%s unknown event_id", __func__); 664 } 665 666 UINT16_TO_BE_STREAM(p_len, len); 667 p_pkt->len = (p_data - p_start); 668 669 return status; 670 } 671 672 /******************************************************************************* 673 * 674 * Function avrc_bld_next_rsp 675 * 676 * Description This function builds the Request Continue or Abort 677 * response. 678 * 679 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 680 * Otherwise, the error code. 681 * 682 ******************************************************************************/ 683 static tAVRC_STS avrc_bld_next_rsp(tAVRC_NEXT_RSP* p_rsp, BT_HDR* p_pkt) { 684 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 685 uint8_t* p_data = (p_start + 2); /* Skip the pdu and reserved bits */ 686 687 UINT16_TO_BE_STREAM(p_data, 0x0001); /* only one attribute to be sent */ 688 UINT8_TO_BE_STREAM(p_data, p_rsp->target_pdu); 689 690 AVRC_TRACE_API("%s: target_pdu: 0x%02x", __func__, p_rsp->target_pdu); 691 return AVRC_STS_NO_ERROR; 692 } 693 694 /***************************************************************************** 695 * 696 * Function avrc_bld_set_absolute_volume_rsp 697 * 698 * Description This function builds the set absolute volume response 699 * 700 * Returns AVRC_STS_NO_ERROR, if the response is build successfully 701 * 702 *****************************************************************************/ 703 static tAVRC_STS avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol, 704 BT_HDR* p_pkt) { 705 AVRC_TRACE_API("%s", __func__); 706 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 707 /* To calculate length */ 708 uint8_t* p_data = p_start + 2; 709 /* add fixed lenth status(1) */ 710 UINT16_TO_BE_STREAM(p_data, 1); 711 UINT8_TO_BE_STREAM(p_data, abs_vol); 712 p_pkt->len = (p_data - p_start); 713 return AVRC_STS_NO_ERROR; 714 } 715 716 /******************************************************************************* 717 * 718 * Function avrc_bld_group_navigation_rsp 719 * 720 * Description This function builds the Group Navigation 721 * response. 722 * 723 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 724 * Otherwise, the error code. 725 * 726 ******************************************************************************/ 727 tAVRC_STS avrc_bld_group_navigation_rsp(uint16_t navi_id, BT_HDR* p_pkt) { 728 if (!AVRC_IS_VALID_GROUP(navi_id)) { 729 AVRC_TRACE_ERROR("%s bad navigation op id: %d", __func__, navi_id); 730 return AVRC_STS_BAD_PARAM; 731 } 732 AVRC_TRACE_API("%s", __func__); 733 uint8_t* p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 734 UINT16_TO_BE_STREAM(p_data, navi_id); 735 p_pkt->len = 2; 736 return AVRC_STS_NO_ERROR; 737 } 738 739 /******************************************************************************* 740 * 741 * Function avrc_bld_rejected_rsp 742 * 743 * Description This function builds the General Response response. 744 * 745 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 746 * 747 ******************************************************************************/ 748 static tAVRC_STS avrc_bld_rejected_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) { 749 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 750 uint8_t* p_data; 751 uint8_t opcode = p_rsp->opcode; 752 753 AVRC_TRACE_API("%s: status=%d, pdu:x%x, opcode=%x", __func__, p_rsp->status, 754 p_rsp->pdu, opcode); 755 756 if (opcode == AVRC_OP_BROWSE) { 757 p_data = p_start + 1; 758 if ((AVRC_PDU_INVALID == *p_start) || 759 (avrc_opcode_from_pdu(*p_start) != AVRC_OP_BROWSE)) { 760 /* if invalid or the given opcode is not recognized as a browsing command 761 * opcode, */ 762 /* use general reject command */ 763 *p_start = AVRC_PDU_GENERAL_REJECT; 764 } 765 } else { 766 p_data = p_start + 2; 767 } 768 AVRC_TRACE_DEBUG("%s pdu:x%x, Opcode:%x", __func__, *p_start, opcode); 769 UINT16_TO_BE_STREAM(p_data, 1); 770 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 771 p_pkt->len = p_data - p_start; 772 return AVRC_STS_NO_ERROR; 773 } 774 775 /***************************************************************************** 776 * the following commands are introduced in AVRCP 1.4 777 ****************************************************************************/ 778 779 /******************************************************************************* 780 * 781 * Function avrc_bld_ctrl_status_rsp 782 * 783 * Description This function builds the responses with a uint8_t parameter. 784 * 785 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 786 * Otherwise, the error code. 787 * 788 ******************************************************************************/ 789 static tAVRC_STS avrc_bld_ctrl_status_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) { 790 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 791 AVRC_TRACE_DEBUG("pdu:x%x", *p_start); 792 793 /* To calculate length */ 794 uint8_t* p_data = p_start + 2; /* pdu + rsvd */ 795 796 /* add fixed lenth - status(1) */ 797 UINT16_TO_BE_STREAM(p_data, 1); 798 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 799 p_pkt->len = (p_data - p_start); 800 return AVRC_STS_NO_ERROR; 801 } 802 803 /******************************************************************************* 804 * 805 * Function avrc_bld_set_addr_player_rsp 806 * 807 * Description This function builds the Set Addresses Player response. 808 * 809 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 810 * Otherwise, the error code. 811 * 812 ******************************************************************************/ 813 static tAVRC_STS avrc_bld_set_addr_player_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) { 814 AVRC_TRACE_API("%s", __func__); 815 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt); 816 } 817 818 /******************************************************************************* 819 * 820 * Function avrc_bld_set_browsed_player_rsp 821 * 822 * Description This function builds the Set Browsed Player response. 823 * 824 * This message goes through the Browsing channel 825 * 826 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 827 * Otherwise, the error code. 828 * 829 ******************************************************************************/ 830 static tAVRC_STS avrc_bld_set_browsed_player_rsp(tAVRC_SET_BR_PLAYER_RSP* p_rsp, 831 BT_HDR* p_pkt) { 832 uint8_t *p_data, *p_start; 833 uint8_t* p_len; 834 uint16_t len; 835 tAVRC_NAME* p_folders = p_rsp->p_folders; 836 uint16_t len_left; 837 uint8_t* p_folder_depth; 838 uint16_t mtu; 839 840 /* make sure the given buffer can accomodate this response */ 841 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE; 842 p_data = (uint8_t*)(p_pkt + 1); 843 BE_STREAM_TO_UINT16(mtu, p_data); 844 if (len_left > mtu) { 845 len_left = mtu; 846 } 847 len_left = len_left - p_pkt->offset - p_pkt->len; 848 AVRC_TRACE_DEBUG("len_left:%d, mtu:%d ", len_left, mtu); 849 850 /* get the existing length, if any, and also the num attributes */ 851 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 852 p_data = p_len = p_start + 1; /* pdu */ 853 854 /* the existing len */ 855 BE_STREAM_TO_UINT16(len, p_data); 856 /* find the position to add the folder depth. 857 * 9 is sizeof (status + uid_counter + num_items + charset_id) */ 858 p_folder_depth = p_data + 9; 859 if (len == 0) { 860 /* first time initialize the attribute count */ 861 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 862 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); 863 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); 864 UINT16_TO_BE_STREAM(p_data, p_rsp->charset_id); 865 *p_folder_depth = 0; 866 p_data++; 867 len = 10; 868 /* assuming that we would never use a buffer that is too small for headers 869 */ 870 len_left -= 12; 871 } else { 872 p_data = p_start + p_pkt->len; 873 } 874 875 for (uint8_t xx = 0; 876 (xx < p_rsp->folder_depth) && (len_left > (p_folders[xx].str_len + 2)); 877 xx++) { 878 (*p_folder_depth)++; 879 UINT16_TO_BE_STREAM(p_data, p_folders[xx].str_len); 880 ARRAY_TO_BE_STREAM(p_data, p_folders[xx].p_str, p_folders[xx].str_len); 881 len += (p_folders[xx].str_len + 2); 882 } 883 UINT16_TO_BE_STREAM(p_len, len); 884 p_pkt->len = (p_data - p_start); 885 return AVRC_STS_NO_ERROR; 886 } 887 888 /******************************************************************************* 889 * 890 * Function avrc_bld_get_folder_items_rsp 891 * 892 * Description This function builds the Get Folder Items response. 893 * The error code is returned in *p_status. 894 * AVRC_STS_INTERNAL_ERR means no buffers. 895 * Try again later or with smaller item_count 896 * 897 * This message goes through the Browsing channel 898 * 899 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 900 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have 901 * enough room 902 * Otherwise, the error code. 903 * 904 ******************************************************************************/ 905 static tAVRC_STS avrc_bld_get_folder_items_rsp(tAVRC_GET_ITEMS_RSP* p_rsp, 906 BT_HDR* p_pkt) { 907 uint8_t *p_data, *p_start; 908 uint8_t *p_len, xx; 909 uint16_t len; 910 uint16_t item_len; 911 uint8_t *p_item_len, yy; 912 tAVRC_ITEM_PLAYER* p_player; 913 tAVRC_ITEM_FOLDER* p_folder; 914 tAVRC_ITEM_MEDIA* p_media; 915 tAVRC_ATTR_ENTRY* p_attr; 916 tAVRC_ITEM* p_item_list = p_rsp->p_item_list; 917 tAVRC_STS status = AVRC_STS_NO_ERROR; 918 uint16_t len_left; 919 uint8_t *p_num, *p; 920 uint8_t *p_item_start, *p_attr_count; 921 uint16_t item_count; 922 uint16_t mtu; 923 bool multi_items_add_fail = false; 924 AVRC_TRACE_API("%s", __func__); 925 926 /* make sure the given buffer can accomodate this response */ 927 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE; 928 p = (uint8_t*)(p_pkt + 1); 929 BE_STREAM_TO_UINT16(mtu, p); 930 if (len_left > mtu) len_left = mtu; 931 len_left = len_left - p_pkt->offset - p_pkt->len; 932 933 /* get the existing length, if any, and also the num attributes */ 934 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 935 p_data = p_len = p_start + 1; /* pdu */ 936 937 /* the existing len */ 938 BE_STREAM_TO_UINT16(len, p_data); 939 p_num = p_data + 3; 940 if (len == 0) { 941 /* first time initialize the attribute count */ 942 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 943 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); 944 item_count = 0; 945 p_data += 2; 946 len = 5; 947 len_left -= 5; 948 } else { 949 p_data = p_start + p_pkt->len; 950 p = p_num; 951 BE_STREAM_TO_UINT16(item_count, p); 952 } 953 AVRC_TRACE_DEBUG("len:%d, len_left:%d, num:%d", len, len_left, item_count); 954 955 /* min len required = item_type(1) + item len(2) + min item (14) = 17 */ 956 for (xx = 0; 957 xx < p_rsp->item_count && len_left > AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP && 958 multi_items_add_fail == false; 959 xx++) { 960 p_item_start = p_data; 961 UINT8_TO_BE_STREAM(p_data, p_item_list[xx].item_type); 962 /* variable item lenth - save the location to add length */ 963 p_item_len = p_data; 964 p_data += 2; 965 item_len = 0; 966 len_left -= 3; /* item_type(1) + item len(2) */ 967 switch (p_item_list[xx].item_type) { 968 case AVRC_ITEM_PLAYER: 969 /* min len required: 2 + 1 + 4 + 1 + 16 + 2 + 2 = 30 + str_len */ 970 p_player = &p_item_list[xx].u.player; 971 item_len = AVRC_FEATURE_MASK_SIZE + p_player->name.str_len + 12; 972 973 if ((len_left <= item_len) || 974 AVRC_ITEM_PLAYER_IS_VALID(p_player) == false) { 975 p_data = p_item_start; 976 } else { 977 UINT16_TO_BE_STREAM(p_data, p_player->player_id); 978 UINT8_TO_BE_STREAM(p_data, p_player->major_type); 979 UINT32_TO_BE_STREAM(p_data, p_player->sub_type); 980 UINT8_TO_BE_STREAM(p_data, p_player->play_status); 981 ARRAY_TO_BE_STREAM(p_data, p_player->features, 982 AVRC_FEATURE_MASK_SIZE); 983 UINT16_TO_BE_STREAM(p_data, p_player->name.charset_id); 984 UINT16_TO_BE_STREAM(p_data, p_player->name.str_len); 985 ARRAY_TO_BE_STREAM(p_data, p_player->name.p_str, 986 p_player->name.str_len); 987 } 988 break; 989 990 case AVRC_ITEM_FOLDER: 991 /* min len required: 8 + 1 + 1 + 2 + 2 = 14 + str_len */ 992 p_folder = &p_item_list[xx].u.folder; 993 item_len = AVRC_UID_SIZE + p_folder->name.str_len + 6; 994 995 if ((len_left > item_len) && p_folder->name.p_str && 996 p_folder->type <= AVRC_FOLDER_TYPE_YEARS) { 997 ARRAY_TO_BE_STREAM(p_data, p_folder->uid, AVRC_UID_SIZE); 998 UINT8_TO_BE_STREAM(p_data, p_folder->type); 999 UINT8_TO_BE_STREAM(p_data, p_folder->playable); 1000 UINT16_TO_BE_STREAM(p_data, p_folder->name.charset_id); 1001 UINT16_TO_BE_STREAM(p_data, p_folder->name.str_len); 1002 ARRAY_TO_BE_STREAM(p_data, p_folder->name.p_str, 1003 p_folder->name.str_len); 1004 } else { 1005 p_data = p_item_start; 1006 } 1007 break; 1008 1009 case AVRC_ITEM_MEDIA: 1010 /* min len required: 8 + 1 + 2 + 2 + 1 = 14 + str_len */ 1011 p_media = &p_item_list[xx].u.media; 1012 item_len = AVRC_UID_SIZE + p_media->name.str_len + 6; 1013 1014 if ((len_left >= item_len) && p_media->name.p_str && 1015 p_media->type <= AVRC_MEDIA_TYPE_VIDEO) { 1016 ARRAY_TO_BE_STREAM(p_data, p_media->uid, AVRC_UID_SIZE); 1017 UINT8_TO_BE_STREAM(p_data, p_media->type); 1018 UINT16_TO_BE_STREAM(p_data, p_media->name.charset_id); 1019 UINT16_TO_BE_STREAM(p_data, p_media->name.str_len); 1020 ARRAY_TO_BE_STREAM(p_data, p_media->name.p_str, 1021 p_media->name.str_len); 1022 p_attr_count = p_data++; 1023 *p_attr_count = 0; 1024 len_left -= item_len; 1025 if (p_media->attr_count > 0) { 1026 p_attr = p_media->p_attr_list; 1027 for (yy = 0; yy < p_media->attr_count; yy++) { 1028 if (p_attr[yy].name.p_str && 1029 AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attr[yy].attr_id) && 1030 (len_left >= (p_attr[yy].name.str_len + 8))) { 1031 (*p_attr_count)++; 1032 UINT32_TO_BE_STREAM(p_data, p_attr[yy].attr_id); 1033 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.charset_id); 1034 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.str_len); 1035 ARRAY_TO_BE_STREAM(p_data, p_attr[yy].name.p_str, 1036 p_attr[yy].name.str_len); 1037 item_len += (p_attr[yy].name.str_len + 8); 1038 len_left -= (p_attr[yy].name.str_len + 8); 1039 } else if ((len_left < (p_attr[yy].name.str_len + 8)) && 1040 item_count > 0) { 1041 p_data = p_item_start; 1042 multi_items_add_fail = TRUE; 1043 break; 1044 } 1045 } 1046 } 1047 } else { 1048 if (len_left < item_len && item_count > 0) 1049 multi_items_add_fail = TRUE; 1050 p_data = p_item_start; 1051 } 1052 break; 1053 } /* switch item_type */ 1054 1055 if (p_item_start != p_data) { 1056 /* successfully added the item */ 1057 item_count++; 1058 /* fill in variable item lenth */ 1059 UINT16_TO_BE_STREAM(p_item_len, item_len); 1060 } else { 1061 if (multi_items_add_fail == false) { 1062 /* some item is not added properly - set an error status */ 1063 if (len_left < item_len) 1064 status = AVRC_STS_INTERNAL_ERR; 1065 else 1066 status = AVRC_STS_BAD_PARAM; 1067 } 1068 } 1069 if (multi_items_add_fail == false) { 1070 len += item_len; 1071 len += 3; /* the item_type(1) and item_len(2) */ 1072 } 1073 AVRC_TRACE_DEBUG("len:%d, len_left:%d, num:%d, item_len:%d", len, len_left, 1074 item_count, item_len); 1075 } /* for item_count */ 1076 1077 UINT16_TO_BE_STREAM(p_num, item_count); 1078 UINT16_TO_BE_STREAM(p_len, len); 1079 p_pkt->len = (p_data - p_start); 1080 1081 return status; 1082 } 1083 1084 /******************************************************************************* 1085 * 1086 * Function avrc_bld_change_path_rsp 1087 * 1088 * Description This function builds the Change Path response. 1089 * 1090 * This message goes through the Browsing channel 1091 * 1092 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1093 * Otherwise, the error code. 1094 * 1095 ******************************************************************************/ 1096 static tAVRC_STS avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP* p_rsp, 1097 BT_HDR* p_pkt) { 1098 uint8_t *p_data, *p_start; 1099 1100 /* get the existing length, if any, and also the num attributes */ 1101 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1102 p_data = p_start + 1; /* pdu */ 1103 /* add fixed length - status(1) + num_items(4) */ 1104 UINT16_TO_BE_STREAM(p_data, 5); 1105 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 1106 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); 1107 p_pkt->len = (p_data - p_start); 1108 return AVRC_STS_NO_ERROR; 1109 } 1110 1111 /******************************************************************************* 1112 * 1113 * Function avrc_bld_get_attrs_rsp 1114 * 1115 * Description This function builds the GetItemAttributes response, 1116 * 1117 * The Get Item Attributes message goes through the 1118 * Browsing channel (already specified in the |p_pkt|) 1119 * 1120 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1121 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have 1122 * enough room 1123 * Otherwise, the error code. 1124 * 1125 ******************************************************************************/ 1126 static tAVRC_STS avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP* p_rsp, 1127 BT_HDR* p_pkt) { 1128 AVRC_TRACE_API("%s", __func__); 1129 if (!p_rsp->p_attrs) { 1130 AVRC_TRACE_ERROR("%s NULL p_attrs", __func__); 1131 return AVRC_STS_BAD_PARAM; 1132 } 1133 /* Figure out how much we have left in current buffer */ 1134 int remaining_buffer_capacity = 1135 BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset; 1136 /* Get to the beginning of data section in buffer */ 1137 uint8_t* p_data = (uint8_t*)(p_pkt + 1); 1138 /* Get the MTU size that is filled in earlier */ 1139 uint16_t mtu; 1140 BE_STREAM_TO_UINT16(mtu, p_data); 1141 if (remaining_buffer_capacity > mtu) { 1142 remaining_buffer_capacity = mtu; 1143 } 1144 AVRC_TRACE_DEBUG("%s: remaining_buffer_capacity:%d, mtu:%d", __func__, 1145 remaining_buffer_capacity, mtu); 1146 if (remaining_buffer_capacity < 5) { 1147 AVRC_TRACE_ERROR("%s: not enough space for packet header, remaining:%d < 5", 1148 __func__, remaining_buffer_capacity); 1149 return AVRC_STS_INTERNAL_ERR; 1150 } 1151 /* Get to the beginning of PDU */ 1152 uint8_t* p_pdu_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1153 /* Skip PDU ID to get pointer to Parameter length */ 1154 uint8_t* p_parameter_len; 1155 p_data = p_parameter_len = p_pdu_start + 1; 1156 /* Parse existing parameter length */ 1157 uint16_t parameter_len; 1158 BE_STREAM_TO_UINT16(parameter_len, p_data); 1159 /* Skip one byte to Number of Attributes */ 1160 uint8_t* p_status = p_data++; 1161 uint8_t* p_attribute_count = p_data++; 1162 if (parameter_len == 0) { 1163 /* First time, initialize the status byte */ 1164 *p_status = p_rsp->status; 1165 if (p_rsp->status != AVRC_STS_NO_ERROR) { 1166 // TODO(siyuanh): This is a hack 1167 parameter_len = 1; 1168 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); 1169 p_pkt->len = p_status - p_pdu_start; 1170 return AVRC_STS_NO_ERROR; 1171 } 1172 *p_attribute_count = 0; 1173 } else { 1174 // TODO(siyuanh): Why do wee need this case? 1175 p_data = p_pdu_start + p_pkt->len; 1176 } 1177 remaining_buffer_capacity -= p_data - p_pdu_start; 1178 /* Fill in the Attribute ID, Character Set, Length and Values */ 1179 avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, 1180 remaining_buffer_capacity, &p_data, 1181 p_attribute_count); 1182 parameter_len = p_data - p_status; 1183 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len); 1184 p_pkt->len = p_data - p_pdu_start; 1185 return AVRC_STS_NO_ERROR; 1186 } 1187 1188 /******************************************************************************* 1189 * 1190 * Function avrc_bld_get_num_of_item_rsp 1191 * 1192 * Description This function builds the Get Total Number of Items response. 1193 * 1194 * This message goes through the Browsing channel 1195 * 1196 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1197 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have 1198 * enough room 1199 * Otherwise, the error code. 1200 * 1201 ******************************************************************************/ 1202 static tAVRC_STS avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP* p_rsp, 1203 BT_HDR* p_pkt) { 1204 uint8_t *p_data, *p_start, *p_len; 1205 1206 AVRC_TRACE_API("%s", __func__); 1207 /* get the existing length, if any, and also the num attributes */ 1208 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1209 p_data = p_len = p_start + 1; /* pdu */ 1210 1211 if (p_rsp->status == AVRC_STS_NO_ERROR) { 1212 /* add fixed lenth - status(1) + uid_counter(2) + num_items(4) */ 1213 UINT16_TO_BE_STREAM(p_data, 7); 1214 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 1215 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); 1216 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); 1217 p_pkt->len = (p_data - p_start); 1218 return AVRC_STS_NO_ERROR; 1219 } else { 1220 /* add fixed lenth - status(1) */ 1221 UINT16_TO_BE_STREAM(p_data, 7); 1222 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 1223 p_pkt->len = (p_data - p_start); 1224 return p_rsp->status; 1225 } 1226 } 1227 1228 /******************************************************************************* 1229 * 1230 * Function avrc_bld_search_rsp 1231 * 1232 * Description This function builds the Search response. 1233 * 1234 * This message goes through the Browsing channel 1235 * 1236 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1237 * Otherwise, the error code. 1238 * 1239 ******************************************************************************/ 1240 static tAVRC_STS avrc_bld_search_rsp(tAVRC_SEARCH_RSP* p_rsp, BT_HDR* p_pkt) { 1241 uint8_t *p_data, *p_start, *p_len; 1242 1243 AVRC_TRACE_API("%s", __func__); 1244 /* get the existing length, if any, and also the num attributes */ 1245 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1246 p_data = p_len = p_start + 1; /* pdu */ 1247 1248 /* add fixed lenth - status(1) + uid_counter(2) + num_items(4) */ 1249 UINT16_TO_BE_STREAM(p_data, 7); 1250 UINT8_TO_BE_STREAM(p_data, p_rsp->status); 1251 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter); 1252 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items); 1253 p_pkt->len = (p_data - p_start); 1254 return AVRC_STS_NO_ERROR; 1255 } 1256 1257 /******************************************************************************* 1258 * 1259 * Function avrc_bld_play_item_rsp 1260 * 1261 * Description This function builds the Play Item response. 1262 * 1263 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1264 * Otherwise, the error code. 1265 * 1266 ******************************************************************************/ 1267 static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) { 1268 AVRC_TRACE_API("%s", __func__); 1269 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt); 1270 } 1271 1272 /******************************************************************************* 1273 * 1274 * Function avrc_bld_add_to_now_playing_rsp 1275 * 1276 * Description This function builds the Add to Now Playing response. 1277 * 1278 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1279 * Otherwise, the error code. 1280 * 1281 ******************************************************************************/ 1282 static tAVRC_STS avrc_bld_add_to_now_playing_rsp(tAVRC_RSP* p_rsp, 1283 BT_HDR* p_pkt) { 1284 AVRC_TRACE_API("%s", __func__); 1285 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt); 1286 } 1287 1288 /******************************************************************************* 1289 * 1290 * Function avrc_bld_init_rsp_buffer 1291 * 1292 * Description This function initializes the response buffer based on PDU 1293 * 1294 * Returns NULL, if no buffer or failure to build the message. 1295 * Otherwise, the buffer that contains the initialized message. 1296 * 1297 ******************************************************************************/ 1298 static BT_HDR* avrc_bld_init_rsp_buffer(tAVRC_RESPONSE* p_rsp) { 1299 uint16_t offset = 0; 1300 uint16_t chnl = AVCT_DATA_CTRL; 1301 uint8_t opcode = avrc_opcode_from_pdu(p_rsp->pdu); 1302 1303 AVRC_TRACE_API("%s: pdu=%x, opcode=%x/%x", __func__, p_rsp->pdu, opcode, 1304 p_rsp->rsp.opcode); 1305 if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR && 1306 avrc_is_valid_opcode(p_rsp->rsp.opcode)) { 1307 opcode = p_rsp->rsp.opcode; 1308 AVRC_TRACE_API("%s opcode=%x", __func__, opcode); 1309 } 1310 1311 switch (opcode) { 1312 case AVRC_OP_BROWSE: 1313 chnl = AVCT_DATA_BROWSE; 1314 offset = AVCT_BROWSE_OFFSET; 1315 break; 1316 1317 case AVRC_OP_PASS_THRU: 1318 offset = AVRC_MSG_PASS_THRU_OFFSET; 1319 break; 1320 1321 case AVRC_OP_VENDOR: 1322 offset = AVRC_MSG_VENDOR_OFFSET; 1323 break; 1324 } 1325 1326 /* allocate and initialize the buffer */ 1327 BT_HDR* p_pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); 1328 uint8_t *p_data, *p_start; 1329 1330 p_pkt->layer_specific = chnl; 1331 p_pkt->event = opcode; 1332 p_pkt->offset = offset; 1333 p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 1334 p_start = p_data; 1335 1336 /* pass thru - group navigation - has a two byte op_id, so dont do it here */ 1337 if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_rsp->pdu; 1338 1339 switch (opcode) { 1340 case AVRC_OP_VENDOR: 1341 /* reserved 0, packet_type 0 */ 1342 UINT8_TO_BE_STREAM(p_data, 0); 1343 /* continue to the next "case to add length */ 1344 1345 case AVRC_OP_BROWSE: 1346 /* add fixed lenth - 0 */ 1347 UINT16_TO_BE_STREAM(p_data, 0); 1348 break; 1349 } 1350 1351 p_pkt->len = (p_data - p_start); 1352 p_rsp->rsp.opcode = opcode; 1353 1354 return p_pkt; 1355 } 1356 1357 /******************************************************************************* 1358 * 1359 * Function AVRC_BldResponse 1360 * 1361 * Description This function builds the given AVRCP response to the given 1362 * buffer 1363 * 1364 * Returns AVRC_STS_NO_ERROR, if the response is built successfully 1365 * Otherwise, the error code. 1366 * 1367 ******************************************************************************/ 1368 tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp, 1369 BT_HDR** pp_pkt) { 1370 tAVRC_STS status = AVRC_STS_BAD_PARAM; 1371 BT_HDR* p_pkt; 1372 bool alloc = false; 1373 uint8_t* p; 1374 uint16_t peer_mtu; 1375 1376 if (!p_rsp || !pp_pkt) { 1377 AVRC_TRACE_API("%s Invalid parameters passed. p_rsp=%p, pp_pkt=%p", 1378 __func__, p_rsp, pp_pkt); 1379 return AVRC_STS_BAD_PARAM; 1380 } 1381 1382 if (*pp_pkt == NULL) { 1383 *pp_pkt = avrc_bld_init_rsp_buffer(p_rsp); 1384 if (*pp_pkt == NULL) { 1385 AVRC_TRACE_API("%s Failed to initialize response buffer", __func__); 1386 return AVRC_STS_INTERNAL_ERR; 1387 } 1388 1389 if ((*pp_pkt)->layer_specific == AVCT_DATA_BROWSE) { 1390 p = (uint8_t*)((*pp_pkt) + 1); 1391 peer_mtu = AVCT_GetBrowseMtu(handle) - AVCT_HDR_LEN_SINGLE; 1392 UINT16_TO_BE_STREAM(p, peer_mtu); 1393 } 1394 1395 alloc = true; 1396 } 1397 status = AVRC_STS_NO_ERROR; 1398 p_pkt = *pp_pkt; 1399 1400 AVRC_TRACE_API("%s pdu=%x status=%x", __func__, p_rsp->rsp.pdu, 1401 p_rsp->rsp.status); 1402 if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) { 1403 return (avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt)); 1404 } 1405 1406 switch (p_rsp->pdu) { 1407 case AVRC_PDU_NEXT_GROUP: 1408 case AVRC_PDU_PREV_GROUP: 1409 status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt); 1410 break; 1411 1412 case AVRC_PDU_GET_CAPABILITIES: 1413 status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt); 1414 break; 1415 1416 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 1417 status = 1418 avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt); 1419 break; 1420 1421 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 1422 status = 1423 avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt); 1424 break; 1425 1426 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: 1427 status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, 1428 p_pkt); 1429 break; 1430 1431 case AVRC_PDU_SET_PLAYER_APP_VALUE: 1432 status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt); 1433 break; 1434 1435 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: 1436 status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, 1437 p_pkt); 1438 break; 1439 1440 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: 1441 status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, 1442 p_pkt); 1443 break; 1444 1445 case AVRC_PDU_INFORM_DISPLAY_CHARSET: 1446 status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt); 1447 break; 1448 1449 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: 1450 status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, 1451 p_pkt); 1452 break; 1453 1454 case AVRC_PDU_GET_ELEMENT_ATTR: 1455 status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt); 1456 break; 1457 1458 case AVRC_PDU_GET_PLAY_STATUS: 1459 status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt); 1460 break; 1461 1462 case AVRC_PDU_REGISTER_NOTIFICATION: 1463 status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt); 1464 break; 1465 1466 case AVRC_PDU_REQUEST_CONTINUATION_RSP: 1467 status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt); 1468 break; 1469 1470 case AVRC_PDU_ABORT_CONTINUATION_RSP: 1471 status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt); 1472 break; 1473 1474 case AVRC_PDU_SET_ADDRESSED_PLAYER: 1475 status = avrc_bld_set_addr_player_rsp(&p_rsp->addr_player, p_pkt); 1476 break; 1477 1478 case AVRC_PDU_PLAY_ITEM: 1479 status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt); 1480 break; 1481 1482 case AVRC_PDU_SET_ABSOLUTE_VOLUME: 1483 status = avrc_bld_set_absolute_volume_rsp(p_rsp->volume.volume, p_pkt); 1484 break; 1485 1486 case AVRC_PDU_ADD_TO_NOW_PLAYING: 1487 status = avrc_bld_add_to_now_playing_rsp(&p_rsp->add_to_play, p_pkt); 1488 break; 1489 1490 case AVRC_PDU_SET_BROWSED_PLAYER: 1491 status = avrc_bld_set_browsed_player_rsp(&p_rsp->br_player, p_pkt); 1492 break; 1493 1494 case AVRC_PDU_GET_FOLDER_ITEMS: 1495 status = avrc_bld_get_folder_items_rsp(&p_rsp->get_items, p_pkt); 1496 break; 1497 1498 case AVRC_PDU_CHANGE_PATH: 1499 status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt); 1500 break; 1501 1502 case AVRC_PDU_GET_ITEM_ATTRIBUTES: 1503 status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt); 1504 break; 1505 1506 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: 1507 status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt); 1508 break; 1509 1510 case AVRC_PDU_SEARCH: 1511 status = avrc_bld_search_rsp(&p_rsp->search, p_pkt); 1512 break; 1513 } 1514 1515 if (alloc && (status != AVRC_STS_NO_ERROR)) { 1516 osi_free(p_pkt); 1517 *pp_pkt = NULL; 1518 } 1519 AVRC_TRACE_API("%s returning %d", __func__, status); 1520 return status; 1521 } 1522 1523 #endif /* (AVRC_METADATA_INCLUDED == true)*/ 1524