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