1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/***************************************************************************** 18 * 19 * Filename: btif_rc.cc 20 * 21 * Description: Bluetooth AVRC implementation 22 * 23 *****************************************************************************/ 24 25#define LOG_TAG "bt_btif_avrc" 26 27#include <errno.h> 28#include <fcntl.h> 29#include <pthread.h> 30#include <string.h> 31#include <time.h> 32#include <unistd.h> 33 34#include <mutex> 35 36#include <hardware/bluetooth.h> 37#include <hardware/bt_rc.h> 38 39#include "avrc_defs.h" 40#include "bdaddr.h" 41#include "bt_common.h" 42#include "bta_api.h" 43#include "bta_av_api.h" 44#include "btif_av.h" 45#include "btif_common.h" 46#include "btif_util.h" 47#include "btu.h" 48#include "device/include/interop.h" 49#include "osi/include/list.h" 50#include "osi/include/osi.h" 51#include "osi/include/properties.h" 52#define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL) 53 54/***************************************************************************** 55 * Constants & Macros 56 *****************************************************************************/ 57 58/* cod value for Headsets */ 59#define COD_AV_HEADSETS 0x0404 60/* for AVRC 1.4 need to change this */ 61#define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE 62 63#define IDX_GET_PLAY_STATUS_RSP 0 64#define IDX_LIST_APP_ATTR_RSP 1 65#define IDX_LIST_APP_VALUE_RSP 2 66#define IDX_GET_CURR_APP_VAL_RSP 3 67#define IDX_SET_APP_VAL_RSP 4 68#define IDX_GET_APP_ATTR_TXT_RSP 5 69#define IDX_GET_APP_VAL_TXT_RSP 6 70#define IDX_GET_ELEMENT_ATTR_RSP 7 71#define IDX_SET_ADDR_PLAYER_RSP 8 72#define IDX_SET_BROWSED_PLAYER_RSP 9 73#define IDX_GET_FOLDER_ITEMS_RSP 10 74#define IDX_CHG_PATH_RSP 11 75#define IDX_GET_ITEM_ATTR_RSP 12 76#define IDX_PLAY_ITEM_RSP 13 77#define IDX_GET_TOTAL_NUM_OF_ITEMS_RSP 14 78#define IDX_SEARCH_RSP 15 79#define IDX_ADD_TO_NOW_PLAYING_RSP 16 80 81/* Update MAX value whenever IDX will be changed */ 82#define MAX_CMD_QUEUE_LEN 17 83 84#define MAX_VOLUME 128 85#define MAX_LABEL 16 86#define MAX_TRANSACTIONS_PER_SESSION 16 87#define PLAY_STATUS_PLAYING 1 88#define BTIF_RC_NUM_CONN BT_RC_NUM_APP 89 90#define CHECK_RC_CONNECTED(p_dev) \ 91 do { \ 92 if ((p_dev) == NULL || (p_dev)->rc_connected == false) { \ 93 BTIF_TRACE_WARNING("%s: called when RC is not connected", __func__); \ 94 return BT_STATUS_NOT_READY; \ 95 } \ 96 } while (0) 97 98#define CHECK_BR_CONNECTED(p_dev) \ 99 do { \ 100 if ((p_dev) == NULL || (p_dev)->br_connected == false) { \ 101 BTIF_TRACE_WARNING("%s: called when BR is not connected", __func__); \ 102 return BT_STATUS_NOT_READY; \ 103 } \ 104 } while (0) 105 106/***************************************************************************** 107 * Local type definitions 108 *****************************************************************************/ 109typedef struct { 110 uint8_t bNotify; 111 uint8_t label; 112} btif_rc_reg_notifications_t; 113 114typedef struct { 115 uint8_t label; 116 uint8_t ctype; 117 bool is_rsp_pending; 118} btif_rc_cmd_ctxt_t; 119 120/* 2 second timeout to get interim response */ 121#define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000) 122#define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000) 123#define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000) 124 125typedef enum { 126 eNOT_REGISTERED, 127 eREGISTERED, 128 eINTERIM 129} btif_rc_nfn_reg_status_t; 130 131typedef struct { 132 uint8_t event_id; 133 uint8_t label; 134 btif_rc_nfn_reg_status_t status; 135} btif_rc_supported_event_t; 136 137#define BTIF_RC_STS_TIMEOUT 0xFE 138typedef struct { 139 uint8_t label; 140 uint8_t pdu_id; 141} btif_rc_status_cmd_timer_t; 142 143typedef struct { 144 uint8_t label; 145 uint8_t pdu_id; 146} btif_rc_control_cmd_timer_t; 147 148typedef struct { 149 union { 150 btif_rc_status_cmd_timer_t rc_status_cmd; 151 btif_rc_control_cmd_timer_t rc_control_cmd; 152 }; 153 BD_ADDR rc_addr; 154} btif_rc_timer_context_t; 155 156typedef struct { 157 bool query_started; 158 uint8_t num_attrs; 159 uint8_t num_ext_attrs; 160 161 uint8_t attr_index; 162 uint8_t ext_attr_index; 163 uint8_t ext_val_index; 164 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE]; 165 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE]; 166} btif_rc_player_app_settings_t; 167 168/* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single 169 * struct */ 170typedef struct { 171 bool rc_connected; 172 bool br_connected; // Browsing channel. 173 uint8_t rc_handle; 174 tBTA_AV_FEAT rc_features; 175 btrc_connection_state_t rc_state; 176 BD_ADDR rc_addr; 177 uint16_t rc_pending_play; 178 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN]; 179 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS]; 180 unsigned int rc_volume; 181 uint8_t rc_vol_label; 182 list_t* rc_supported_event_list; 183 btif_rc_player_app_settings_t rc_app_settings; 184 alarm_t* rc_play_status_timer; 185 bool rc_features_processed; 186 uint64_t rc_playing_uid; 187 bool rc_procedure_complete; 188} btif_rc_device_cb_t; 189 190typedef struct { 191 std::mutex lock; 192 btif_rc_device_cb_t rc_multi_cb[BTIF_RC_NUM_CONN]; 193} rc_cb_t; 194 195typedef struct { 196 bool in_use; 197 uint8_t lbl; 198 uint8_t handle; 199 btif_rc_timer_context_t txn_timer_context; 200 alarm_t* txn_timer; 201} rc_transaction_t; 202 203typedef struct { 204 std::recursive_mutex lbllock; 205 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION]; 206} rc_device_t; 207 208typedef struct { 209 uint8_t label; 210 BD_ADDR rc_addr; 211} rc_context_t; 212 213typedef struct { uint8_t handle; } btif_rc_handle_t; 214 215rc_device_t device; 216 217static void sleep_ms(period_ms_t timeout_ms); 218 219/* Response status code - Unknown Error - this is changed to "reserved" */ 220#define BTIF_STS_GEN_ERROR 0x06 221 222/* Utility table to map hal status codes to bta status codes for the response 223 * status */ 224static const uint8_t status_code_map[] = { 225 /* BTA_Status codes HAL_Status codes */ 226 AVRC_STS_BAD_CMD, /* BTRC_STS_BAD_CMD */ 227 AVRC_STS_BAD_PARAM, /* BTRC_STS_BAD_PARAM */ 228 AVRC_STS_NOT_FOUND, /* BTRC_STS_NOT_FOUND */ 229 AVRC_STS_INTERNAL_ERR, /* BTRC_STS_INTERNAL_ERR */ 230 AVRC_STS_NO_ERROR, /* BTRC_STS_NO_ERROR */ 231 AVRC_STS_UID_CHANGED, /* BTRC_STS_UID_CHANGED */ 232 BTIF_STS_GEN_ERROR, /* BTRC_STS_RESERVED */ 233 AVRC_STS_BAD_DIR, /* BTRC_STS_INV_DIRN */ 234 AVRC_STS_NOT_DIR, /* BTRC_STS_INV_DIRECTORY */ 235 AVRC_STS_NOT_EXIST, /* BTRC_STS_INV_ITEM */ 236 AVRC_STS_BAD_SCOPE, /* BTRC_STS_INV_SCOPE */ 237 AVRC_STS_BAD_RANGE, /* BTRC_STS_INV_RANGE */ 238 AVRC_STS_UID_IS_DIR, /* BTRC_STS_DIRECTORY */ 239 AVRC_STS_IN_USE, /* BTRC_STS_MEDIA_IN_USE */ 240 AVRC_STS_NOW_LIST_FULL, /* BTRC_STS_PLAY_LIST_FULL */ 241 AVRC_STS_SEARCH_NOT_SUP, /* BTRC_STS_SRCH_NOT_SPRTD */ 242 AVRC_STS_SEARCH_BUSY, /* BTRC_STS_SRCH_IN_PROG */ 243 AVRC_STS_BAD_PLAYER_ID, /* BTRC_STS_INV_PLAYER */ 244 AVRC_STS_PLAYER_N_BR, /* BTRC_STS_PLAY_NOT_BROW */ 245 AVRC_STS_PLAYER_N_ADDR, /* BTRC_STS_PLAY_NOT_ADDR */ 246 AVRC_STS_BAD_SEARCH_RES, /* BTRC_STS_INV_RESULTS */ 247 AVRC_STS_NO_AVAL_PLAYER, /* BTRC_STS_NO_AVBL_PLAY */ 248 AVRC_STS_ADDR_PLAYER_CHG, /* BTRC_STS_ADDR_PLAY_CHGD */ 249}; 250 251static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu, 252 uint8_t status, uint8_t opcode); 253static uint8_t opcode_from_pdu(uint8_t pdu); 254static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index, 255 uint8_t label, tBTA_AV_CODE code, 256 tAVRC_RESPONSE* pmetamsg_resp); 257static void register_volumechange(uint8_t label, btif_rc_device_cb_t* p_dev); 258static void lbl_init(); 259static void init_all_transactions(); 260static bt_status_t get_transaction(rc_transaction_t** ptransaction); 261static void release_transaction(uint8_t label); 262static rc_transaction_t* get_transaction_by_lbl(uint8_t label); 263static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg, 264 btif_rc_device_cb_t* p_dev); 265 266static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg); 267static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg); 268static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event, 269 tAVRC_COMMAND* pavrc_cmd, 270 uint8_t label, 271 btif_rc_device_cb_t* p_dev); 272static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev); 273static void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev); 274static void register_for_event_notification(btif_rc_supported_event_t* p_event, 275 btif_rc_device_cb_t* p_dev); 276static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg, 277 tAVRC_GET_CAPS_RSP* p_rsp); 278static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg, 279 tAVRC_LIST_APP_ATTR_RSP* p_rsp); 280static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg, 281 tAVRC_LIST_APP_VALUES_RSP* p_rsp); 282static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg, 283 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp); 284static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg, 285 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp); 286static void handle_app_attr_val_txt_response(tBTA_AV_META_MSG* pmeta_msg, 287 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp); 288static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg, 289 tAVRC_GET_PLAY_STATUS_RSP* p_rsp); 290static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg, 291 tAVRC_RSP* p_rsp); 292static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg, 293 tAVRC_GET_ATTRS_RSP* p_rsp); 294static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, 295 tAVRC_RSP* p_rsp); 296static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev); 297static bt_status_t get_player_app_setting_attr_text_cmd( 298 uint8_t* attrs, uint8_t num_attrs, btif_rc_device_cb_t* p_dev); 299static bt_status_t get_player_app_setting_value_text_cmd( 300 uint8_t* vals, uint8_t num_vals, btif_rc_device_cb_t* p_dev); 301static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id, 302 uint32_t event_value, 303 btif_rc_device_cb_t* p_dev); 304static bt_status_t get_element_attribute_cmd(uint8_t num_attribute, 305 uint32_t* p_attr_ids, 306 btif_rc_device_cb_t* p_dev); 307static bt_status_t getcapabilities_cmd(uint8_t cap_id, 308 btif_rc_device_cb_t* p_dev); 309static bt_status_t list_player_app_setting_attrib_cmd( 310 btif_rc_device_cb_t* p_dev); 311static bt_status_t list_player_app_setting_value_cmd( 312 uint8_t attrib_id, btif_rc_device_cb_t* p_dev); 313static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, 314 uint8_t* attrib_ids, 315 btif_rc_device_cb_t* p_dev); 316void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, 317 btrc_folder_items_t* btrc_item); 318void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, 319 btrc_folder_items_t* btrc_item); 320void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, 321 btrc_folder_items_t* btrc_item); 322static bt_status_t get_folder_items_cmd(bt_bdaddr_t* bd_addr, uint8_t scope, 323 uint8_t start_item, uint8_t num_items); 324 325static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* p_param, 326 uint8_t ctype, uint8_t label, 327 btif_rc_device_cb_t* p_dev); 328 329static void btif_rc_upstreams_rsp_evt(uint16_t event, 330 tAVRC_RESPONSE* pavrc_resp, uint8_t ctype, 331 uint8_t label, 332 btif_rc_device_cb_t* p_dev); 333 334static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev); 335static bool absolute_volume_disabled(void); 336 337/***************************************************************************** 338 * Static variables 339 *****************************************************************************/ 340static rc_cb_t btif_rc_cb; 341static btrc_callbacks_t* bt_rc_callbacks = NULL; 342static btrc_ctrl_callbacks_t* bt_rc_ctrl_callbacks = NULL; 343 344/***************************************************************************** 345 * Static functions 346 *****************************************************************************/ 347 348/***************************************************************************** 349 * Externs 350 *****************************************************************************/ 351extern bool btif_hf_call_terminated_recently(); 352extern bool check_cod(const bt_bdaddr_t* remote_bdaddr, uint32_t cod); 353 354extern fixed_queue_t* btu_general_alarm_queue; 355 356/***************************************************************************** 357 * Functions 358 *****************************************************************************/ 359static btif_rc_device_cb_t* alloc_device() { 360 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 361 if (btif_rc_cb.rc_multi_cb[idx].rc_state == 362 BTRC_CONNECTION_STATE_DISCONNECTED) { 363 return (&btif_rc_cb.rc_multi_cb[idx]); 364 } 365 } 366 return NULL; 367} 368 369static btif_rc_device_cb_t* get_connected_device(int index) { 370 BTIF_TRACE_DEBUG("%s: index: %d", __func__, index); 371 if (index > BTIF_RC_NUM_CONN) { 372 BTIF_TRACE_ERROR("%s: can't support more than %d connections", __func__, 373 BTIF_RC_NUM_CONN); 374 return NULL; 375 } 376 if (btif_rc_cb.rc_multi_cb[index].rc_state != 377 BTRC_CONNECTION_STATE_CONNECTED) { 378 BTIF_TRACE_ERROR("%s: returning NULL", __func__); 379 return NULL; 380 } 381 return (&btif_rc_cb.rc_multi_cb[index]); 382} 383 384static int get_num_connected_devices() { 385 int connected_devices = 0; 386 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 387 if (btif_rc_cb.rc_multi_cb[idx].rc_state == 388 BTRC_CONNECTION_STATE_CONNECTED) { 389 connected_devices++; 390 } 391 } 392 BTIF_TRACE_DEBUG("%s: returning connected_devices: %d", __func__, 393 connected_devices); 394 return connected_devices; 395} 396 397btif_rc_device_cb_t* btif_rc_get_device_by_bda(bt_bdaddr_t* bd_addr) { 398 BTIF_TRACE_DEBUG("%s: bd_addr: %02x-%02x-%02x-%02x-%02x-%02x", __func__, 399 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], 400 bd_addr[5]); 401 402 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 403 if ((btif_rc_cb.rc_multi_cb[idx].rc_state != 404 BTRC_CONNECTION_STATE_DISCONNECTED) && 405 (bdcmp(btif_rc_cb.rc_multi_cb[idx].rc_addr, bd_addr->address) == 0)) { 406 return (&btif_rc_cb.rc_multi_cb[idx]); 407 } 408 } 409 BTIF_TRACE_ERROR("%s: device not found, returning NULL!", __func__); 410 return NULL; 411} 412 413btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) { 414 BTIF_TRACE_DEBUG("%s: handle: 0x%x", __func__, handle); 415 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 416 if ((btif_rc_cb.rc_multi_cb[idx].rc_state != 417 BTRC_CONNECTION_STATE_DISCONNECTED) && 418 (btif_rc_cb.rc_multi_cb[idx].rc_handle == handle)) { 419 BTIF_TRACE_DEBUG("%s: btif_rc_cb.rc_multi_cb[idx].rc_handle: 0x%x", 420 __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle); 421 return (&btif_rc_cb.rc_multi_cb[idx]); 422 } 423 } 424 BTIF_TRACE_ERROR("%s: returning NULL", __func__); 425 return NULL; 426} 427 428void fill_pdu_queue(int index, uint8_t ctype, uint8_t label, bool pending, 429 btif_rc_device_cb_t* p_dev) { 430 p_dev->rc_pdu_info[index].ctype = ctype; 431 p_dev->rc_pdu_info[index].label = label; 432 p_dev->rc_pdu_info[index].is_rsp_pending = pending; 433} 434 435void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, 436 btrc_element_attr_val_t* p_attrs) { 437 for (int attr_cnt = 0; attr_cnt < num_attrs; attr_cnt++) { 438 attr_vals[attr_cnt].attr_id = p_attrs[attr_cnt].attr_id; 439 attr_vals[attr_cnt].name.charset_id = AVRC_CHARSET_ID_UTF8; 440 attr_vals[attr_cnt].name.str_len = 441 (uint16_t)strlen((char*)p_attrs[attr_cnt].text); 442 attr_vals[attr_cnt].name.p_str = p_attrs[attr_cnt].text; 443 BTIF_TRACE_DEBUG( 444 "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__, 445 (unsigned int)attr_vals[attr_cnt].attr_id, 446 attr_vals[attr_cnt].name.charset_id, attr_vals[attr_cnt].name.str_len, 447 attr_vals[attr_cnt].name.p_str); 448 } 449} 450 451void rc_cleanup_sent_cmd(void* p_data) { BTIF_TRACE_DEBUG("%s: ", __func__); } 452 453void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) { 454 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG) && 455 (!(p_dev->rc_features & BTA_AV_FEAT_RCCT) || 456 !(p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL))) { 457 return; 458 } 459 460 bt_bdaddr_t rc_addr; 461 int rc_features = 0; 462 bdcpy(rc_addr.address, p_dev->rc_addr); 463 464 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) && 465 (p_dev->rc_features & BTA_AV_FEAT_RCCT)) { 466 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME; 467 } 468 469 if ((p_dev->rc_features & BTA_AV_FEAT_METADATA) && 470 (p_dev->rc_features & BTA_AV_FEAT_VENDOR) && 471 (p_dev->rc_features_processed != true)) { 472 rc_features |= BTRC_FEAT_METADATA; 473 474 /* Mark rc features processed to avoid repeating 475 * the AVRCP procedure every time on receiving this 476 * update. 477 */ 478 p_dev->rc_features_processed = true; 479 if (btif_av_is_sink_enabled()) { 480 getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev); 481 } 482 } 483 484 /* Add browsing feature capability */ 485 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) { 486 rc_features |= BTRC_FEAT_BROWSE; 487 } 488 489 BTIF_TRACE_DEBUG("%s: Update rc features to CTRL: %d", __func__, rc_features); 490 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features); 491} 492 493void handle_rc_features(btif_rc_device_cb_t* p_dev) { 494 bt_bdaddr_t rc_addr; 495 bdcpy(rc_addr.address, p_dev->rc_addr); 496 bdstr_t addr1, addr2; 497 498 CHECK(bt_rc_callbacks); 499 500 btrc_remote_features_t rc_features = BTRC_FEAT_NONE; 501 bt_bdaddr_t avdtp_addr = btif_av_get_addr(); 502 503 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__, 504 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)), 505 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2))); 506 507 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) || 508 absolute_volume_disabled() || 509 bdcmp(avdtp_addr.address, rc_addr.address)) { 510 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL; 511 } 512 513 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) { 514 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_BROWSE); 515 } 516 517#if (AVRC_ADV_CTRL_INCLUDED == TRUE) 518 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) && 519 (p_dev->rc_features & BTA_AV_FEAT_RCTG)) { 520 rc_features = 521 (btrc_remote_features_t)(rc_features | BTRC_FEAT_ABSOLUTE_VOLUME); 522 } 523#endif 524 525 if (p_dev->rc_features & BTA_AV_FEAT_METADATA) { 526 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_METADATA); 527 } 528 529 BTIF_TRACE_DEBUG("%s: rc_features: 0x%x", __func__, rc_features); 530 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features); 531 532#if (AVRC_ADV_CTRL_INCLUDED == TRUE) 533 BTIF_TRACE_DEBUG( 534 "%s: Checking for feature flags in btif_rc_handler with label: %d", 535 __func__, p_dev->rc_vol_label); 536 // Register for volume change on connect 537 if (p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL && 538 p_dev->rc_features & BTA_AV_FEAT_RCTG) { 539 rc_transaction_t* p_transaction = NULL; 540 bt_status_t status = BT_STATUS_NOT_READY; 541 if (MAX_LABEL == p_dev->rc_vol_label) { 542 status = get_transaction(&p_transaction); 543 } else { 544 p_transaction = get_transaction_by_lbl(p_dev->rc_vol_label); 545 if (NULL != p_transaction) { 546 BTIF_TRACE_DEBUG( 547 "%s: register_volumechange already in progress for label: %d", 548 __func__, p_dev->rc_vol_label); 549 return; 550 } 551 status = get_transaction(&p_transaction); 552 } 553 if (BT_STATUS_SUCCESS == status && NULL != p_transaction) { 554 p_dev->rc_vol_label = p_transaction->lbl; 555 register_volumechange(p_dev->rc_vol_label, p_dev); 556 } 557 } 558#endif 559} 560 561/*************************************************************************** 562 * Function handle_rc_connect 563 * 564 * - Argument: tBTA_AV_RC_OPEN browse RC open data structure 565 * 566 * - Description: browse RC connection event handler 567 * 568 ***************************************************************************/ 569void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) { 570 BTIF_TRACE_DEBUG("%s: rc_handle %d status %d", __func__, 571 p_rc_br_open->rc_handle, p_rc_br_open->status); 572 btif_rc_device_cb_t* p_dev = 573 btif_rc_get_device_by_handle(p_rc_br_open->rc_handle); 574 575 if (!p_dev) { 576 BTIF_TRACE_ERROR("%s p_dev is null", __func__); 577 return; 578 } 579 580 /* check that we are already connected to this address since being connected 581 * to a browse when not connected to the control channel over AVRCP is 582 * probably not preferred anyways. */ 583 if (p_rc_br_open->status == BTA_AV_SUCCESS) { 584 bt_bdaddr_t rc_addr; 585 bdcpy(rc_addr.address, p_dev->rc_addr); 586 p_dev->br_connected = true; 587 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, true, &rc_addr); 588 } 589} 590 591/*************************************************************************** 592 * Function handle_rc_connect 593 * 594 * - Argument: tBTA_AV_RC_OPEN RC open data structure 595 * 596 * - Description: RC connection event handler 597 * 598 ***************************************************************************/ 599void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) { 600 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __func__, p_rc_open->rc_handle); 601 602 btif_rc_device_cb_t* p_dev = alloc_device(); 603 if (p_dev == NULL) { 604 BTIF_TRACE_ERROR("%s: p_dev is NULL", __func__); 605 return; 606 } 607 608 if (!(p_rc_open->status == BTA_AV_SUCCESS)) { 609 BTIF_TRACE_ERROR("%s: Connect failed with error code: %d", __func__, 610 p_rc_open->status); 611 p_dev->rc_connected = false; 612 } 613 614 // check if already some RC is connected 615 if (p_dev->rc_connected) { 616 BTIF_TRACE_ERROR( 617 "%s: Got RC OPEN in connected state, Connected RC: %d \ 618 and Current RC: %d", 619 __func__, p_dev->rc_handle, p_rc_open->rc_handle); 620 if ((p_dev->rc_handle != p_rc_open->rc_handle) && 621 (bdcmp(p_dev->rc_addr, p_rc_open->peer_addr))) { 622 BTIF_TRACE_DEBUG("%s: Got RC connected for some other handle", __func__); 623 BTA_AvCloseRc(p_rc_open->rc_handle); 624 return; 625 } 626 } 627 memcpy(p_dev->rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR)); 628 p_dev->rc_features = p_rc_open->peer_features; 629 BTIF_TRACE_DEBUG("%s: handle_rc_connect in features: 0x%x out features 0x%x", 630 __func__, p_rc_open->peer_features, p_dev->rc_features); 631 p_dev->rc_vol_label = MAX_LABEL; 632 p_dev->rc_volume = MAX_VOLUME; 633 634 p_dev->rc_connected = true; 635 p_dev->rc_handle = p_rc_open->rc_handle; 636 p_dev->rc_state = BTRC_CONNECTION_STATE_CONNECTED; 637 /* on locally initiated connection we will get remote features as part of 638 * connect */ 639 if (p_dev->rc_features != 0 && bt_rc_callbacks != NULL) { 640 handle_rc_features(p_dev); 641 } 642 643 p_dev->rc_playing_uid = RC_INVALID_TRACK_ID; 644 bt_bdaddr_t rc_addr; 645 bdcpy(rc_addr.address, p_dev->rc_addr); 646 if (bt_rc_ctrl_callbacks != NULL) { 647 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, false, &rc_addr); 648 } 649 /* report connection state if remote device is AVRCP target */ 650 handle_rc_ctrl_features(p_dev); 651} 652 653/*************************************************************************** 654 * Function handle_rc_disconnect 655 * 656 * - Argument: tBTA_AV_RC_CLOSE RC close data structure 657 * 658 * - Description: RC disconnection event handler 659 * 660 ***************************************************************************/ 661void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) { 662 btif_rc_device_cb_t* p_dev = NULL; 663 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __func__, p_rc_close->rc_handle); 664 665 p_dev = btif_rc_get_device_by_handle(p_rc_close->rc_handle); 666 if (p_dev == NULL) { 667 BTIF_TRACE_ERROR("%s: Got disconnect from invalid rc handle", __func__); 668 return; 669 } 670 671 if ((p_rc_close->rc_handle != p_dev->rc_handle) && 672 (bdcmp(p_dev->rc_addr, p_rc_close->peer_addr))) { 673 BTIF_TRACE_ERROR("Got disconnect of unknown device"); 674 return; 675 } 676 bt_bdaddr_t rc_addr; 677 bdcpy(rc_addr.address, p_dev->rc_addr); 678 /* Clean up AVRCP procedure flags */ 679 memset(&p_dev->rc_app_settings, 0, sizeof(btif_rc_player_app_settings_t)); 680 p_dev->rc_features_processed = false; 681 p_dev->rc_procedure_complete = false; 682 rc_stop_play_status_timer(p_dev); 683 /* Check and clear the notification event list */ 684 if (p_dev->rc_supported_event_list != NULL) { 685 list_clear(p_dev->rc_supported_event_list); 686 p_dev->rc_supported_event_list = NULL; 687 } 688 689 /* check if there is another device connected */ 690 if (p_dev->rc_state == BTRC_CONNECTION_STATE_CONNECTED) { 691 p_dev->rc_handle = 0; 692 p_dev->rc_connected = false; 693 p_dev->rc_state = BTRC_CONNECTION_STATE_DISCONNECTED; 694 695 memset(p_dev->rc_notif, 0, sizeof(p_dev->rc_notif)); 696 697 p_dev->rc_features = 0; 698 p_dev->rc_vol_label = MAX_LABEL; 699 p_dev->rc_volume = MAX_VOLUME; 700 701 memset(p_dev->rc_addr, 0, sizeof(BD_ADDR)); 702 } 703 if (get_num_connected_devices() == 0) { 704 BTIF_TRACE_DEBUG("%s: Closing all handles", __func__); 705 init_all_transactions(); 706 } 707 708 memset(p_dev->rc_addr, 0, sizeof(BD_ADDR)); 709 /* report connection state if device is AVRCP target */ 710 if (bt_rc_ctrl_callbacks != NULL) { 711 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, false, false, 712 &rc_addr); 713 } 714} 715 716/*************************************************************************** 717 * Function handle_rc_passthrough_cmd 718 * 719 * - Argument: tBTA_AV_RC rc_id remote control command ID 720 * tBTA_AV_STATE key_state status of key press 721 * 722 * - Description: Remote control command handler 723 * 724 ***************************************************************************/ 725void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) { 726 if (p_remote_cmd == NULL) { 727 BTIF_TRACE_ERROR("%s: No remote command!", __func__); 728 return; 729 } 730 731 btif_rc_device_cb_t* p_dev = 732 btif_rc_get_device_by_handle(p_remote_cmd->rc_handle); 733 if (p_dev == NULL) { 734 BTIF_TRACE_ERROR("%s: Got passthrough command from invalid rc handle", 735 __func__); 736 return; 737 } 738 739 bt_bdaddr_t rc_addr; 740 bdcpy(rc_addr.address, p_dev->rc_addr); 741 742 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id: %d", __func__, 743 p_remote_cmd->rc_id); 744 745 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up 746 * this PLAY */ 747 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) { 748 if (p_remote_cmd->key_state == AVRC_STATE_PRESS) { 749 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", 750 __func__); 751 p_dev->rc_pending_play = true; 752 } 753 return; 754 } 755 756 /* If we previously queued a play and we get a PAUSE, clear it. */ 757 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (p_dev->rc_pending_play)) { 758 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", 759 __func__); 760 p_dev->rc_pending_play = false; 761 return; 762 } 763 764 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && 765 (!btif_av_stream_started_ready())) { 766 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd", __func__); 767 return; 768 } 769 770 int pressed = (p_remote_cmd->key_state == AVRC_STATE_PRESS) ? 1 : 0; 771 772 /* pass all commands up */ 773 BTIF_TRACE_DEBUG("%s: rc_features: %d, cmd->rc_id: %d, pressed: %d", __func__, 774 p_dev->rc_features, p_remote_cmd->rc_id, pressed); 775 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed, 776 &rc_addr); 777} 778 779/*************************************************************************** 780 * Function handle_rc_passthrough_rsp 781 * 782 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response 783 * 784 * - Description: Remote control passthrough response handler 785 * 786 ***************************************************************************/ 787void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { 788 btif_rc_device_cb_t* p_dev = NULL; 789 bt_bdaddr_t rc_addr; 790 791 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle); 792 if (p_dev == NULL) { 793 BTIF_TRACE_ERROR("%s: passthrough response for Invalid rc handle", 794 __func__); 795 return; 796 } 797 798 bdcpy(rc_addr.address, p_dev->rc_addr); 799 800 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG)) { 801 BTIF_TRACE_ERROR("%s: DUT does not support AVRCP controller role", 802 __func__); 803 return; 804 } 805 806 const char* status = (p_remote_rsp->key_state == 1) ? "released" : "pressed"; 807 BTIF_TRACE_DEBUG("%s: rc_id: %d state: %s", __func__, p_remote_rsp->rc_id, 808 status); 809 810 release_transaction(p_remote_rsp->label); 811 if (bt_rc_ctrl_callbacks != NULL) { 812 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, &rc_addr, 813 p_remote_rsp->rc_id, p_remote_rsp->key_state); 814 } 815} 816 817/*************************************************************************** 818 * Function handle_rc_vendorunique_rsp 819 * 820 * - Argument: tBTA_AV_REMOTE_RSP command response 821 * 822 * - Description: Remote control vendor unique response handler 823 * 824 ***************************************************************************/ 825void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { 826 btif_rc_device_cb_t* p_dev = NULL; 827 const char* status; 828 uint8_t vendor_id = 0; 829 830 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle); 831 if (p_dev == NULL) { 832 BTIF_TRACE_ERROR("%s: Got vendorunique rsp from invalid rc handle", 833 __func__); 834 return; 835 } 836 837 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) { 838 int key_state; 839 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE) { 840 status = "released"; 841 key_state = 1; 842 } else { 843 status = "pressed"; 844 key_state = 0; 845 } 846 847 if (p_remote_rsp->len > 0) { 848 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN) 849 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN - 1]; 850 osi_free_and_reset((void**)&p_remote_rsp->p_data); 851 } 852 BTIF_TRACE_DEBUG("%s: vendor_id: %d status: %s", __func__, vendor_id, 853 status); 854 855 release_transaction(p_remote_rsp->label); 856 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, 857 key_state); 858 } else { 859 BTIF_TRACE_ERROR("%s: Remote does not support AVRCP TG role", __func__); 860 } 861} 862 863/*************************************************************************** 864 * Function handle_rc_metamsg_cmd 865 * 866 * - Argument: tBTA_AV_VENDOR Structure containing the received 867 * metamsg command 868 * 869 * - Description: Remote control metamsg command handler (AVRCP 1.3) 870 * 871 ***************************************************************************/ 872void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) { 873 /* Parse the metamsg command and pass it on to BTL-IFS */ 874 uint8_t scratch_buf[512] = {0}; 875 tAVRC_COMMAND avrc_command = {0}; 876 tAVRC_STS status; 877 btif_rc_device_cb_t* p_dev = NULL; 878 879 if (NULL == pmeta_msg) { 880 BTIF_TRACE_EVENT("%s: Exiting as pmeta_msg is NULL", __func__); 881 return; 882 } 883 884 if (NULL == pmeta_msg->p_msg) { 885 BTIF_TRACE_EVENT("%s: Exiting as pmeta_msg->p_msg is NULL", __func__); 886 return; 887 } 888 889 BTIF_TRACE_EVENT("%s: pmeta_msg: opcode: %x, code: %x", __func__, 890 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code); 891 892 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 893 if (p_dev == NULL) { 894 BTIF_TRACE_ERROR("%s: Meta msg event for Invalid rc handle", __func__); 895 return; 896 } 897 898 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR && 899 pmeta_msg->p_msg->hdr.opcode != AVRC_OP_BROWSE) { 900 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode); 901 return; 902 } 903 904 if (pmeta_msg->len < 3) { 905 BTIF_TRACE_WARNING("%s: Invalid length. opcode: 0x%x, len: 0x%x", __func__, 906 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->len); 907 return; 908 } 909 910 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) { 911 { 912 rc_transaction_t* transaction = NULL; 913 transaction = get_transaction_by_lbl(pmeta_msg->label); 914 if (transaction != NULL) { 915 handle_rc_metamsg_rsp(pmeta_msg, p_dev); 916 } else { 917 BTIF_TRACE_DEBUG( 918 "%s: Discard vendor dependent rsp. code: %d label: %d.", __func__, 919 pmeta_msg->code, pmeta_msg->label); 920 } 921 return; 922 } 923 } 924 925 status = AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, 926 sizeof(scratch_buf)); 927 BTIF_TRACE_DEBUG("%s: Received vendor command.code,PDU and label: %d, %d, %d", 928 __func__, pmeta_msg->code, avrc_command.cmd.pdu, 929 pmeta_msg->label); 930 931 if (status != AVRC_STS_NO_ERROR) { 932 /* return error */ 933 BTIF_TRACE_WARNING( 934 "%s: Error in parsing received metamsg command. status: 0x%02x", 935 __func__, status); 936 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, 937 avrc_command.pdu, status, 938 pmeta_msg->p_msg->hdr.opcode); 939 } else { 940 /* if RegisterNotification, add it to our registered queue */ 941 942 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) { 943 uint8_t event_id = avrc_command.reg_notif.event_id; 944 945 BTIF_TRACE_EVENT( 946 "%s: New register notification received.event_id: %s, label: 0x%x, " 947 "code: %x", 948 __func__, dump_rc_notification_event_id(event_id), pmeta_msg->label, 949 pmeta_msg->code); 950 p_dev->rc_notif[event_id - 1].bNotify = true; 951 p_dev->rc_notif[event_id - 1].label = pmeta_msg->label; 952 } 953 954 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s", 955 __func__, dump_rc_pdu(avrc_command.cmd.pdu)); 956 957 /* Since handle_rc_metamsg_cmd() itself is called from 958 *btif context, no context switching is required. Invoke 959 * btif_rc_upstreams_evt directly from here. */ 960 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, 961 pmeta_msg->code, pmeta_msg->label, p_dev); 962 } 963} 964 965/*************************************************************************** 966 ** 967 ** Function btif_rc_handler 968 ** 969 ** Description RC event handler 970 ** 971 ***************************************************************************/ 972void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) { 973 BTIF_TRACE_DEBUG("%s: event: %s", __func__, dump_rc_event(event)); 974 btif_rc_device_cb_t* p_dev = NULL; 975 switch (event) { 976 case BTA_AV_RC_OPEN_EVT: { 977 BTIF_TRACE_DEBUG("%s: Peer_features: %x", __func__, 978 p_data->rc_open.peer_features); 979 handle_rc_connect(&(p_data->rc_open)); 980 } break; 981 982 case BTA_AV_RC_BROWSE_OPEN_EVT: { 983 /* tell the UL that we have connection to browse channel and that 984 * browse commands can be directed accordingly. */ 985 handle_rc_browse_connect(&p_data->rc_browse_open); 986 } break; 987 988 case BTA_AV_RC_CLOSE_EVT: { 989 handle_rc_disconnect(&(p_data->rc_close)); 990 } break; 991 992 case BTA_AV_RC_BROWSE_CLOSE_EVT: { 993 BTIF_TRACE_DEBUG("%s: BTA_AV_RC_BROWSE_CLOSE_EVT", __func__); 994 } break; 995 996 case BTA_AV_REMOTE_CMD_EVT: { 997 if (bt_rc_callbacks != NULL) { 998 BTIF_TRACE_DEBUG("%s: rc_id: 0x%x key_state: %d", __func__, 999 p_data->remote_cmd.rc_id, 1000 p_data->remote_cmd.key_state); 1001 handle_rc_passthrough_cmd((&p_data->remote_cmd)); 1002 } else { 1003 BTIF_TRACE_ERROR("%s: AVRCP TG role not up, drop passthrough commands", 1004 __func__); 1005 } 1006 } break; 1007 1008 case BTA_AV_REMOTE_RSP_EVT: { 1009 BTIF_TRACE_DEBUG("%s: RSP: rc_id: 0x%x key_state: %d", __func__, 1010 p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state); 1011 1012 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR) { 1013 handle_rc_vendorunique_rsp((&p_data->remote_rsp)); 1014 } else { 1015 handle_rc_passthrough_rsp((&p_data->remote_rsp)); 1016 } 1017 } break; 1018 1019 case BTA_AV_RC_FEAT_EVT: { 1020 BTIF_TRACE_DEBUG("%s: Peer_features: %x", __func__, 1021 p_data->rc_feat.peer_features); 1022 p_dev = btif_rc_get_device_by_handle(p_data->rc_feat.rc_handle); 1023 if (p_dev == NULL) { 1024 BTIF_TRACE_ERROR("%s: RC Feature event for Invalid rc handle", 1025 __func__); 1026 break; 1027 } 1028 1029 p_dev->rc_features = p_data->rc_feat.peer_features; 1030 if (bt_rc_callbacks != NULL) { 1031 handle_rc_features(p_dev); 1032 } 1033 1034 if ((p_dev->rc_connected) && (bt_rc_ctrl_callbacks != NULL)) { 1035 handle_rc_ctrl_features(p_dev); 1036 } 1037 } break; 1038 1039 case BTA_AV_META_MSG_EVT: { 1040 if (bt_rc_callbacks != NULL) { 1041 BTIF_TRACE_DEBUG("%s: BTA_AV_META_MSG_EVT code: %d label: %d", __func__, 1042 p_data->meta_msg.code, p_data->meta_msg.label); 1043 BTIF_TRACE_DEBUG("%s: company_id: 0x%x len: %d handle: %d", __func__, 1044 p_data->meta_msg.company_id, p_data->meta_msg.len, 1045 p_data->meta_msg.rc_handle); 1046 1047 /* handle the metamsg command */ 1048 handle_rc_metamsg_cmd(&(p_data->meta_msg)); 1049 1050 /* Free the Memory allocated for tAVRC_MSG */ 1051 } else if (bt_rc_ctrl_callbacks != NULL) { 1052 /* This is case of Sink + CT + TG(for abs vol)) */ 1053 BTIF_TRACE_DEBUG( 1054 "%s BTA_AV_META_MSG_EVT code:%d label:%d opcode %d ctype %d", 1055 __func__, p_data->meta_msg.code, p_data->meta_msg.label, 1056 p_data->meta_msg.p_msg->hdr.opcode, 1057 p_data->meta_msg.p_msg->hdr.ctype); 1058 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d", __func__, 1059 p_data->meta_msg.company_id, p_data->meta_msg.len, 1060 p_data->meta_msg.rc_handle); 1061 switch (p_data->meta_msg.p_msg->hdr.opcode) { 1062 case AVRC_OP_VENDOR: 1063 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL) && 1064 (p_data->meta_msg.code <= AVRC_RSP_INTERIM)) { 1065 /* Its a response */ 1066 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg)); 1067 } else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ) { 1068 /* Its a command */ 1069 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg)); 1070 } 1071 break; 1072 1073 case AVRC_OP_BROWSE: 1074 if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_CMD) { 1075 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg)); 1076 } else if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_RSP) { 1077 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg)); 1078 } 1079 break; 1080 } 1081 } else { 1082 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands"); 1083 } 1084 } break; 1085 1086 default: 1087 BTIF_TRACE_DEBUG("%s: Unhandled RC event : 0x%x", __func__, event); 1088 } 1089} 1090 1091/*************************************************************************** 1092 ** 1093 ** Function btif_rc_get_connected_peer 1094 ** 1095 ** Description Fetches the connected headset's BD_ADDR if any 1096 ** 1097 ***************************************************************************/ 1098bool btif_rc_get_connected_peer(BD_ADDR peer_addr) { 1099 bt_bdaddr_t rc_addr; 1100 bdcpy(rc_addr.address, peer_addr); 1101 btif_rc_device_cb_t* p_dev = NULL; 1102 1103 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 1104 p_dev = get_connected_device(idx); 1105 if (p_dev != NULL && (p_dev->rc_connected == TRUE)) { 1106 bdcpy(peer_addr, p_dev->rc_addr); 1107 return true; 1108 } 1109 } 1110 return false; 1111} 1112 1113/*************************************************************************** 1114 ** 1115 ** Function btif_rc_get_connected_peer_handle 1116 ** 1117 ** Description Fetches the connected headset's handle if any 1118 ** 1119 ***************************************************************************/ 1120uint8_t btif_rc_get_connected_peer_handle(BD_ADDR peer_addr) { 1121 bt_bdaddr_t rc_addr; 1122 bdcpy(rc_addr.address, peer_addr); 1123 1124 btif_rc_device_cb_t* p_dev = NULL; 1125 p_dev = btif_rc_get_device_by_bda(&rc_addr); 1126 1127 if (p_dev == NULL) { 1128 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 1129 return BTRC_HANDLE_NONE; 1130 } 1131 return p_dev->rc_handle; 1132} 1133 1134/*************************************************************************** 1135 ** 1136 ** Function btif_rc_check_handle_pending_play 1137 ** 1138 ** Description Clears the queued PLAY command. if |bSendToApp| is true, 1139 ** forwards to app 1140 ** 1141 ***************************************************************************/ 1142 1143/* clear the queued PLAY command. if |bSendToApp| is true, forward to app */ 1144void btif_rc_check_handle_pending_play(BD_ADDR peer_addr, bool bSendToApp) { 1145 bt_bdaddr_t rc_addr; 1146 bdcpy(rc_addr.address, peer_addr); 1147 1148 btif_rc_device_cb_t* p_dev = NULL; 1149 p_dev = btif_rc_get_device_by_bda(&rc_addr); 1150 1151 if (p_dev == NULL) { 1152 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 1153 return; 1154 } 1155 1156 BTIF_TRACE_DEBUG("%s: bSendToApp: %d", __func__, bSendToApp); 1157 if (p_dev->rc_pending_play) { 1158 if (bSendToApp) { 1159 tBTA_AV_REMOTE_CMD remote_cmd; 1160 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __func__); 1161 1162 memset(&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD)); 1163 remote_cmd.rc_handle = p_dev->rc_handle; 1164 remote_cmd.rc_id = AVRC_ID_PLAY; 1165 remote_cmd.hdr.ctype = AVRC_CMD_CTRL; 1166 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU; 1167 1168 /* delay sending to app, else there is a timing issue in the framework, 1169 ** which causes the audio to be on th device's speaker. Delay between 1170 ** OPEN & RC_PLAYs 1171 */ 1172 sleep_ms(200); 1173 /* send to app - both PRESSED & RELEASED */ 1174 remote_cmd.key_state = AVRC_STATE_PRESS; 1175 handle_rc_passthrough_cmd(&remote_cmd); 1176 1177 sleep_ms(100); 1178 1179 remote_cmd.key_state = AVRC_STATE_RELEASE; 1180 handle_rc_passthrough_cmd(&remote_cmd); 1181 } 1182 p_dev->rc_pending_play = false; 1183 } 1184} 1185 1186/* Generic reject response */ 1187static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu, 1188 uint8_t status, uint8_t opcode) { 1189 uint8_t ctype = AVRC_RSP_REJ; 1190 tAVRC_RESPONSE avrc_rsp; 1191 BT_HDR* p_msg = NULL; 1192 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE)); 1193 1194 avrc_rsp.rsp.opcode = opcode; 1195 avrc_rsp.rsp.pdu = pdu; 1196 avrc_rsp.rsp.status = status; 1197 1198 status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg); 1199 1200 if (status != AVRC_STS_NO_ERROR) { 1201 BTIF_TRACE_ERROR("%s: status not AVRC_STS_NO_ERROR", __func__); 1202 return; 1203 } 1204 1205 BTIF_TRACE_DEBUG( 1206 "%s: Sending error notification to handle: %d. pdu: %s,status: 0x%02x", 1207 __func__, rc_handle, dump_rc_pdu(pdu), status); 1208 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg); 1209} 1210 1211/*************************************************************************** 1212 * Function get_rsp_type_code 1213 * 1214 * - Argument: status 1215 * - Description: Returns response type codes for particular command code and 1216 * status. 1217 * 1218 ***************************************************************************/ 1219static tBTA_AV_CODE get_rsp_type_code(tAVRC_STS status, tBTA_AV_CODE code) { 1220 if (status != AVRC_STS_NO_ERROR) { 1221 return AVRC_RSP_REJ; 1222 } 1223 1224 if (code < AVRC_RSP_NOT_IMPL) { 1225 if (code == AVRC_CMD_NOTIF) return AVRC_RSP_INTERIM; 1226 1227 if (code == AVRC_CMD_STATUS) return AVRC_RSP_IMPL_STBL; 1228 1229 return AVRC_RSP_ACCEPT; 1230 } 1231 1232 return code; 1233} 1234 1235/*************************************************************************** 1236 * Function send_metamsg_rsp 1237 * 1238 * - Argument: 1239 * p_dev Dev pointer 1240 * index Command index (= -1 if not used) 1241 * label Label of the RC response 1242 * code Response type 1243 * pmetamsg_resp Vendor response 1244 * 1245 * - Description: Remote control metamsg response handler 1246 * 1247 ***************************************************************************/ 1248static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index, 1249 uint8_t label, tBTA_AV_CODE code, 1250 tAVRC_RESPONSE* pmetamsg_resp) { 1251 uint8_t ctype; 1252 1253 if (p_dev == NULL) { 1254 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 1255 return; 1256 } 1257 1258 if (pmetamsg_resp == NULL) { 1259 BTIF_TRACE_WARNING("%s: Invalid response received from application", 1260 __func__); 1261 return; 1262 } 1263 1264 BTIF_TRACE_EVENT( 1265 "%s: rc_handle: %d, index: %d, label: %d, code: 0x%02x, pdu: %s", 1266 __func__, p_dev->rc_handle, index, label, code, 1267 dump_rc_pdu(pmetamsg_resp->rsp.pdu)); 1268 1269 if (index >= 0 && p_dev->rc_pdu_info[index].is_rsp_pending == false) { 1270 BTIF_TRACE_ERROR("%s: is_rsp_pending false, returning", __func__); 1271 return; 1272 } 1273 1274 ctype = get_rsp_type_code(pmetamsg_resp->rsp.status, code); 1275 1276 /* if response is for register_notification, make sure the rc has 1277 actually registered for this */ 1278 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && 1279 ((code == AVRC_RSP_CHANGED) || (code == AVRC_RSP_INTERIM))) { 1280 bool bSent = false; 1281 uint8_t event_id = pmetamsg_resp->reg_notif.event_id; 1282 bool bNotify = 1283 (p_dev->rc_connected) && (p_dev->rc_notif[event_id - 1].bNotify); 1284 1285 /* de-register this notification for a CHANGED response */ 1286 p_dev->rc_notif[event_id - 1].bNotify = false; 1287 BTIF_TRACE_DEBUG("%s: rc_handle: %d. event_id: 0x%02d bNotify: %u", 1288 __func__, p_dev->rc_handle, event_id, bNotify); 1289 if (bNotify) { 1290 BT_HDR* p_msg = NULL; 1291 tAVRC_STS status; 1292 1293 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse( 1294 p_dev->rc_handle, pmetamsg_resp, &p_msg))) { 1295 BTIF_TRACE_DEBUG( 1296 "%s: Sending notification to rc_handle: %d. event_id: 0x%02d", 1297 __func__, p_dev->rc_handle, event_id); 1298 bSent = true; 1299 BTA_AvMetaRsp(p_dev->rc_handle, p_dev->rc_notif[event_id - 1].label, 1300 ctype, p_msg); 1301 } else { 1302 BTIF_TRACE_WARNING( 1303 "%s: failed to build metamsg response. status: 0x%02x", __func__, 1304 status); 1305 } 1306 } 1307 1308 if (!bSent) { 1309 BTIF_TRACE_DEBUG( 1310 "%s: Notification not sent, as there are no RC connections or the \ 1311 CT has not subscribed for event_id: %s", 1312 __func__, dump_rc_notification_event_id(event_id)); 1313 } 1314 } else { 1315 /* All other commands go here */ 1316 1317 BT_HDR* p_msg = NULL; 1318 tAVRC_STS status; 1319 1320 status = AVRC_BldResponse(p_dev->rc_handle, pmetamsg_resp, &p_msg); 1321 1322 if (status == AVRC_STS_NO_ERROR) { 1323 BTA_AvMetaRsp(p_dev->rc_handle, label, ctype, p_msg); 1324 } else { 1325 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x", 1326 __func__, status); 1327 } 1328 } 1329 1330 if (index >= 0) { 1331 p_dev->rc_pdu_info[index].ctype = 0; 1332 p_dev->rc_pdu_info[index].label = 0; 1333 p_dev->rc_pdu_info[index].is_rsp_pending = false; 1334 } 1335} 1336 1337static uint8_t opcode_from_pdu(uint8_t pdu) { 1338 uint8_t opcode = 0; 1339 1340 switch (pdu) { 1341 case AVRC_PDU_SET_BROWSED_PLAYER: 1342 case AVRC_PDU_GET_FOLDER_ITEMS: 1343 case AVRC_PDU_CHANGE_PATH: 1344 case AVRC_PDU_GET_ITEM_ATTRIBUTES: 1345 case AVRC_PDU_ADD_TO_NOW_PLAYING: 1346 case AVRC_PDU_SEARCH: 1347 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: 1348 case AVRC_PDU_GENERAL_REJECT: 1349 opcode = AVRC_OP_BROWSE; 1350 break; 1351 1352 case AVRC_PDU_NEXT_GROUP: 1353 case AVRC_PDU_PREV_GROUP: /* pass thru */ 1354 opcode = AVRC_OP_PASS_THRU; 1355 break; 1356 1357 default: /* vendor */ 1358 opcode = AVRC_OP_VENDOR; 1359 break; 1360 } 1361 1362 return opcode; 1363} 1364 1365/*************************************************************************** 1366 * Function: fill_attribute_id_array 1367 * 1368 * - Argument: 1369 * cmd_attribute_number input attribute number from AVRCP command 1370 * cmd_attribute_id_array input attribute list from AVRCP command 1371 * out_array_size allocated size of out attribute id array 1372 * out_attribute_id_array output attribute list resolved here 1373 * 1374 * - Description: 1375 * Resolve attribute id array as defined by the AVRCP specification. 1376 * 1377 * - Returns: 1378 * The number of attributes filled in 1379 * 1380 ***************************************************************************/ 1381static uint8_t fill_attribute_id_array( 1382 uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array, 1383 size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) { 1384 /* Reset attribute array */ 1385 memset(out_attribute_id_array, 0, out_array_size); 1386 /* Default case for cmd_attribute_number == 0xFF, No attribute */ 1387 uint8_t out_attribute_number = 0; 1388 if (cmd_attribute_number == 0) { 1389 /* All attributes */ 1390 out_attribute_number = out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID 1391 ? out_array_size 1392 : AVRC_MAX_NUM_MEDIA_ATTR_ID; 1393 for (int i = 0; i < out_attribute_number; i++) { 1394 out_attribute_id_array[i] = (btrc_media_attr_t)(i + 1); 1395 } 1396 } else if (cmd_attribute_number != 0xFF) { 1397 /* Attribute List */ 1398 out_attribute_number = 0; 1399 int filled_id_count = 0; 1400 for (int i = 0; (i < cmd_attribute_number) && 1401 (out_attribute_number < out_array_size) && 1402 (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID); 1403 i++) { 1404 /* Fill only valid entries */ 1405 if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) { 1406 /* Skip the duplicate entries */ 1407 for (filled_id_count = 0; filled_id_count < out_attribute_number; 1408 filled_id_count++) { 1409 if (out_attribute_id_array[filled_id_count] == 1410 cmd_attribute_id_array[i]) 1411 break; 1412 } 1413 /* New ID */ 1414 if (filled_id_count == out_attribute_number) { 1415 out_attribute_id_array[out_attribute_number] = 1416 (btrc_media_attr_t)cmd_attribute_id_array[i]; 1417 out_attribute_number++; 1418 } 1419 } 1420 } 1421 } 1422 return out_attribute_number; 1423} 1424 1425/******************************************************************************* 1426 * 1427 * Function btif_rc_upstreams_evt 1428 * 1429 * Description Executes AVRC UPSTREAMS events in btif context. 1430 * 1431 * Returns void 1432 * 1433 ******************************************************************************/ 1434static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, 1435 uint8_t ctype, uint8_t label, 1436 btif_rc_device_cb_t* p_dev) { 1437 BTIF_TRACE_EVENT("%s: pdu: %s handle: 0x%x ctype: %x label: %x event ID: %x", 1438 __func__, dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle, 1439 ctype, label, pavrc_cmd->reg_notif.event_id); 1440 bt_bdaddr_t rc_addr; 1441 1442 bdcpy(rc_addr.address, p_dev->rc_addr); 1443 1444 switch (event) { 1445 case AVRC_PDU_GET_PLAY_STATUS: { 1446 fill_pdu_queue(IDX_GET_PLAY_STATUS_RSP, ctype, label, true, p_dev); 1447 HAL_CBACK(bt_rc_callbacks, get_play_status_cb, &rc_addr); 1448 } break; 1449 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 1450 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 1451 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: 1452 case AVRC_PDU_SET_PLAYER_APP_VALUE: 1453 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: 1454 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: { 1455 /* TODO: Add support for Application Settings */ 1456 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1457 AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode); 1458 } break; 1459 case AVRC_PDU_GET_ELEMENT_ATTR: { 1460 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; 1461 uint8_t num_attr = fill_attribute_id_array( 1462 pavrc_cmd->get_elem_attrs.num_attr, 1463 (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs, 1464 BTRC_MAX_ELEM_ATTR_SIZE, element_attrs); 1465 if (num_attr == 0) { 1466 BTIF_TRACE_ERROR( 1467 "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES", 1468 __func__); 1469 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1470 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); 1471 return; 1472 } 1473 fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev); 1474 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, 1475 &rc_addr); 1476 } break; 1477 case AVRC_PDU_REGISTER_NOTIFICATION: { 1478 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED && 1479 pavrc_cmd->reg_notif.param == 0) { 1480 BTIF_TRACE_WARNING( 1481 "%s: Device registering position changed with illegal param 0.", 1482 __func__); 1483 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1484 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); 1485 /* de-register this notification for a rejected response */ 1486 p_dev->rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = false; 1487 return; 1488 } 1489 HAL_CBACK(bt_rc_callbacks, register_notification_cb, 1490 (btrc_event_id_t)pavrc_cmd->reg_notif.event_id, 1491 pavrc_cmd->reg_notif.param, &rc_addr); 1492 } break; 1493 case AVRC_PDU_INFORM_DISPLAY_CHARSET: { 1494 tAVRC_RESPONSE avrc_rsp; 1495 BTIF_TRACE_EVENT("%s: AVRC_PDU_INFORM_DISPLAY_CHARSET", __func__); 1496 if (p_dev->rc_connected == true) { 1497 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP)); 1498 avrc_rsp.inform_charset.opcode = 1499 opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET); 1500 avrc_rsp.inform_charset.pdu = AVRC_PDU_INFORM_DISPLAY_CHARSET; 1501 avrc_rsp.inform_charset.status = AVRC_STS_NO_ERROR; 1502 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp); 1503 } 1504 } break; 1505 1506 case AVRC_PDU_GET_FOLDER_ITEMS: { 1507 uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE]; 1508 uint8_t num_attr; 1509 num_attr = pavrc_cmd->get_items.attr_count; 1510 1511 BTIF_TRACE_EVENT( 1512 "%s: AVRC_PDU_GET_FOLDER_ITEMS num_attr: %d, start_item [%d] \ 1513 end_item [%d]", 1514 __func__, num_attr, pavrc_cmd->get_items.start_item, 1515 pavrc_cmd->get_items.end_item); 1516 1517 /* num_attr requested: 1518 * 0x00: All attributes requested 1519 * 0xFF: No Attributes requested 1520 * 0x01 to 0x07: Specified number of attributes 1521 */ 1522 if ((num_attr != 0xFF && num_attr > BTRC_MAX_ELEM_ATTR_SIZE)) { 1523 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1524 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); 1525 return; 1526 } 1527 1528 /* Except num_attr is None(0xff) / All(0x00), request follows with an 1529 * Attribute List */ 1530 if ((num_attr != 0xFF) && (num_attr != 0x00)) { 1531 memcpy(attr_ids, pavrc_cmd->get_items.p_attr_list, 1532 sizeof(uint32_t) * num_attr); 1533 } 1534 1535 fill_pdu_queue(IDX_GET_FOLDER_ITEMS_RSP, ctype, label, true, p_dev); 1536 HAL_CBACK(bt_rc_callbacks, get_folder_items_cb, 1537 pavrc_cmd->get_items.scope, pavrc_cmd->get_items.start_item, 1538 pavrc_cmd->get_items.end_item, num_attr, attr_ids, &rc_addr); 1539 } break; 1540 1541 case AVRC_PDU_SET_ADDRESSED_PLAYER: { 1542 fill_pdu_queue(IDX_SET_ADDR_PLAYER_RSP, ctype, label, true, p_dev); 1543 HAL_CBACK(bt_rc_callbacks, set_addressed_player_cb, 1544 pavrc_cmd->addr_player.player_id, &rc_addr); 1545 } break; 1546 1547 case AVRC_PDU_SET_BROWSED_PLAYER: { 1548 fill_pdu_queue(IDX_SET_BROWSED_PLAYER_RSP, ctype, label, true, p_dev); 1549 HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb, 1550 pavrc_cmd->br_player.player_id, &rc_addr); 1551 } break; 1552 1553 case AVRC_PDU_REQUEST_CONTINUATION_RSP: { 1554 BTIF_TRACE_EVENT("%s() REQUEST CONTINUATION: target_pdu: 0x%02d", 1555 __func__, pavrc_cmd->continu.target_pdu); 1556 tAVRC_RESPONSE avrc_rsp; 1557 if (p_dev->rc_connected == TRUE) { 1558 memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP)); 1559 avrc_rsp.continu.opcode = 1560 opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP); 1561 avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP; 1562 avrc_rsp.continu.status = AVRC_STS_NO_ERROR; 1563 avrc_rsp.continu.target_pdu = pavrc_cmd->continu.target_pdu; 1564 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp); 1565 } 1566 } break; 1567 1568 case AVRC_PDU_ABORT_CONTINUATION_RSP: { 1569 BTIF_TRACE_EVENT("%s() ABORT CONTINUATION: target_pdu: 0x%02d", __func__, 1570 pavrc_cmd->abort.target_pdu); 1571 tAVRC_RESPONSE avrc_rsp; 1572 if (p_dev->rc_connected == TRUE) { 1573 memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP)); 1574 avrc_rsp.abort.opcode = 1575 opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP); 1576 avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP; 1577 avrc_rsp.abort.status = AVRC_STS_NO_ERROR; 1578 avrc_rsp.abort.target_pdu = pavrc_cmd->continu.target_pdu; 1579 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp); 1580 } 1581 } break; 1582 1583 case AVRC_PDU_CHANGE_PATH: { 1584 fill_pdu_queue(IDX_CHG_PATH_RSP, ctype, label, true, p_dev); 1585 HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction, 1586 pavrc_cmd->chg_path.folder_uid, &rc_addr); 1587 } break; 1588 1589 case AVRC_PDU_SEARCH: { 1590 fill_pdu_queue(IDX_SEARCH_RSP, ctype, label, true, p_dev); 1591 HAL_CBACK(bt_rc_callbacks, search_cb, pavrc_cmd->search.string.charset_id, 1592 pavrc_cmd->search.string.str_len, 1593 pavrc_cmd->search.string.p_str, &rc_addr); 1594 } break; 1595 1596 case AVRC_PDU_GET_ITEM_ATTRIBUTES: { 1597 btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; 1598 uint8_t num_attr = fill_attribute_id_array( 1599 pavrc_cmd->get_attrs.attr_count, 1600 (btrc_media_attr_t*)pavrc_cmd->get_attrs.p_attr_list, 1601 BTRC_MAX_ELEM_ATTR_SIZE, item_attrs); 1602 if (num_attr == 0) { 1603 BTIF_TRACE_ERROR( 1604 "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES", 1605 __func__); 1606 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1607 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode); 1608 return; 1609 } 1610 fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev); 1611 BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__, 1612 num_attr); 1613 HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope, 1614 pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter, 1615 num_attr, item_attrs, &rc_addr); 1616 } break; 1617 1618 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: { 1619 fill_pdu_queue(IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, ctype, label, true, p_dev); 1620 HAL_CBACK(bt_rc_callbacks, get_total_num_of_items_cb, 1621 pavrc_cmd->get_num_of_items.scope, &rc_addr); 1622 } break; 1623 1624 case AVRC_PDU_ADD_TO_NOW_PLAYING: { 1625 fill_pdu_queue(IDX_ADD_TO_NOW_PLAYING_RSP, ctype, label, true, p_dev); 1626 HAL_CBACK(bt_rc_callbacks, add_to_now_playing_cb, 1627 pavrc_cmd->add_to_play.scope, pavrc_cmd->add_to_play.uid, 1628 pavrc_cmd->add_to_play.uid_counter, &rc_addr); 1629 } break; 1630 1631 case AVRC_PDU_PLAY_ITEM: { 1632 fill_pdu_queue(IDX_PLAY_ITEM_RSP, ctype, label, true, p_dev); 1633 HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope, 1634 pavrc_cmd->play_item.uid_counter, pavrc_cmd->play_item.uid, 1635 &rc_addr); 1636 } break; 1637 1638 default: { 1639 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu, 1640 AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode); 1641 return; 1642 } break; 1643 } 1644} 1645 1646/******************************************************************************* 1647 * 1648 * Function btif_rc_ctrl_upstreams_rsp_cmd 1649 * 1650 * Description Executes AVRC UPSTREAMS response events in btif context. 1651 * 1652 * Returns void 1653 * 1654 ******************************************************************************/ 1655static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event, 1656 tAVRC_COMMAND* pavrc_cmd, 1657 uint8_t label, 1658 btif_rc_device_cb_t* p_dev) { 1659 BTIF_TRACE_DEBUG("%s: pdu: %s: handle: 0x%x", __func__, 1660 dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle); 1661 bt_bdaddr_t rc_addr; 1662 bdcpy(rc_addr.address, p_dev->rc_addr); 1663 switch (event) { 1664 case AVRC_PDU_SET_ABSOLUTE_VOLUME: 1665 HAL_CBACK(bt_rc_ctrl_callbacks, setabsvol_cmd_cb, &rc_addr, 1666 pavrc_cmd->volume.volume, label); 1667 break; 1668 case AVRC_PDU_REGISTER_NOTIFICATION: 1669 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE) { 1670 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb, 1671 &rc_addr, label); 1672 } 1673 break; 1674 } 1675} 1676 1677/******************************************************************************* 1678 * 1679 * Function btif_rc_upstreams_rsp_evt 1680 * 1681 * Description Executes AVRC UPSTREAMS response events in btif context. 1682 * 1683 * Returns void 1684 * 1685 ******************************************************************************/ 1686static void btif_rc_upstreams_rsp_evt(uint16_t event, 1687 tAVRC_RESPONSE* pavrc_resp, uint8_t ctype, 1688 uint8_t label, 1689 btif_rc_device_cb_t* p_dev) { 1690 BTIF_TRACE_EVENT("%s: pdu: %s: handle: 0x%x ctype: %x label: %x", __func__, 1691 dump_rc_pdu(pavrc_resp->pdu), p_dev->rc_handle, ctype, 1692 label); 1693 bt_bdaddr_t rc_addr; 1694 bdcpy(rc_addr.address, p_dev->rc_addr); 1695 1696 switch (event) { 1697 case AVRC_PDU_REGISTER_NOTIFICATION: { 1698 if (AVRC_RSP_CHANGED == ctype) 1699 p_dev->rc_volume = pavrc_resp->reg_notif.param.volume; 1700 HAL_CBACK(bt_rc_callbacks, volume_change_cb, 1701 pavrc_resp->reg_notif.param.volume, ctype, &rc_addr); 1702 } break; 1703 1704 case AVRC_PDU_SET_ABSOLUTE_VOLUME: { 1705 BTIF_TRACE_DEBUG( 1706 "%s: Set absolute volume change event received: volume: %d, ctype: " 1707 "%d", 1708 __func__, pavrc_resp->volume.volume, ctype); 1709 if (AVRC_RSP_ACCEPT == ctype) 1710 p_dev->rc_volume = pavrc_resp->volume.volume; 1711 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->volume.volume, 1712 ctype, &rc_addr); 1713 } break; 1714 1715 default: 1716 return; 1717 } 1718} 1719 1720/******************************************************************************* 1721 * AVRCP API Functions 1722 ******************************************************************************/ 1723 1724/******************************************************************************* 1725 * 1726 * Function init 1727 * 1728 * Description Initializes the AVRC interface 1729 * 1730 * Returns bt_status_t 1731 * 1732 ******************************************************************************/ 1733static bt_status_t init(btrc_callbacks_t* callbacks) { 1734 BTIF_TRACE_EVENT("%s: ", __func__); 1735 bt_status_t result = BT_STATUS_SUCCESS; 1736 1737 if (bt_rc_callbacks) return BT_STATUS_DONE; 1738 1739 bt_rc_callbacks = callbacks; 1740 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 1741 memset(&btif_rc_cb.rc_multi_cb[idx], 0, 1742 sizeof(btif_rc_cb.rc_multi_cb[idx])); 1743 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL; 1744 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME; 1745 btif_rc_cb.rc_multi_cb[idx].rc_state = BTRC_CONNECTION_STATE_DISCONNECTED; 1746 } 1747 lbl_init(); 1748 1749 return result; 1750} 1751 1752/******************************************************************************* 1753 * 1754 * Function init_ctrl 1755 * 1756 * Description Initializes the AVRC interface 1757 * 1758 * Returns bt_status_t 1759 * 1760 ******************************************************************************/ 1761static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks) { 1762 BTIF_TRACE_EVENT("%s: ", __func__); 1763 bt_status_t result = BT_STATUS_SUCCESS; 1764 1765 if (bt_rc_ctrl_callbacks) return BT_STATUS_DONE; 1766 1767 bt_rc_ctrl_callbacks = callbacks; 1768 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 1769 memset(&btif_rc_cb.rc_multi_cb[idx], 0, 1770 sizeof(btif_rc_cb.rc_multi_cb[idx])); 1771 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL; 1772 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME; 1773 } 1774 lbl_init(); 1775 1776 return result; 1777} 1778 1779static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev) { 1780 if (p_dev == NULL) { 1781 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 1782 return; 1783 } 1784 1785 if (p_dev->rc_procedure_complete == true) { 1786 return; 1787 } 1788 p_dev->rc_procedure_complete = true; 1789 uint32_t attr_list[] = { 1790 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST, 1791 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM, 1792 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE, 1793 AVRC_MEDIA_ATTR_ID_PLAYING_TIME}; 1794 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev); 1795} 1796 1797/*************************************************************************** 1798 * 1799 * Function get_play_status_rsp 1800 * 1801 * Description Returns the current play status. 1802 * This method is called in response to 1803 * GetPlayStatus request. 1804 * 1805 * Returns bt_status_t 1806 * 1807 **************************************************************************/ 1808static bt_status_t get_play_status_rsp(bt_bdaddr_t* bd_addr, 1809 btrc_play_status_t play_status, 1810 uint32_t song_len, uint32_t song_pos) { 1811 tAVRC_RESPONSE avrc_rsp; 1812 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 1813 1814 BTIF_TRACE_DEBUG("%s: song len %d song pos %d", __func__, song_len, song_pos); 1815 CHECK_RC_CONNECTED(p_dev); 1816 1817 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP)); 1818 1819 avrc_rsp.get_play_status.song_len = song_len; 1820 avrc_rsp.get_play_status.song_pos = song_pos; 1821 avrc_rsp.get_play_status.play_status = play_status; 1822 1823 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS; 1824 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS); 1825 avrc_rsp.get_play_status.status = 1826 ((play_status != BTRC_PLAYSTATE_ERROR) ? AVRC_STS_NO_ERROR 1827 : AVRC_STS_BAD_PARAM); 1828 1829 /* Send the response */ 1830 send_metamsg_rsp(p_dev, IDX_GET_PLAY_STATUS_RSP, 1831 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].label, 1832 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].ctype, 1833 &avrc_rsp); 1834 1835 return BT_STATUS_SUCCESS; 1836} 1837 1838/*************************************************************************** 1839 * 1840 * Function get_element_attr_rsp 1841 * 1842 * Description Returns the current songs' element attributes 1843 * in text. 1844 * 1845 * Returns bt_status_t 1846 * 1847 **************************************************************************/ 1848static bt_status_t get_element_attr_rsp(bt_bdaddr_t* bd_addr, uint8_t num_attr, 1849 btrc_element_attr_val_t* p_attrs) { 1850 tAVRC_RESPONSE avrc_rsp; 1851 uint32_t i; 1852 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; 1853 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 1854 1855 BTIF_TRACE_DEBUG("%s", __func__); 1856 CHECK_RC_CONNECTED(p_dev); 1857 1858 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr); 1859 1860 if (num_attr == 0) { 1861 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM; 1862 } else { 1863 for (i = 0; i < num_attr; i++) { 1864 element_attrs[i].attr_id = p_attrs[i].attr_id; 1865 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8; 1866 element_attrs[i].name.str_len = (uint16_t)strlen((char*)p_attrs[i].text); 1867 element_attrs[i].name.p_str = p_attrs[i].text; 1868 BTIF_TRACE_DEBUG( 1869 "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__, 1870 (unsigned int)element_attrs[i].attr_id, 1871 element_attrs[i].name.charset_id, element_attrs[i].name.str_len, 1872 element_attrs[i].name.p_str); 1873 } 1874 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR; 1875 } 1876 avrc_rsp.get_attrs.num_attrs = num_attr; 1877 avrc_rsp.get_attrs.p_attrs = element_attrs; 1878 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR; 1879 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR); 1880 1881 /* Send the response */ 1882 send_metamsg_rsp(p_dev, IDX_GET_ELEMENT_ATTR_RSP, 1883 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].label, 1884 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].ctype, 1885 &avrc_rsp); 1886 1887 return BT_STATUS_SUCCESS; 1888} 1889 1890/*************************************************************************** 1891 * 1892 * Function reject_pending_notification 1893 * 1894 * Description Utility function to reject a pending notification. When 1895 * AddressedPlayer change is received, all pending 1896 * notifications should be completed. 1897 * 1898 * Returns void 1899 * 1900 **************************************************************************/ 1901static void reject_pending_notification(btrc_event_id_t event_id, int idx) { 1902 tAVRC_RESPONSE avrc_rsp; 1903 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP)); 1904 1905 avrc_rsp.reg_notif.event_id = event_id; 1906 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION; 1907 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION); 1908 avrc_rsp.reg_notif.status = AVRC_STS_ADDR_PLAYER_CHG; 1909 BTIF_TRACE_WARNING("%s: Handling event ID: 0x%x", __func__, event_id); 1910 1911 send_metamsg_rsp(&btif_rc_cb.rc_multi_cb[idx], -1, 1912 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label, 1913 AVRC_RSP_REJ, &avrc_rsp); 1914} 1915 1916/*************************************************************************** 1917 * 1918 * Function register_notification_rsp 1919 * 1920 * Description Response to the register notification request. 1921 * 1922 * Returns bt_status_t 1923 * 1924 **************************************************************************/ 1925static bt_status_t register_notification_rsp( 1926 btrc_event_id_t event_id, btrc_notification_type_t type, 1927 btrc_register_notification_t* p_param) { 1928 tAVRC_RESPONSE avrc_rsp; 1929 BTIF_TRACE_EVENT("%s: event_id: %s", __func__, 1930 dump_rc_notification_event_id(event_id)); 1931 std::unique_lock<std::mutex> lock(btif_rc_cb.lock); 1932 1933 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP)); 1934 1935 avrc_rsp.reg_notif.event_id = event_id; 1936 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION; 1937 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION); 1938 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR; 1939 1940 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 1941 memset(&(avrc_rsp.reg_notif.param), 0, sizeof(tAVRC_NOTIF_RSP_PARAM)); 1942 1943 if (!(btif_rc_cb.rc_multi_cb[idx].rc_connected)) { 1944 BTIF_TRACE_ERROR("%s: Avrcp device is not connected, handle: 0x%x", 1945 __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle); 1946 continue; 1947 } 1948 1949 if (btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify == false) { 1950 BTIF_TRACE_WARNING( 1951 "%s: Avrcp Event id is not registered: event_id: %x, handle: 0x%x", 1952 __func__, event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle); 1953 continue; 1954 } 1955 1956 BTIF_TRACE_DEBUG( 1957 "%s: Avrcp Event id is registered: event_id: %x handle: 0x%x", __func__, 1958 event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle); 1959 1960 switch (event_id) { 1961 case BTRC_EVT_PLAY_STATUS_CHANGED: 1962 avrc_rsp.reg_notif.param.play_status = p_param->play_status; 1963 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING) 1964 btif_av_clear_remote_suspend_flag(); 1965 break; 1966 case BTRC_EVT_TRACK_CHANGE: 1967 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), 1968 sizeof(btrc_uid_t)); 1969 break; 1970 case BTRC_EVT_PLAY_POS_CHANGED: 1971 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos; 1972 break; 1973 case BTRC_EVT_AVAL_PLAYER_CHANGE: 1974 break; 1975 case BTRC_EVT_ADDR_PLAYER_CHANGE: 1976 avrc_rsp.reg_notif.param.addr_player.player_id = 1977 p_param->addr_player_changed.player_id; 1978 avrc_rsp.reg_notif.param.addr_player.uid_counter = 1979 p_param->addr_player_changed.uid_counter; 1980 break; 1981 case BTRC_EVT_UIDS_CHANGED: 1982 avrc_rsp.reg_notif.param.uid_counter = 1983 p_param->uids_changed.uid_counter; 1984 break; 1985 case BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED: 1986 break; 1987 1988 default: 1989 BTIF_TRACE_WARNING("%s: Unhandled event ID: 0x%x", __func__, event_id); 1990 return BT_STATUS_UNHANDLED; 1991 } 1992 1993 /* Send the response. */ 1994 send_metamsg_rsp( 1995 &btif_rc_cb.rc_multi_cb[idx], -1, 1996 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label, 1997 ((type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_CMD_NOTIF 1998 : AVRC_RSP_CHANGED), 1999 &avrc_rsp); 2000 2001 /* if notification type is address player changed, then complete all player 2002 * specific 2003 * notifications with AV/C C-Type REJECTED with error code Addressed Player 2004 * Changed. */ 2005 if (event_id == BTRC_EVT_ADDR_PLAYER_CHANGE && 2006 type == BTRC_NOTIFICATION_TYPE_CHANGED) { 2007 /* array includes notifications to be completed on addressed player change 2008 */ 2009 btrc_event_id_t evt_id[] = { 2010 BTRC_EVT_PLAY_STATUS_CHANGED, BTRC_EVT_TRACK_CHANGE, 2011 BTRC_EVT_PLAY_POS_CHANGED, BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED}; 2012 for (uint8_t id = 0; id < sizeof(evt_id) / sizeof((evt_id)[0]); id++) { 2013 reject_pending_notification(evt_id[id], idx); 2014 } 2015 } 2016 } 2017 return BT_STATUS_SUCCESS; 2018} 2019 2020/*************************************************************************** 2021 * 2022 * Function get_folder_items_list_rsp 2023 * 2024 * Description Returns the list of media items in current folder along with 2025 * requested attributes. This is called in response to 2026 * GetFolderItems request. 2027 * 2028 * Returns bt_status_t 2029 * BT_STATUS_NOT_READY - when RC is not connected. 2030 * BT_STATUS_SUCCESS - always if RC is connected 2031 * BT_STATUS_UNHANDLED - when rsp is not pending for 2032 * get_folder_items_list PDU 2033 * 2034 **************************************************************************/ 2035static bt_status_t get_folder_items_list_rsp(bt_bdaddr_t* bd_addr, 2036 btrc_status_t rsp_status, 2037 uint16_t uid_counter, 2038 uint8_t num_items, 2039 btrc_folder_items_t* p_items) { 2040 tAVRC_RESPONSE avrc_rsp; 2041 tAVRC_ITEM item; 2042 tBTA_AV_CODE code = 0, ctype = 0; 2043 BT_HDR* p_msg = NULL; 2044 int item_cnt; 2045 tAVRC_STS status = AVRC_STS_NO_ERROR; 2046 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2047 btrc_folder_items_t* cur_item = NULL; 2048 2049 BTIF_TRACE_DEBUG("%s: uid_counter %d num_items %d", __func__, uid_counter, 2050 num_items); 2051 CHECK_RC_CONNECTED(p_dev); 2052 2053 /* check if rsp to previous cmd was completed */ 2054 if (p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending == false) { 2055 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered", 2056 __func__); 2057 return BT_STATUS_UNHANDLED; 2058 } 2059 2060 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE)); 2061 memset(&item, 0, sizeof(tAVRC_ITEM)); 2062 2063 avrc_rsp.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS; 2064 avrc_rsp.get_items.opcode = opcode_from_pdu(AVRC_PDU_GET_FOLDER_ITEMS); 2065 avrc_rsp.get_items.status = status_code_map[rsp_status]; 2066 2067 if (avrc_rsp.get_items.status != AVRC_STS_NO_ERROR) { 2068 BTIF_TRACE_WARNING( 2069 "%s: Error in parsing the received getfolderitems cmd. status: 0x%02x", 2070 __func__, avrc_rsp.get_items.status); 2071 status = avrc_rsp.get_items.status; 2072 } else { 2073 avrc_rsp.get_items.uid_counter = uid_counter; 2074 avrc_rsp.get_items.item_count = 1; 2075 2076 /* create single item and build response iteratively for all num_items */ 2077 for (item_cnt = 0; item_cnt < num_items; item_cnt++) { 2078 cur_item = &p_items[item_cnt]; 2079 item.item_type = p_items->item_type; 2080 /* build respective item based on item_type. All items should be of same 2081 * type within 2082 * a response */ 2083 switch (p_items->item_type) { 2084 case AVRC_ITEM_PLAYER: { 2085 item.u.player.name.charset_id = cur_item->player.charset_id; 2086 memcpy(&(item.u.player.features), &(cur_item->player.features), 2087 sizeof(cur_item->player.features)); 2088 item.u.player.major_type = cur_item->player.major_type; 2089 item.u.player.sub_type = cur_item->player.sub_type; 2090 item.u.player.play_status = cur_item->player.play_status; 2091 item.u.player.player_id = cur_item->player.player_id; 2092 item.u.player.name.p_str = cur_item->player.name; 2093 item.u.player.name.str_len = 2094 (uint16_t)strlen((char*)(cur_item->player.name)); 2095 } break; 2096 2097 case AVRC_ITEM_FOLDER: { 2098 memcpy(item.u.folder.uid, cur_item->folder.uid, sizeof(tAVRC_UID)); 2099 item.u.folder.type = cur_item->folder.type; 2100 item.u.folder.playable = cur_item->folder.playable; 2101 item.u.folder.name.charset_id = AVRC_CHARSET_ID_UTF8; 2102 item.u.folder.name.str_len = strlen((char*)cur_item->folder.name); 2103 item.u.folder.name.p_str = cur_item->folder.name; 2104 } break; 2105 2106 case AVRC_ITEM_MEDIA: { 2107 tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE]; 2108 2109 memcpy(item.u.media.uid, cur_item->media.uid, sizeof(tAVRC_UID)); 2110 item.u.media.type = cur_item->media.type; 2111 item.u.media.name.charset_id = cur_item->media.charset_id; 2112 item.u.media.name.str_len = strlen((char*)cur_item->media.name); 2113 item.u.media.name.p_str = cur_item->media.name; 2114 item.u.media.attr_count = cur_item->media.num_attrs; 2115 2116 /* Handle attributes of given item */ 2117 if (item.u.media.attr_count == 0) { 2118 item.u.media.p_attr_list = NULL; 2119 } else { 2120 memset(&attr_vals, 0, 2121 sizeof(tAVRC_ATTR_ENTRY) * BTRC_MAX_ELEM_ATTR_SIZE); 2122 fill_avrc_attr_entry(attr_vals, item.u.media.attr_count, 2123 cur_item->media.p_attrs); 2124 item.u.media.p_attr_list = attr_vals; 2125 } 2126 } break; 2127 2128 default: { 2129 BTIF_TRACE_ERROR("%s: Unknown item_type: %d. Internal Error", 2130 __func__, p_items->item_type); 2131 status = AVRC_STS_INTERNAL_ERR; 2132 } break; 2133 } 2134 2135 avrc_rsp.get_items.p_item_list = &item; 2136 2137 /* Add current item to buffer and build response if no error in item type 2138 */ 2139 if (status != AVRC_STS_NO_ERROR) { 2140 /* Reject response due to error occured for unknown item_type, break the 2141 * loop */ 2142 break; 2143 } 2144 2145 int len_before = p_msg ? p_msg->len : 0; 2146 BTIF_TRACE_DEBUG("%s: item_cnt: %d len: %d", __func__, item_cnt, 2147 len_before); 2148 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); 2149 BTIF_TRACE_DEBUG("%s: Build rsp status: %d len: %d", __func__, status, 2150 (p_msg ? p_msg->len : 0)); 2151 int len_after = p_msg ? p_msg->len : 0; 2152 if (status != AVRC_STS_NO_ERROR || len_before == len_after) { 2153 /* Error occured in build response or we ran out of buffer so break the 2154 * loop */ 2155 break; 2156 } 2157 } 2158 2159 /* setting the error status */ 2160 avrc_rsp.get_items.status = status; 2161 } 2162 2163 /* if packet built successfully, send the built items to BTA layer */ 2164 if (status == AVRC_STS_NO_ERROR) { 2165 code = p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype; 2166 ctype = get_rsp_type_code(avrc_rsp.get_items.status, code); 2167 BTA_AvMetaRsp(p_dev->rc_handle, 2168 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label, ctype, 2169 p_msg); 2170 } else /* Error occured, send reject response */ 2171 { 2172 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__, 2173 avrc_rsp.rsp.status); 2174 send_reject_response( 2175 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label, 2176 avrc_rsp.pdu, avrc_rsp.get_items.status, avrc_rsp.get_items.opcode); 2177 } 2178 2179 /* Reset values for current pdu. */ 2180 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype = 0; 2181 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label = 0; 2182 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending = false; 2183 2184 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 2185} 2186 2187/*************************************************************************** 2188 * 2189 * Function set_addressed_player_rsp 2190 * 2191 * Description Response to set the addressed player for specified media 2192 * player based on id in the media player list. 2193 * 2194 * Returns bt_status_t 2195 * BT_STATUS_NOT_READY - when RC is not connected. 2196 * BT_STATUS_SUCCESS - always if RC is connected 2197 * 2198 **************************************************************************/ 2199static bt_status_t set_addressed_player_rsp(bt_bdaddr_t* bd_addr, 2200 btrc_status_t rsp_status) { 2201 tAVRC_RESPONSE avrc_rsp; 2202 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2203 2204 BTIF_TRACE_DEBUG("%s", __func__); 2205 CHECK_RC_CONNECTED(p_dev); 2206 2207 avrc_rsp.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER; 2208 avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER); 2209 avrc_rsp.addr_player.status = status_code_map[rsp_status]; 2210 2211 /* Send the response. */ 2212 send_metamsg_rsp(p_dev, IDX_SET_ADDR_PLAYER_RSP, 2213 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].label, 2214 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].ctype, 2215 &avrc_rsp); 2216 2217 return BT_STATUS_SUCCESS; 2218} 2219 2220/*************************************************************************** 2221 * 2222 * Function set_browsed_player_rsp 2223 * 2224 * Description Response to set the browsed player command which contains 2225 * current browsed path of the media player. By default, 2226 * current_path = root and folder_depth = 0 for 2227 * every set_browsed_player request. 2228 * 2229 * Returns bt_status_t 2230 * BT_STATUS_NOT_READY - when RC is not connected. 2231 * BT_STATUS_SUCCESS - if RC is connected and reponse 2232 * sent successfully 2233 * BT_STATUS_UNHANDLED - when rsp is not pending for 2234 * set_browsed_player PDU 2235 * 2236 **************************************************************************/ 2237static bt_status_t set_browsed_player_rsp(bt_bdaddr_t* bd_addr, 2238 btrc_status_t rsp_status, 2239 uint32_t num_items, 2240 uint16_t charset_id, 2241 uint8_t folder_depth, 2242 btrc_br_folder_name_t* p_folders) { 2243 tAVRC_RESPONSE avrc_rsp; 2244 tAVRC_NAME item; 2245 BT_HDR* p_msg = NULL; 2246 tBTA_AV_CODE code = 0; 2247 tBTA_AV_CODE ctype = 0; 2248 unsigned int item_cnt; 2249 tAVRC_STS status = AVRC_STS_NO_ERROR; 2250 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2251 2252 CHECK_RC_CONNECTED(p_dev); 2253 2254 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE)); 2255 memset(&item, 0, sizeof(tAVRC_NAME)); 2256 2257 avrc_rsp.br_player.status = status_code_map[rsp_status]; 2258 avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER; 2259 avrc_rsp.br_player.opcode = opcode_from_pdu(AVRC_PDU_SET_BROWSED_PLAYER); 2260 2261 BTIF_TRACE_DEBUG("%s: rsp_status: 0x%02X avrc_rsp.br_player.status: 0x%02X", 2262 __func__, rsp_status, avrc_rsp.br_player.status); 2263 2264 /* check if rsp to previous cmd was completed */ 2265 if (p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending == false) { 2266 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered", 2267 __func__); 2268 return BT_STATUS_UNHANDLED; 2269 } 2270 2271 if (AVRC_STS_NO_ERROR == avrc_rsp.get_items.status) { 2272 avrc_rsp.br_player.num_items = num_items; 2273 avrc_rsp.br_player.charset_id = charset_id; 2274 avrc_rsp.br_player.folder_depth = folder_depth; 2275 avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_folders; 2276 2277 BTIF_TRACE_DEBUG("%s: folder_depth: 0x%02X num_items: %d", __func__, 2278 folder_depth, num_items); 2279 2280 if (folder_depth > 0) { 2281 /* Iteratively build response for all folders across folder depth upto 2282 * current path */ 2283 avrc_rsp.br_player.folder_depth = 1; 2284 for (item_cnt = 0; item_cnt < folder_depth; item_cnt++) { 2285 BTIF_TRACE_DEBUG("%s: iteration: %d", __func__, item_cnt); 2286 item.str_len = p_folders[item_cnt].str_len; 2287 item.p_str = p_folders[item_cnt].p_str; 2288 avrc_rsp.br_player.p_folders = &item; 2289 2290 /* Add current item to buffer and build response */ 2291 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); 2292 if (AVRC_STS_NO_ERROR != status) { 2293 BTIF_TRACE_WARNING("%s: Build rsp status: %d", __func__, status); 2294 /* if the build fails, it is likely that we ran out of buffer. so if 2295 * we have 2296 * some items to send, reset this error to no error for sending what we 2297 * have */ 2298 if (item_cnt > 0) status = AVRC_STS_NO_ERROR; 2299 2300 /* Error occured in build response so break the loop */ 2301 break; 2302 } 2303 } 2304 } else /* current path is root folder, no folders navigated yet */ 2305 { 2306 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); 2307 } 2308 2309 /* setting the error status */ 2310 avrc_rsp.br_player.status = status; 2311 } else /* error received from above layer */ 2312 { 2313 BTIF_TRACE_WARNING( 2314 "%s: Error in parsing the received setbrowsed command. status: 0x%02x", 2315 __func__, avrc_rsp.br_player.status); 2316 status = avrc_rsp.br_player.status; 2317 } 2318 2319 /* if packet built successfully, send the built items to BTA layer */ 2320 if (status == AVRC_STS_NO_ERROR) { 2321 code = p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype; 2322 ctype = get_rsp_type_code(avrc_rsp.br_player.status, code); 2323 BTA_AvMetaRsp(p_dev->rc_handle, 2324 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label, ctype, 2325 p_msg); 2326 } else /* Error occured, send reject response */ 2327 { 2328 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__, 2329 avrc_rsp.br_player.status); 2330 send_reject_response( 2331 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label, 2332 avrc_rsp.pdu, avrc_rsp.br_player.status, avrc_rsp.get_items.opcode); 2333 } 2334 2335 /* Reset values for set_browsed_player pdu.*/ 2336 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype = 0; 2337 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label = 0; 2338 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending = false; 2339 2340 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 2341} 2342 2343/******************************************************************************* 2344 * 2345 * Function change_path_rsp 2346 * 2347 * Description Response to the change path command which 2348 * contains number of items in the changed path. 2349 * 2350 * Returns bt_status_t 2351 * BT_STATUS_NOT_READY - when RC is not connected. 2352 * BT_STATUS_SUCCESS - always if RC is connected 2353 * 2354 **************************************************************************/ 2355static bt_status_t change_path_rsp(bt_bdaddr_t* bd_addr, 2356 btrc_status_t rsp_status, 2357 uint32_t num_items) { 2358 tAVRC_RESPONSE avrc_rsp; 2359 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2360 2361 BTIF_TRACE_DEBUG("%s", __func__); 2362 CHECK_RC_CONNECTED(p_dev); 2363 2364 avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH; 2365 avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH); 2366 avrc_rsp.chg_path.num_items = num_items; 2367 avrc_rsp.chg_path.status = status_code_map[rsp_status]; 2368 2369 /* Send the response. */ 2370 send_metamsg_rsp(p_dev, IDX_CHG_PATH_RSP, 2371 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].label, 2372 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].ctype, &avrc_rsp); 2373 2374 return BT_STATUS_SUCCESS; 2375} 2376 2377/*************************************************************************** 2378 * 2379 * Function search_rsp 2380 * 2381 * Description Response to search a string from media content command. 2382 * 2383 * Returns bt_status_t 2384 * BT_STATUS_NOT_READY - when RC is not connected. 2385 * BT_STATUS_SUCCESS - always if RC is connected 2386 * 2387 **************************************************************************/ 2388static bt_status_t search_rsp(bt_bdaddr_t* bd_addr, btrc_status_t rsp_status, 2389 uint32_t uid_counter, uint32_t num_items) { 2390 tAVRC_RESPONSE avrc_rsp; 2391 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2392 2393 BTIF_TRACE_DEBUG("%s", __func__); 2394 CHECK_RC_CONNECTED(p_dev); 2395 2396 avrc_rsp.search.pdu = AVRC_PDU_SEARCH; 2397 avrc_rsp.search.opcode = opcode_from_pdu(AVRC_PDU_SEARCH); 2398 avrc_rsp.search.num_items = num_items; 2399 avrc_rsp.search.uid_counter = uid_counter; 2400 avrc_rsp.search.status = status_code_map[rsp_status]; 2401 2402 /* Send the response. */ 2403 send_metamsg_rsp(p_dev, IDX_SEARCH_RSP, 2404 p_dev->rc_pdu_info[IDX_SEARCH_RSP].label, 2405 p_dev->rc_pdu_info[IDX_SEARCH_RSP].ctype, &avrc_rsp); 2406 2407 return BT_STATUS_SUCCESS; 2408} 2409/*************************************************************************** 2410 * 2411 * Function get_item_attr_rsp 2412 * 2413 * Description Response to the get item's attributes command which 2414 * contains number of attributes and values list in text. 2415 * 2416 * Returns bt_status_t 2417 * BT_STATUS_NOT_READY - when RC is not connected. 2418 * BT_STATUS_SUCCESS - always if RC is connected 2419 * 2420 **************************************************************************/ 2421static bt_status_t get_item_attr_rsp(bt_bdaddr_t* bd_addr, 2422 btrc_status_t rsp_status, uint8_t num_attr, 2423 btrc_element_attr_val_t* p_attrs) { 2424 tAVRC_RESPONSE avrc_rsp; 2425 tAVRC_ATTR_ENTRY item_attrs[BTRC_MAX_ELEM_ATTR_SIZE]; 2426 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2427 2428 BTIF_TRACE_DEBUG("%s", __func__); 2429 CHECK_RC_CONNECTED(p_dev); 2430 2431 memset(item_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr); 2432 2433 avrc_rsp.get_attrs.status = status_code_map[rsp_status]; 2434 if (rsp_status == BTRC_STS_NO_ERROR) { 2435 fill_avrc_attr_entry(item_attrs, num_attr, p_attrs); 2436 } 2437 2438 avrc_rsp.get_attrs.num_attrs = num_attr; 2439 avrc_rsp.get_attrs.p_attrs = item_attrs; 2440 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES; 2441 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES); 2442 2443 /* Send the response. */ 2444 send_metamsg_rsp(p_dev, IDX_GET_ITEM_ATTR_RSP, 2445 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].label, 2446 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].ctype, &avrc_rsp); 2447 2448 return BT_STATUS_SUCCESS; 2449} 2450 2451/*************************************************************************** 2452 * 2453 * Function add_to_now_playing_rsp 2454 * 2455 * Description Response to command for adding speciafied media item 2456 * to Now Playing queue. 2457 * 2458 * Returns bt_status_t 2459 * BT_STATUS_NOT_READY - when RC is not connected. 2460 * BT_STATUS_SUCCESS - always if RC is connected 2461 * 2462 **************************************************************************/ 2463static bt_status_t add_to_now_playing_rsp(bt_bdaddr_t* bd_addr, 2464 btrc_status_t rsp_status) { 2465 tAVRC_RESPONSE avrc_rsp; 2466 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2467 2468 BTIF_TRACE_DEBUG("%s", __func__); 2469 CHECK_RC_CONNECTED(p_dev); 2470 2471 avrc_rsp.add_to_play.pdu = AVRC_PDU_ADD_TO_NOW_PLAYING; 2472 avrc_rsp.add_to_play.opcode = opcode_from_pdu(AVRC_PDU_ADD_TO_NOW_PLAYING); 2473 avrc_rsp.add_to_play.status = status_code_map[rsp_status]; 2474 2475 /* Send the response. */ 2476 send_metamsg_rsp(p_dev, IDX_ADD_TO_NOW_PLAYING_RSP, 2477 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].label, 2478 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].ctype, 2479 &avrc_rsp); 2480 2481 return BT_STATUS_SUCCESS; 2482} 2483 2484/*************************************************************************** 2485 * 2486 * Function play_item_rsp 2487 * 2488 * Description Response to command for playing the specified media item. 2489 * 2490 * Returns bt_status_t 2491 * BT_STATUS_NOT_READY - when RC is not connected. 2492 * BT_STATUS_SUCCESS - always if RC is connected 2493 * 2494 **************************************************************************/ 2495static bt_status_t play_item_rsp(bt_bdaddr_t* bd_addr, 2496 btrc_status_t rsp_status) { 2497 tAVRC_RESPONSE avrc_rsp; 2498 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2499 2500 BTIF_TRACE_DEBUG("%s", __func__); 2501 CHECK_RC_CONNECTED(p_dev); 2502 2503 avrc_rsp.play_item.pdu = AVRC_PDU_PLAY_ITEM; 2504 avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM); 2505 avrc_rsp.play_item.status = status_code_map[rsp_status]; 2506 2507 /* Send the response. */ 2508 send_metamsg_rsp(p_dev, IDX_PLAY_ITEM_RSP, 2509 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].label, 2510 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].ctype, &avrc_rsp); 2511 2512 return BT_STATUS_SUCCESS; 2513} 2514 2515/*************************************************************************** 2516 * 2517 * Function get_total_num_of_items_rsp 2518 * 2519 * Description response to command to get the Number of Items 2520 * in the selected folder at the selected scope 2521 * 2522 * Returns bt_status_t 2523 * BT_STATUS_NOT_READY - when RC is not connected. 2524 * BT_STATUS_SUCCESS - always if RC is connected 2525 * 2526 **************************************************************************/ 2527static bt_status_t get_total_num_of_items_rsp(bt_bdaddr_t* bd_addr, 2528 btrc_status_t rsp_status, 2529 uint32_t uid_counter, 2530 uint32_t num_items) { 2531 tAVRC_RESPONSE avrc_rsp; 2532 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 2533 2534 BTIF_TRACE_DEBUG("%s", __func__); 2535 CHECK_RC_CONNECTED(p_dev); 2536 2537 avrc_rsp.get_num_of_items.pdu = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS; 2538 avrc_rsp.get_num_of_items.opcode = 2539 opcode_from_pdu(AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS); 2540 avrc_rsp.get_num_of_items.num_items = num_items; 2541 avrc_rsp.get_num_of_items.uid_counter = uid_counter; 2542 avrc_rsp.get_num_of_items.status = status_code_map[rsp_status]; 2543 2544 /* Send the response. */ 2545 send_metamsg_rsp(p_dev, IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, 2546 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].label, 2547 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].ctype, 2548 &avrc_rsp); 2549 2550 return BT_STATUS_SUCCESS; 2551} 2552 2553/*************************************************************************** 2554 * 2555 * Function set_volume 2556 * 2557 * Description Send current volume setting to remote side. 2558 * Support limited to SetAbsoluteVolume 2559 * This can be enhanced to support Relative Volume (AVRCP 1.0). 2560 * With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN 2561 * as opposed to absolute volume level 2562 * volume: Should be in the range 0-127. bit7 is reseved and cannot be set 2563 * 2564 * Returns bt_status_t 2565 * 2566 **************************************************************************/ 2567static bt_status_t set_volume(uint8_t volume) { 2568 BTIF_TRACE_DEBUG("%s: volume: %d", __func__, volume); 2569 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 2570 rc_transaction_t* p_transaction = NULL; 2571 2572 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 2573 if (!btif_rc_cb.rc_multi_cb[idx].rc_connected) { 2574 status = BT_STATUS_NOT_READY; 2575 BTIF_TRACE_ERROR("%s: RC is not connected for device: 0x%x", __func__, 2576 btif_rc_cb.rc_multi_cb[idx].rc_addr); 2577 continue; 2578 } 2579 2580 if (btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) { 2581 status = BT_STATUS_DONE; 2582 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x", __func__, 2583 volume); 2584 continue; 2585 } 2586 2587 if ((btif_rc_cb.rc_multi_cb[idx].rc_volume != volume) && 2588 btif_rc_cb.rc_multi_cb[idx].rc_state == 2589 BTRC_CONNECTION_STATE_CONNECTED) { 2590 if ((btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_RCTG) == 0) { 2591 status = BT_STATUS_NOT_READY; 2592 continue; 2593 } else { 2594 tAVRC_COMMAND avrc_cmd = {0}; 2595 BT_HDR* p_msg = NULL; 2596 2597 if (btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_ADV_CTRL) { 2598 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume: %d", 2599 __func__, volume); 2600 avrc_cmd.volume.opcode = AVRC_OP_VENDOR; 2601 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME; 2602 avrc_cmd.volume.status = AVRC_STS_NO_ERROR; 2603 avrc_cmd.volume.volume = volume; 2604 2605 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR) { 2606 bt_status_t tran_status = get_transaction(&p_transaction); 2607 2608 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) { 2609 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", 2610 __func__, p_transaction->lbl); 2611 BTA_AvMetaCmd(btif_rc_cb.rc_multi_cb[idx].rc_handle, 2612 p_transaction->lbl, AVRC_CMD_CTRL, p_msg); 2613 status = BT_STATUS_SUCCESS; 2614 } else { 2615 osi_free_and_reset((void**)&p_msg); 2616 BTIF_TRACE_ERROR( 2617 "%s: failed to obtain transaction details. status: 0x%02x", 2618 __func__, tran_status); 2619 status = BT_STATUS_FAIL; 2620 } 2621 } else { 2622 BTIF_TRACE_ERROR( 2623 "%s: failed to build absolute volume command. status: 0x%02x", 2624 __func__, status); 2625 status = BT_STATUS_FAIL; 2626 } 2627 } 2628 } 2629 } 2630 } 2631 return (bt_status_t)status; 2632} 2633 2634/*************************************************************************** 2635 * 2636 * Function register_volumechange 2637 * 2638 * Description Register for volume change notification from remote side. 2639 * 2640 * Returns void 2641 * 2642 **************************************************************************/ 2643 2644static void register_volumechange(uint8_t lbl, btif_rc_device_cb_t* p_dev) { 2645 tAVRC_COMMAND avrc_cmd = {0}; 2646 BT_HDR* p_msg = NULL; 2647 tAVRC_STS BldResp = AVRC_STS_BAD_CMD; 2648 rc_transaction_t* p_transaction = NULL; 2649 2650 BTIF_TRACE_DEBUG("%s: label: %d", __func__, lbl); 2651 2652 avrc_cmd.cmd.opcode = 0x00; 2653 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION; 2654 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE; 2655 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR; 2656 avrc_cmd.reg_notif.param = 0; 2657 2658 BldResp = AVRC_BldCommand(&avrc_cmd, &p_msg); 2659 if (AVRC_STS_NO_ERROR == BldResp && p_msg) { 2660 p_transaction = get_transaction_by_lbl(lbl); 2661 if (p_transaction != NULL) { 2662 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_NOTIF, 2663 p_msg); 2664 BTIF_TRACE_DEBUG("%s: BTA_AvMetaCmd called", __func__); 2665 } else { 2666 osi_free(p_msg); 2667 BTIF_TRACE_ERROR("%s: transaction not obtained with label: %d", __func__, 2668 lbl); 2669 } 2670 } else { 2671 BTIF_TRACE_ERROR("%s: failed to build command: %d", __func__, BldResp); 2672 } 2673} 2674 2675/*************************************************************************** 2676 * 2677 * Function handle_rc_metamsg_rsp 2678 * 2679 * Description Handle RC metamessage response 2680 * 2681 * Returns void 2682 * 2683 **************************************************************************/ 2684static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg, 2685 btif_rc_device_cb_t* p_dev) { 2686 tAVRC_RESPONSE avrc_response = {0}; 2687 uint8_t scratch_buf[512] = {0}; 2688 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 2689 2690 BTIF_TRACE_DEBUG("%s: ", __func__); 2691 2692 if (AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode && 2693 (AVRC_RSP_CHANGED == pmeta_msg->code || 2694 AVRC_RSP_INTERIM == pmeta_msg->code || 2695 AVRC_RSP_ACCEPT == pmeta_msg->code || AVRC_RSP_REJ == pmeta_msg->code || 2696 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) { 2697 status = AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, 2698 sizeof(scratch_buf)); 2699 BTIF_TRACE_DEBUG( 2700 "%s: code:%d, event ID: %d, PDU: %x, parsing status: %d, label: %d", 2701 __func__, pmeta_msg->code, avrc_response.reg_notif.event_id, 2702 avrc_response.reg_notif.pdu, status, pmeta_msg->label); 2703 2704 if (status != AVRC_STS_NO_ERROR) { 2705 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu && 2706 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id && 2707 p_dev->rc_vol_label == pmeta_msg->label) { 2708 p_dev->rc_vol_label = MAX_LABEL; 2709 release_transaction(p_dev->rc_vol_label); 2710 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) { 2711 release_transaction(pmeta_msg->label); 2712 } 2713 return; 2714 } 2715 2716 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu && 2717 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id && 2718 p_dev->rc_vol_label != pmeta_msg->label) { 2719 // Just discard the message, if the device sends back with an incorrect 2720 // label 2721 BTIF_TRACE_DEBUG( 2722 "%s: Discarding register notification in rsp.code: %d and label: %d", 2723 __func__, pmeta_msg->code, pmeta_msg->label); 2724 return; 2725 } 2726 2727 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu && 2728 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id && 2729 (AVRC_RSP_REJ == pmeta_msg->code || 2730 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) { 2731 BTIF_TRACE_DEBUG("%s remove AbsoluteVolume feature flag.", __func__); 2732 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL; 2733 handle_rc_features(p_dev); 2734 return; 2735 } 2736 } else { 2737 BTIF_TRACE_DEBUG( 2738 "%s: Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not " 2739 "processing it.", 2740 __func__, pmeta_msg->code, pmeta_msg->len); 2741 return; 2742 } 2743 2744 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu && 2745 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id && 2746 AVRC_RSP_CHANGED == pmeta_msg->code) { 2747 /* re-register for volume change notification */ 2748 // Do not re-register for rejected case, as it might get into endless loop 2749 register_volumechange(p_dev->rc_vol_label, p_dev); 2750 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) { 2751 /* free up the label here */ 2752 release_transaction(pmeta_msg->label); 2753 } 2754 2755 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s", 2756 __func__, dump_rc_pdu(avrc_response.pdu)); 2757 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, 2758 pmeta_msg->code, pmeta_msg->label, p_dev); 2759} 2760 2761/*************************************************************************** 2762 * 2763 * Function iterate_supported_event_list_for_interim_rsp 2764 * 2765 * Description iterator callback function to match the event and handle 2766 * timer cleanup 2767 * Returns true to continue iterating, false to stop 2768 * 2769 **************************************************************************/ 2770bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) { 2771 uint8_t* p_event_id; 2772 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data; 2773 2774 p_event_id = (uint8_t*)cb_data; 2775 2776 if (p_event->event_id == *p_event_id) { 2777 p_event->status = eINTERIM; 2778 return false; 2779 } 2780 return true; 2781} 2782 2783/*************************************************************************** 2784 * 2785 * Function iterate_supported_event_list_for_timeout 2786 * 2787 * Description Iterator callback function for timeout handling. 2788 * As part of the failure handling, it releases the 2789 * transaction label and removes the event from list, 2790 * this event will not be requested again during 2791 * the lifetime of the connection. 2792 * Returns false to stop iterating, true to continue 2793 * 2794 **************************************************************************/ 2795bool iterate_supported_event_list_for_timeout(void* data, void* cb_data) { 2796 bt_bdaddr_t bd_addr; 2797 rc_context_t* cntxt = (rc_context_t*)cb_data; 2798 uint8_t label = cntxt->label & 0xFF; 2799 bdcpy(bd_addr.address, cntxt->rc_addr); 2800 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&bd_addr); 2801 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data; 2802 2803 if (p_event->label == label) { 2804 list_remove(p_dev->rc_supported_event_list, p_event); 2805 return false; 2806 } 2807 return true; 2808} 2809 2810/*************************************************************************** 2811 * 2812 * Function rc_notification_interim_timout 2813 * 2814 * Description Interim response timeout handler. 2815 * Runs the iterator to check and clear the timed out event. 2816 * Proceeds to register for the unregistered events. 2817 * Returns None 2818 * 2819 **************************************************************************/ 2820static void rc_notification_interim_timout(uint8_t label, 2821 btif_rc_device_cb_t* p_dev) { 2822 list_node_t* node; 2823 rc_context_t cntxt; 2824 memset(&cntxt, 0, sizeof(rc_context_t)); 2825 cntxt.label = label; 2826 bdcpy(cntxt.rc_addr, p_dev->rc_addr); 2827 2828 list_foreach(p_dev->rc_supported_event_list, 2829 iterate_supported_event_list_for_timeout, &cntxt); 2830 /* Timeout happened for interim response for the registered event, 2831 * check if there are any pending for registration 2832 */ 2833 node = list_begin(p_dev->rc_supported_event_list); 2834 while (node != NULL) { 2835 btif_rc_supported_event_t* p_event; 2836 2837 p_event = (btif_rc_supported_event_t*)list_node(node); 2838 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) { 2839 register_for_event_notification(p_event, p_dev); 2840 break; 2841 } 2842 node = list_next(node); 2843 } 2844 /* Todo. Need to initiate application settings query if this 2845 * is the last event registration. 2846 */ 2847} 2848 2849/*************************************************************************** 2850 * 2851 * Function btif_rc_status_cmd_timeout_handler 2852 * 2853 * Description RC status command timeout handler (Runs in BTIF context). 2854 * Returns None 2855 * 2856 **************************************************************************/ 2857static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event, 2858 char* data) { 2859 btif_rc_timer_context_t* p_context; 2860 tAVRC_RESPONSE avrc_response = {0}; 2861 tBTA_AV_META_MSG meta_msg; 2862 btif_rc_device_cb_t* p_dev = NULL; 2863 bt_bdaddr_t bd_addr; 2864 2865 p_context = (btif_rc_timer_context_t*)data; 2866 bdcpy(bd_addr.address, p_context->rc_addr); 2867 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG)); 2868 p_dev = btif_rc_get_device_by_bda(&bd_addr); 2869 if (p_dev == NULL) { 2870 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 2871 return; 2872 } 2873 meta_msg.rc_handle = p_dev->rc_handle; 2874 2875 switch (p_context->rc_status_cmd.pdu_id) { 2876 case AVRC_PDU_REGISTER_NOTIFICATION: 2877 rc_notification_interim_timout(p_context->rc_status_cmd.label, p_dev); 2878 break; 2879 2880 case AVRC_PDU_GET_CAPABILITIES: 2881 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT; 2882 handle_get_capability_response(&meta_msg, &avrc_response.get_caps); 2883 break; 2884 2885 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 2886 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT; 2887 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr); 2888 break; 2889 2890 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 2891 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT; 2892 handle_app_val_response(&meta_msg, &avrc_response.list_app_values); 2893 break; 2894 2895 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: 2896 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT; 2897 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val); 2898 break; 2899 2900 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: 2901 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT; 2902 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt); 2903 break; 2904 2905 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: 2906 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT; 2907 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt); 2908 break; 2909 2910 case AVRC_PDU_GET_ELEMENT_ATTR: 2911 avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT; 2912 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_attrs); 2913 break; 2914 2915 case AVRC_PDU_GET_PLAY_STATUS: 2916 avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT; 2917 handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status); 2918 break; 2919 } 2920 release_transaction(p_context->rc_status_cmd.label); 2921} 2922 2923/*************************************************************************** 2924 * 2925 * Function btif_rc_status_cmd_timer_timeout 2926 * 2927 * Description RC status command timeout callback. 2928 * This is called from BTU context and switches to BTIF 2929 * context to handle the timeout events 2930 * Returns None 2931 * 2932 **************************************************************************/ 2933static void btif_rc_status_cmd_timer_timeout(void* data) { 2934 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data; 2935 2936 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0, (char*)p_data, 2937 sizeof(btif_rc_timer_context_t), NULL); 2938} 2939 2940/*************************************************************************** 2941 * 2942 * Function btif_rc_control_cmd_timeout_handler 2943 * 2944 * Description RC control command timeout handler (Runs in BTIF context). 2945 * Returns None 2946 * 2947 **************************************************************************/ 2948static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event, 2949 char* data) { 2950 btif_rc_timer_context_t* p_context = (btif_rc_timer_context_t*)data; 2951 tAVRC_RESPONSE avrc_response = {0}; 2952 tBTA_AV_META_MSG meta_msg; 2953 bt_bdaddr_t bd_addr; 2954 bdcpy(bd_addr.address, p_context->rc_addr); 2955 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&bd_addr); 2956 if (p_dev == NULL) { 2957 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 2958 return; 2959 } 2960 2961 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG)); 2962 meta_msg.rc_handle = p_dev->rc_handle; 2963 2964 switch (p_context->rc_control_cmd.pdu_id) { 2965 case AVRC_PDU_SET_PLAYER_APP_VALUE: 2966 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT; 2967 handle_set_app_attr_val_response(&meta_msg, &avrc_response.set_app_val); 2968 break; 2969 } 2970 release_transaction(p_context->rc_control_cmd.label); 2971} 2972 2973/*************************************************************************** 2974 * 2975 * Function btif_rc_control_cmd_timer_timeout 2976 * 2977 * Description RC control command timeout callback. 2978 * This is called from BTU context and switches to BTIF 2979 * context to handle the timeout events 2980 * Returns None 2981 * 2982 **************************************************************************/ 2983static void btif_rc_control_cmd_timer_timeout(void* data) { 2984 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data; 2985 2986 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0, (char*)p_data, 2987 sizeof(btif_rc_timer_context_t), NULL); 2988} 2989 2990/*************************************************************************** 2991 * 2992 * Function btif_rc_play_status_timeout_handler 2993 * 2994 * Description RC play status timeout handler (Runs in BTIF context). 2995 * Returns None 2996 * 2997 **************************************************************************/ 2998static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event, 2999 char* p_data) { 3000 btif_rc_handle_t* rc_handle = (btif_rc_handle_t*)p_data; 3001 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(rc_handle->handle); 3002 if (p_dev == NULL) { 3003 BTIF_TRACE_ERROR("%s timeout handler but no device found for handle %d", 3004 __func__, rc_handle->handle); 3005 return; 3006 } 3007 get_play_status_cmd(p_dev); 3008 rc_start_play_status_timer(p_dev); 3009} 3010 3011/*************************************************************************** 3012 * 3013 * Function btif_rc_play_status_timer_timeout 3014 * 3015 * Description RC play status timeout callback. 3016 * This is called from BTU context and switches to BTIF 3017 * context to handle the timeout events 3018 * Returns None 3019 * 3020 **************************************************************************/ 3021static void btif_rc_play_status_timer_timeout(void* data) { 3022 btif_rc_handle_t rc_handle; 3023 rc_handle.handle = PTR_TO_UINT(data); 3024 BTIF_TRACE_DEBUG("%s called with handle: %d", __func__, rc_handle); 3025 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 3026 (char*)(&rc_handle), sizeof(btif_rc_handle_t), NULL); 3027} 3028 3029/*************************************************************************** 3030 * 3031 * Function rc_start_play_status_timer 3032 * 3033 * Description Helper function to start the timer to fetch play status. 3034 * Returns None 3035 * 3036 **************************************************************************/ 3037static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev) { 3038 /* Start the Play status timer only if it is not started */ 3039 if (!alarm_is_scheduled(p_dev->rc_play_status_timer)) { 3040 if (p_dev->rc_play_status_timer == NULL) { 3041 p_dev->rc_play_status_timer = alarm_new("p_dev->rc_play_status_timer"); 3042 } 3043 alarm_set_on_queue(p_dev->rc_play_status_timer, 3044 BTIF_TIMEOUT_RC_INTERIM_RSP_MS, 3045 btif_rc_play_status_timer_timeout, 3046 UINT_TO_PTR(p_dev->rc_handle), btu_general_alarm_queue); 3047 } 3048} 3049 3050/*************************************************************************** 3051 * 3052 * Function rc_stop_play_status_timer 3053 * 3054 * Description Helper function to stop the play status timer. 3055 * Returns None 3056 * 3057 **************************************************************************/ 3058void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev) { 3059 alarm_cancel(p_dev->rc_play_status_timer); 3060} 3061 3062/*************************************************************************** 3063 * 3064 * Function register_for_event_notification 3065 * 3066 * Description Helper function registering notification events 3067 * sets an interim response timeout to handle if the remote 3068 * does not respond. 3069 * Returns None 3070 * 3071 **************************************************************************/ 3072static void register_for_event_notification(btif_rc_supported_event_t* p_event, 3073 btif_rc_device_cb_t* p_dev) { 3074 rc_transaction_t* p_transaction = NULL; 3075 bt_status_t status = get_transaction(&p_transaction); 3076 if (status != BT_STATUS_SUCCESS) { 3077 BTIF_TRACE_ERROR("%s: no more transaction labels: %d", __func__, status); 3078 return; 3079 } 3080 3081 status = register_notification_cmd(p_transaction->lbl, p_event->event_id, 0, 3082 p_dev); 3083 if (status != BT_STATUS_SUCCESS) { 3084 BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__, 3085 status); 3086 release_transaction(p_transaction->lbl); 3087 return; 3088 } 3089 3090 btif_rc_timer_context_t* p_context = &p_transaction->txn_timer_context; 3091 p_event->label = p_transaction->lbl; 3092 p_event->status = eREGISTERED; 3093 p_context->rc_status_cmd.label = p_transaction->lbl; 3094 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION; 3095 bdcpy(p_context->rc_addr, p_dev->rc_addr); 3096 3097 alarm_free(p_transaction->txn_timer); 3098 p_transaction->txn_timer = alarm_new("btif_rc.status_command_txn_timer"); 3099 alarm_set_on_queue(p_transaction->txn_timer, BTIF_TIMEOUT_RC_INTERIM_RSP_MS, 3100 btif_rc_status_cmd_timer_timeout, p_context, 3101 btu_general_alarm_queue); 3102} 3103 3104static void start_status_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn, 3105 btif_rc_device_cb_t* p_dev) { 3106 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context; 3107 p_context->rc_status_cmd.label = p_txn->lbl; 3108 p_context->rc_status_cmd.pdu_id = pdu_id; 3109 bdcpy(p_context->rc_addr, p_dev->rc_addr); 3110 3111 alarm_free(p_txn->txn_timer); 3112 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer"); 3113 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS, 3114 btif_rc_status_cmd_timer_timeout, p_context, 3115 btu_general_alarm_queue); 3116} 3117 3118static void start_control_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn, 3119 btif_rc_device_cb_t* p_dev) { 3120 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context; 3121 p_context->rc_control_cmd.label = p_txn->lbl; 3122 p_context->rc_control_cmd.pdu_id = pdu_id; 3123 bdcpy(p_context->rc_addr, p_dev->rc_addr); 3124 3125 alarm_free(p_txn->txn_timer); 3126 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer"); 3127 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_CONTROL_CMD_MS, 3128 btif_rc_control_cmd_timer_timeout, p_context, 3129 btu_general_alarm_queue); 3130} 3131 3132bt_status_t build_and_send_vendor_cmd(tAVRC_COMMAND* avrc_cmd, 3133 tBTA_AV_CODE cmd_code, 3134 btif_rc_device_cb_t* p_dev) { 3135 rc_transaction_t* p_transaction = NULL; 3136 bt_status_t tran_status = get_transaction(&p_transaction); 3137 if (BT_STATUS_SUCCESS != tran_status) return BT_STATUS_FAIL; 3138 3139 BT_HDR* p_msg = NULL; 3140 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg); 3141 if (status == AVRC_STS_NO_ERROR && p_msg != NULL) { 3142 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset; 3143 BTIF_TRACE_DEBUG("%s: %s msgreq being sent out with label: %d", __func__, 3144 dump_rc_pdu(avrc_cmd->pdu), p_transaction->lbl); 3145 BTA_AvVendorCmd(p_dev->rc_handle, p_transaction->lbl, cmd_code, data_start, 3146 p_msg->len); 3147 status = BT_STATUS_SUCCESS; 3148 if (cmd_code == AVRC_CMD_STATUS) { 3149 start_status_command_timer(avrc_cmd->pdu, p_transaction, p_dev); 3150 } else if (cmd_code == AVRC_CMD_CTRL) { 3151 start_control_command_timer(avrc_cmd->pdu, p_transaction, p_dev); 3152 } 3153 } else { 3154 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__, 3155 status); 3156 } 3157 osi_free(p_msg); 3158 return (bt_status_t)status; 3159} 3160 3161/*************************************************************************** 3162 * 3163 * Function handle_get_capability_response 3164 * 3165 * Description Handles the get_cap_response to populate company id info 3166 * and query the supported events. 3167 * Initiates Notification registration for events supported 3168 * Returns None 3169 * 3170 **************************************************************************/ 3171static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg, 3172 tAVRC_GET_CAPS_RSP* p_rsp) { 3173 int xx = 0; 3174 btif_rc_device_cb_t* p_dev = 3175 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3176 3177 /* Todo: Do we need to retry on command timeout */ 3178 if (p_rsp->status != AVRC_STS_NO_ERROR) { 3179 BTIF_TRACE_ERROR("%s: Error capability response: 0x%02X", __func__, 3180 p_rsp->status); 3181 return; 3182 } 3183 3184 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED) { 3185 btif_rc_supported_event_t* p_event; 3186 3187 /* Todo: Check if list can be active when we hit here */ 3188 p_dev->rc_supported_event_list = list_new(osi_free); 3189 for (xx = 0; xx < p_rsp->count; xx++) { 3190 /* Skip registering for Play position change notification */ 3191 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) || 3192 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) || 3193 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) || 3194 (p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE)) { 3195 p_event = (btif_rc_supported_event_t*)osi_malloc( 3196 sizeof(btif_rc_supported_event_t)); 3197 p_event->event_id = p_rsp->param.event_id[xx]; 3198 p_event->status = eNOT_REGISTERED; 3199 list_append(p_dev->rc_supported_event_list, p_event); 3200 } 3201 } 3202 p_event = 3203 (btif_rc_supported_event_t*)list_front(p_dev->rc_supported_event_list); 3204 if (p_event != NULL) { 3205 register_for_event_notification(p_event, p_dev); 3206 } 3207 } else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) { 3208 getcapabilities_cmd(AVRC_CAP_EVENTS_SUPPORTED, p_dev); 3209 BTIF_TRACE_EVENT("%s: AVRC_CAP_COMPANY_ID: ", __func__); 3210 for (xx = 0; xx < p_rsp->count; xx++) { 3211 BTIF_TRACE_EVENT("%s: company_id: %d", __func__, 3212 p_rsp->param.company_id[xx]); 3213 } 3214 } 3215} 3216 3217bool rc_is_track_id_valid(tAVRC_UID uid) { 3218 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 3219 3220 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0) { 3221 return false; 3222 } else { 3223 return true; 3224 } 3225} 3226 3227/*************************************************************************** 3228 * 3229 * Function handle_notification_response 3230 * 3231 * Description Main handler for notification responses to registered events 3232 * 1. Register for unregistered event(in interim response path) 3233 * 2. After registering for all supported events, start 3234 * retrieving application settings and values 3235 * 3. Reregister for events on getting changed response 3236 * 4. Run play status timer for getting position when the 3237 * status changes to playing 3238 * 5. Get the Media details when the track change happens 3239 * or track change interim response is received with 3240 * valid track id 3241 * 6. HAL callback for play status change and application 3242 * setting change 3243 * Returns None 3244 * 3245 **************************************************************************/ 3246static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg, 3247 tAVRC_REG_NOTIF_RSP* p_rsp) { 3248 bt_bdaddr_t rc_addr; 3249 btif_rc_device_cb_t* p_dev = 3250 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3251 uint32_t attr_list[] = { 3252 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST, 3253 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM, 3254 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE, 3255 AVRC_MEDIA_ATTR_ID_PLAYING_TIME}; 3256 3257 if (p_dev == NULL) { 3258 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3259 return; 3260 } 3261 3262 bdcpy(rc_addr.address, p_dev->rc_addr); 3263 3264 if (pmeta_msg->code == AVRC_RSP_INTERIM) { 3265 btif_rc_supported_event_t* p_event; 3266 list_node_t* node; 3267 3268 BTIF_TRACE_DEBUG("%s: Interim response: 0x%2X ", __func__, p_rsp->event_id); 3269 switch (p_rsp->event_id) { 3270 case AVRC_EVT_PLAY_STATUS_CHANGE: 3271 /* Start timer to get play status periodically 3272 * if the play state is playing. 3273 */ 3274 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) { 3275 rc_start_play_status_timer(p_dev); 3276 } 3277 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr, 3278 (btrc_play_status_t)p_rsp->param.play_status); 3279 break; 3280 3281 case AVRC_EVT_TRACK_CHANGE: 3282 if (rc_is_track_id_valid(p_rsp->param.track) != true) { 3283 break; 3284 } else { 3285 uint8_t* p_data = p_rsp->param.track; 3286 /* Update the UID for current track 3287 * Attributes will be fetched after the AVRCP procedure 3288 */ 3289 BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data); 3290 } 3291 break; 3292 3293 case AVRC_EVT_APP_SETTING_CHANGE: 3294 break; 3295 3296 case AVRC_EVT_NOW_PLAYING_CHANGE: 3297 break; 3298 3299 case AVRC_EVT_AVAL_PLAYERS_CHANGE: 3300 break; 3301 3302 case AVRC_EVT_ADDR_PLAYER_CHANGE: 3303 break; 3304 3305 case AVRC_EVT_UIDS_CHANGE: 3306 break; 3307 3308 case AVRC_EVT_TRACK_REACHED_END: 3309 case AVRC_EVT_TRACK_REACHED_START: 3310 case AVRC_EVT_PLAY_POS_CHANGED: 3311 case AVRC_EVT_BATTERY_STATUS_CHANGE: 3312 case AVRC_EVT_SYSTEM_STATUS_CHANGE: 3313 default: 3314 BTIF_TRACE_ERROR("%s: Unhandled interim response: 0x%2X", __func__, 3315 p_rsp->event_id); 3316 return; 3317 } 3318 3319 list_foreach(p_dev->rc_supported_event_list, 3320 iterate_supported_event_list_for_interim_rsp, 3321 &p_rsp->event_id); 3322 3323 node = list_begin(p_dev->rc_supported_event_list); 3324 3325 while (node != NULL) { 3326 p_event = (btif_rc_supported_event_t*)list_node(node); 3327 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) { 3328 register_for_event_notification(p_event, p_dev); 3329 break; 3330 } 3331 node = list_next(node); 3332 p_event = NULL; 3333 } 3334 /* Registered for all events, we can request application settings */ 3335 if (p_event == NULL && p_dev->rc_app_settings.query_started == false) { 3336 /* we need to do this only if remote TG supports 3337 * player application settings 3338 */ 3339 p_dev->rc_app_settings.query_started = true; 3340 if (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING) { 3341 list_player_app_setting_attrib_cmd(p_dev); 3342 } else { 3343 BTIF_TRACE_DEBUG("%s: App setting not supported, complete procedure", 3344 __func__); 3345 rc_ctrl_procedure_complete(p_dev); 3346 } 3347 } 3348 } else if (pmeta_msg->code == AVRC_RSP_CHANGED) { 3349 btif_rc_supported_event_t* p_event; 3350 list_node_t* node; 3351 3352 BTIF_TRACE_DEBUG("%s: Notification completed: 0x%2X ", __func__, 3353 p_rsp->event_id); 3354 3355 node = list_begin(p_dev->rc_supported_event_list); 3356 3357 while (node != NULL) { 3358 p_event = (btif_rc_supported_event_t*)list_node(node); 3359 if (p_event != NULL && p_event->event_id == p_rsp->event_id) { 3360 p_event->status = eNOT_REGISTERED; 3361 register_for_event_notification(p_event, p_dev); 3362 break; 3363 } 3364 node = list_next(node); 3365 } 3366 3367 switch (p_rsp->event_id) { 3368 case AVRC_EVT_PLAY_STATUS_CHANGE: 3369 /* Start timer to get play status periodically 3370 * if the play state is playing. 3371 */ 3372 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) { 3373 rc_start_play_status_timer(p_dev); 3374 } else { 3375 rc_stop_play_status_timer(p_dev); 3376 } 3377 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr, 3378 (btrc_play_status_t)p_rsp->param.play_status); 3379 3380 break; 3381 3382 case AVRC_EVT_TRACK_CHANGE: 3383 if (rc_is_track_id_valid(p_rsp->param.track) != true) { 3384 break; 3385 } 3386 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev); 3387 break; 3388 3389 case AVRC_EVT_APP_SETTING_CHANGE: { 3390 btrc_player_settings_t app_settings; 3391 uint16_t xx; 3392 3393 app_settings.num_attr = p_rsp->param.player_setting.num_attr; 3394 for (xx = 0; xx < app_settings.num_attr; xx++) { 3395 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx]; 3396 app_settings.attr_values[xx] = 3397 p_rsp->param.player_setting.attr_value[xx]; 3398 } 3399 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb, 3400 &rc_addr, &app_settings); 3401 } break; 3402 3403 case AVRC_EVT_NOW_PLAYING_CHANGE: 3404 break; 3405 3406 case AVRC_EVT_AVAL_PLAYERS_CHANGE: 3407 break; 3408 3409 case AVRC_EVT_ADDR_PLAYER_CHANGE: 3410 break; 3411 3412 case AVRC_EVT_UIDS_CHANGE: 3413 break; 3414 3415 case AVRC_EVT_TRACK_REACHED_END: 3416 case AVRC_EVT_TRACK_REACHED_START: 3417 case AVRC_EVT_PLAY_POS_CHANGED: 3418 case AVRC_EVT_BATTERY_STATUS_CHANGE: 3419 case AVRC_EVT_SYSTEM_STATUS_CHANGE: 3420 default: 3421 BTIF_TRACE_ERROR("%s: Unhandled completion response: 0x%2X", __func__, 3422 p_rsp->event_id); 3423 return; 3424 } 3425 } 3426} 3427 3428/*************************************************************************** 3429 * 3430 * Function handle_app_attr_response 3431 * 3432 * Description handles the the application attributes response and 3433 * initiates procedure to fetch the attribute values 3434 * Returns None 3435 * 3436 **************************************************************************/ 3437static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg, 3438 tAVRC_LIST_APP_ATTR_RSP* p_rsp) { 3439 uint8_t xx; 3440 btif_rc_device_cb_t* p_dev = 3441 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3442 3443 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) { 3444 BTIF_TRACE_ERROR("%s: Error getting Player application settings: 0x%2X", 3445 __func__, p_rsp->status); 3446 rc_ctrl_procedure_complete(p_dev); 3447 return; 3448 } 3449 3450 for (xx = 0; xx < p_rsp->num_attr; xx++) { 3451 uint8_t st_index; 3452 3453 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT) { 3454 st_index = p_dev->rc_app_settings.num_ext_attrs; 3455 p_dev->rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx]; 3456 p_dev->rc_app_settings.num_ext_attrs++; 3457 } else { 3458 st_index = p_dev->rc_app_settings.num_attrs; 3459 p_dev->rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx]; 3460 p_dev->rc_app_settings.num_attrs++; 3461 } 3462 } 3463 p_dev->rc_app_settings.attr_index = 0; 3464 p_dev->rc_app_settings.ext_attr_index = 0; 3465 p_dev->rc_app_settings.ext_val_index = 0; 3466 if (p_rsp->num_attr) { 3467 list_player_app_setting_value_cmd(p_dev->rc_app_settings.attrs[0].attr_id, 3468 p_dev); 3469 } else { 3470 BTIF_TRACE_ERROR("%s: No Player application settings found", __func__); 3471 } 3472} 3473 3474/*************************************************************************** 3475 * 3476 * Function handle_app_val_response 3477 * 3478 * Description handles the the attributes value response and if extended 3479 * menu is available, it initiates query for the attribute 3480 * text. If not, it initiates procedure to get the current 3481 * attribute values and calls the HAL callback for provding 3482 * application settings information. 3483 * Returns None 3484 * 3485 **************************************************************************/ 3486static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg, 3487 tAVRC_LIST_APP_VALUES_RSP* p_rsp) { 3488 uint8_t xx, attr_index; 3489 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE]; 3490 btif_rc_player_app_settings_t* p_app_settings; 3491 bt_bdaddr_t rc_addr; 3492 btif_rc_device_cb_t* p_dev = 3493 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3494 3495 /* Todo: Do we need to retry on command timeout */ 3496 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) { 3497 BTIF_TRACE_ERROR("%s: Error fetching attribute values: 0x%02X", __func__, 3498 p_rsp->status); 3499 return; 3500 } 3501 3502 p_app_settings = &p_dev->rc_app_settings; 3503 bdcpy(rc_addr.address, p_dev->rc_addr); 3504 3505 if (p_app_settings->attr_index < p_app_settings->num_attrs) { 3506 attr_index = p_app_settings->attr_index; 3507 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val; 3508 for (xx = 0; xx < p_rsp->num_val; xx++) { 3509 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx]; 3510 } 3511 attr_index++; 3512 p_app_settings->attr_index++; 3513 if (attr_index < p_app_settings->num_attrs) { 3514 list_player_app_setting_value_cmd( 3515 p_app_settings->attrs[p_app_settings->attr_index].attr_id, p_dev); 3516 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) { 3517 attr_index = 0; 3518 p_app_settings->ext_attr_index = 0; 3519 list_player_app_setting_value_cmd( 3520 p_app_settings->ext_attrs[attr_index].attr_id, p_dev); 3521 } else { 3522 for (xx = 0; xx < p_app_settings->num_attrs; xx++) { 3523 attrs[xx] = p_app_settings->attrs[xx].attr_id; 3524 } 3525 get_player_app_setting_cmd(p_app_settings->num_attrs, attrs, p_dev); 3526 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr, 3527 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL); 3528 } 3529 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) { 3530 attr_index = p_app_settings->ext_attr_index; 3531 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val; 3532 for (xx = 0; xx < p_rsp->num_val; xx++) { 3533 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = 3534 p_rsp->vals[xx]; 3535 } 3536 attr_index++; 3537 p_app_settings->ext_attr_index++; 3538 if (attr_index < p_app_settings->num_ext_attrs) { 3539 list_player_app_setting_value_cmd( 3540 p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id, 3541 p_dev); 3542 } else { 3543 uint8_t attr[AVRC_MAX_APP_ATTR_SIZE]; 3544 3545 for (uint8_t xx = 0; xx < p_app_settings->num_ext_attrs; xx++) { 3546 attr[xx] = p_app_settings->ext_attrs[xx].attr_id; 3547 } 3548 get_player_app_setting_attr_text_cmd(attr, p_app_settings->num_ext_attrs, 3549 p_dev); 3550 } 3551 } 3552} 3553 3554/*************************************************************************** 3555 * 3556 * Function handle_app_cur_val_response 3557 * 3558 * Description handles the the get attributes value response. 3559 * 3560 * Returns None 3561 * 3562 **************************************************************************/ 3563static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg, 3564 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp) { 3565 btrc_player_settings_t app_settings; 3566 bt_bdaddr_t rc_addr; 3567 uint16_t xx; 3568 btif_rc_device_cb_t* p_dev = NULL; 3569 3570 /* Todo: Do we need to retry on command timeout */ 3571 if (p_rsp->status != AVRC_STS_NO_ERROR) { 3572 BTIF_TRACE_ERROR("%s: Error fetching current settings: 0x%02X", __func__, 3573 p_rsp->status); 3574 return; 3575 } 3576 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3577 if (p_dev == NULL) { 3578 BTIF_TRACE_ERROR("%s: Error in getting Device Address", __func__); 3579 osi_free_and_reset((void**)&p_rsp->p_vals); 3580 return; 3581 } 3582 3583 bdcpy(rc_addr.address, p_dev->rc_addr); 3584 3585 app_settings.num_attr = p_rsp->num_val; 3586 for (xx = 0; xx < app_settings.num_attr; xx++) { 3587 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id; 3588 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val; 3589 } 3590 3591 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb, &rc_addr, 3592 &app_settings); 3593 /* Application settings are fetched only once for initial values 3594 * initiate anything that follows after RC procedure. 3595 * Defer it if browsing is supported till players query 3596 */ 3597 rc_ctrl_procedure_complete(p_dev); 3598 osi_free_and_reset((void**)&p_rsp->p_vals); 3599} 3600 3601/*************************************************************************** 3602 * 3603 * Function handle_app_attr_txt_response 3604 * 3605 * Description handles the the get attributes text response, if fails 3606 * calls HAL callback with just normal settings and initiates 3607 * query for current settings else initiates query for value 3608 * text 3609 * Returns None 3610 * 3611 **************************************************************************/ 3612static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg, 3613 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) { 3614 uint8_t xx; 3615 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE]; 3616 btif_rc_player_app_settings_t* p_app_settings; 3617 bt_bdaddr_t rc_addr; 3618 btif_rc_device_cb_t* p_dev = 3619 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3620 3621 if (p_dev == NULL) { 3622 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3623 return; 3624 } 3625 3626 bdcpy(rc_addr.address, p_dev->rc_addr); 3627 p_app_settings = &p_dev->rc_app_settings; 3628 3629 /* Todo: Do we need to retry on command timeout */ 3630 if (p_rsp->status != AVRC_STS_NO_ERROR) { 3631 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE]; 3632 3633 BTIF_TRACE_ERROR("%s: Error fetching attribute text: 0x%02X", __func__, 3634 p_rsp->status); 3635 /* Not able to fetch Text for extended Menu, skip the process 3636 * and cleanup used memory. Proceed to get the current settings 3637 * for standard attributes. 3638 */ 3639 p_app_settings->num_ext_attrs = 0; 3640 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) { 3641 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str); 3642 } 3643 p_app_settings->ext_attr_index = 0; 3644 3645 if (p_dev) { 3646 for (xx = 0; xx < p_app_settings->num_attrs; xx++) { 3647 attrs[xx] = p_app_settings->attrs[xx].attr_id; 3648 } 3649 3650 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr, 3651 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL); 3652 get_player_app_setting_cmd(xx, attrs, p_dev); 3653 } 3654 return; 3655 } 3656 3657 for (xx = 0; xx < p_rsp->num_attr; xx++) { 3658 uint8_t x; 3659 for (x = 0; x < p_app_settings->num_ext_attrs; x++) { 3660 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id) { 3661 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id; 3662 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len; 3663 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str; 3664 break; 3665 } 3666 } 3667 } 3668 3669 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++) { 3670 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val; 3671 } 3672 get_player_app_setting_value_text_cmd(vals, xx, p_dev); 3673} 3674 3675/*************************************************************************** 3676 * 3677 * Function handle_app_attr_val_txt_response 3678 * 3679 * Description handles the the get attributes value text response, if fails 3680 * calls HAL callback with just normal settings and initiates 3681 * query for current settings 3682 * Returns None 3683 * 3684 **************************************************************************/ 3685static void handle_app_attr_val_txt_response( 3686 tBTA_AV_META_MSG* pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) { 3687 uint8_t xx, attr_index; 3688 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE]; 3689 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE]; 3690 btif_rc_player_app_settings_t* p_app_settings; 3691 bt_bdaddr_t rc_addr; 3692 btif_rc_device_cb_t* p_dev = 3693 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3694 3695 if (p_dev == NULL) { 3696 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3697 return; 3698 } 3699 3700 bdcpy(rc_addr.address, p_dev->rc_addr); 3701 p_app_settings = &p_dev->rc_app_settings; 3702 3703 /* Todo: Do we need to retry on command timeout */ 3704 if (p_rsp->status != AVRC_STS_NO_ERROR) { 3705 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE]; 3706 3707 BTIF_TRACE_ERROR("%s: Error fetching attribute value text: 0x%02X", 3708 __func__, p_rsp->status); 3709 3710 /* Not able to fetch Text for extended Menu, skip the process 3711 * and cleanup used memory. Proceed to get the current settings 3712 * for standard attributes. 3713 */ 3714 p_app_settings->num_ext_attrs = 0; 3715 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) { 3716 int x; 3717 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx]; 3718 3719 for (x = 0; x < p_ext_attr->num_val; x++) 3720 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str); 3721 p_ext_attr->num_val = 0; 3722 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str); 3723 } 3724 p_app_settings->ext_attr_index = 0; 3725 3726 for (xx = 0; xx < p_app_settings->num_attrs; xx++) { 3727 attrs[xx] = p_app_settings->attrs[xx].attr_id; 3728 } 3729 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr, 3730 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL); 3731 3732 get_player_app_setting_cmd(xx, attrs, p_dev); 3733 return; 3734 } 3735 3736 for (xx = 0; xx < p_rsp->num_attr; xx++) { 3737 uint8_t x; 3738 btrc_player_app_ext_attr_t* p_ext_attr; 3739 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index]; 3740 for (x = 0; x < p_rsp->num_attr; x++) { 3741 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id) { 3742 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id; 3743 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len; 3744 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str; 3745 break; 3746 } 3747 } 3748 } 3749 p_app_settings->ext_val_index++; 3750 3751 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs) { 3752 attr_index = p_app_settings->ext_val_index; 3753 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++) { 3754 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val; 3755 } 3756 get_player_app_setting_value_text_cmd(vals, xx, p_dev); 3757 } else { 3758 uint8_t x; 3759 3760 for (xx = 0; xx < p_app_settings->num_attrs; xx++) { 3761 attrs[xx] = p_app_settings->attrs[xx].attr_id; 3762 } 3763 for (x = 0; x < p_app_settings->num_ext_attrs; x++) { 3764 attrs[xx + x] = p_app_settings->ext_attrs[x].attr_id; 3765 } 3766 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr, 3767 p_app_settings->num_attrs, p_app_settings->attrs, 3768 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs); 3769 get_player_app_setting_cmd(xx + x, attrs, p_dev); 3770 3771 /* Free the application settings information after sending to 3772 * application. 3773 */ 3774 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) { 3775 int x; 3776 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx]; 3777 3778 for (x = 0; x < p_ext_attr->num_val; x++) 3779 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str); 3780 p_ext_attr->num_val = 0; 3781 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str); 3782 } 3783 p_app_settings->num_attrs = 0; 3784 } 3785} 3786 3787/*************************************************************************** 3788 * 3789 * Function handle_set_app_attr_val_response 3790 * 3791 * Description handles the the set attributes value response, if fails 3792 * calls HAL callback to indicate the failure 3793 * Returns None 3794 * 3795 **************************************************************************/ 3796static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, 3797 tAVRC_RSP* p_rsp) { 3798 uint8_t accepted = 0; 3799 bt_bdaddr_t rc_addr; 3800 btif_rc_device_cb_t* p_dev = 3801 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3802 3803 if (p_dev == NULL) { 3804 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3805 return; 3806 } 3807 3808 bdcpy(rc_addr.address, p_dev->rc_addr); 3809 3810 /* For timeout pmeta_msg will be NULL, else we need to 3811 * check if this is accepted by TG 3812 */ 3813 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT)) { 3814 accepted = 1; 3815 } 3816 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, 3817 accepted); 3818} 3819 3820/*************************************************************************** 3821 * 3822 * Function handle_get_elem_attr_response 3823 * 3824 * Description handles the the element attributes response, calls 3825 * HAL callback to update track change information. 3826 * Returns None 3827 * 3828 **************************************************************************/ 3829static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg, 3830 tAVRC_GET_ATTRS_RSP* p_rsp) { 3831 btif_rc_device_cb_t* p_dev = 3832 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3833 3834 if (p_rsp->status == AVRC_STS_NO_ERROR) { 3835 bt_bdaddr_t rc_addr; 3836 size_t buf_size = p_rsp->num_attrs * sizeof(btrc_element_attr_val_t); 3837 btrc_element_attr_val_t* p_attr = 3838 (btrc_element_attr_val_t*)osi_calloc(buf_size); 3839 3840 if (p_dev == NULL) { 3841 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3842 return; 3843 } 3844 3845 bdcpy(rc_addr.address, p_dev->rc_addr); 3846 3847 for (int i = 0; i < p_rsp->num_attrs; i++) { 3848 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id; 3849 /* Todo. Legth limit check to include null */ 3850 if (p_rsp->p_attrs[i].name.str_len && p_rsp->p_attrs[i].name.p_str) { 3851 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str, 3852 p_rsp->p_attrs[i].name.str_len); 3853 osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str); 3854 } 3855 } 3856 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb, &rc_addr, 3857 p_rsp->num_attrs, p_attr); 3858 osi_free(p_attr); 3859 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) { 3860 /* Retry for timeout case, this covers error handling 3861 * for continuation failure also. 3862 */ 3863 uint32_t attr_list[] = { 3864 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST, 3865 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM, 3866 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE, 3867 AVRC_MEDIA_ATTR_ID_PLAYING_TIME}; 3868 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev); 3869 } else { 3870 BTIF_TRACE_ERROR("%s: Error in get element attr procedure: %d", __func__, 3871 p_rsp->status); 3872 } 3873} 3874 3875/*************************************************************************** 3876 * 3877 * Function handle_get_playstatus_response 3878 * 3879 * Description handles the the play status response, calls 3880 * HAL callback to update play position. 3881 * Returns None 3882 * 3883 **************************************************************************/ 3884static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg, 3885 tAVRC_GET_PLAY_STATUS_RSP* p_rsp) { 3886 bt_bdaddr_t rc_addr; 3887 3888 btif_rc_device_cb_t* p_dev = 3889 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3890 3891 if (p_dev == NULL) { 3892 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3893 return; 3894 } 3895 3896 bdcpy(rc_addr.address, p_dev->rc_addr); 3897 3898 if (p_rsp->status == AVRC_STS_NO_ERROR) { 3899 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb, &rc_addr, 3900 p_rsp->song_len, p_rsp->song_pos); 3901 } else { 3902 BTIF_TRACE_ERROR("%s: Error in get play status procedure: %d", __func__, 3903 p_rsp->status); 3904 } 3905} 3906 3907/*************************************************************************** 3908 * 3909 * Function handle_set_addressed_player_response 3910 * 3911 * Description handles the the set addressed player response, calls 3912 * HAL callback 3913 * Returns None 3914 * 3915 **************************************************************************/ 3916static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg, 3917 tAVRC_RSP* p_rsp) { 3918 bt_bdaddr_t rc_addr; 3919 3920 btif_rc_device_cb_t* p_dev = 3921 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3922 3923 if (p_dev == NULL) { 3924 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__); 3925 return; 3926 } 3927 3928 bdcpy(rc_addr.address, p_dev->rc_addr); 3929 3930 if (p_rsp->status == AVRC_STS_NO_ERROR) { 3931 HAL_CBACK(bt_rc_ctrl_callbacks, set_addressed_player_cb, &rc_addr, 3932 p_rsp->status); 3933 } else { 3934 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d", __func__, 3935 p_rsp->status); 3936 } 3937} 3938 3939/*************************************************************************** 3940 * 3941 * Function handle_get_folder_items_response 3942 * 3943 * Description handles the the get folder items response, calls 3944 * HAL callback to send the folder items. 3945 * Returns None 3946 * 3947 **************************************************************************/ 3948static void handle_get_folder_items_response(tBTA_AV_META_MSG* pmeta_msg, 3949 tAVRC_GET_ITEMS_RSP* p_rsp) { 3950 btif_rc_device_cb_t* p_dev = 3951 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 3952 bt_bdaddr_t rc_addr; 3953 bdcpy(rc_addr.address, p_dev->rc_addr); 3954 3955 if (p_rsp->status == AVRC_STS_NO_ERROR) { 3956 /* Convert the internal folder listing into a response that can 3957 * be passed onto JNI via HAL_CBACK 3958 */ 3959 uint8_t item_count = p_rsp->item_count; 3960 btrc_folder_items_t* btrc_items = (btrc_folder_items_t*)osi_malloc( 3961 sizeof(btrc_folder_items_t) * item_count); 3962 for (uint8_t i = 0; i < item_count; i++) { 3963 const tAVRC_ITEM* avrc_item = &(p_rsp->p_item_list[i]); 3964 btrc_folder_items_t* btrc_item = &(btrc_items[i]); 3965 BTIF_TRACE_DEBUG("%s folder item type %d", __func__, 3966 avrc_item->item_type); 3967 switch (avrc_item->item_type) { 3968 case AVRC_ITEM_MEDIA: 3969 BTIF_TRACE_DEBUG("%s setting type to %d", __func__, BTRC_ITEM_MEDIA); 3970 get_folder_item_type_media(avrc_item, btrc_item); 3971 break; 3972 3973 case AVRC_ITEM_FOLDER: 3974 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_FOLDER", __func__); 3975 get_folder_item_type_folder(avrc_item, btrc_item); 3976 break; 3977 3978 case AVRC_ITEM_PLAYER: 3979 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_PLAYER", __func__); 3980 get_folder_item_type_player(avrc_item, btrc_item); 3981 break; 3982 3983 default: 3984 BTIF_TRACE_ERROR("%s cannot understand folder item type %d", __func__, 3985 avrc_item->item_type); 3986 } 3987 } 3988 3989 HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr, 3990 BTRC_STS_NO_ERROR, 3991 /* We want to make the ownership explicit in native */ 3992 (const btrc_folder_items_t*)btrc_items, item_count); 3993 BTIF_TRACE_DEBUG("%s HAL CBACK get_folder_items_cb finished", __func__); 3994 3995 /* Release the memory block for items since we OWN the object */ 3996 osi_free(btrc_items); 3997 } else { 3998 BTIF_TRACE_ERROR("%s: Error %d", __func__, p_rsp->status); 3999 HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr, 4000 (btrc_status_t)p_rsp->status, NULL, 0); 4001 } 4002} 4003 4004/*************************************************************************** 4005 * 4006 * Function get_folder_item_type_media 4007 * 4008 * Description Converts the AVRC representation of a folder item with 4009 * TYPE media to BTIF representation. 4010 * Returns None 4011 * 4012 **************************************************************************/ 4013void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, 4014 btrc_folder_items_t* btrc_item) { 4015 btrc_item->item_type = BTRC_ITEM_MEDIA; 4016 const tAVRC_ITEM_MEDIA* avrc_item_media = &(avrc_item->u.media); 4017 btrc_item_media_t* btrc_item_media = &(btrc_item->media); 4018 /* UID */ 4019 memset(btrc_item_media->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t)); 4020 memcpy(btrc_item_media->uid, avrc_item_media->uid, 4021 sizeof(uint8_t) * BTRC_UID_SIZE); 4022 4023 /* Audio/Video type */ 4024 switch (avrc_item_media->type) { 4025 case AVRC_MEDIA_TYPE_AUDIO: 4026 btrc_item_media->type = BTRC_MEDIA_TYPE_AUDIO; 4027 break; 4028 case AVRC_MEDIA_TYPE_VIDEO: 4029 btrc_item_media->type = BTRC_MEDIA_TYPE_VIDEO; 4030 break; 4031 } 4032 4033 /* Charset ID */ 4034 btrc_item_media->charset_id = avrc_item_media->name.charset_id; 4035 4036 /* Copy the name */ 4037 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN, 4038 avrc_item_media->name.str_len); 4039 memset(btrc_item_media->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t)); 4040 memcpy(btrc_item_media->name, avrc_item_media->name.p_str, 4041 sizeof(uint8_t) * (avrc_item_media->name.str_len)); 4042 4043 /* Copy the parameters */ 4044 btrc_item_media->num_attrs = avrc_item_media->attr_count; 4045 btrc_item_media->p_attrs = (btrc_element_attr_val_t*)osi_malloc( 4046 btrc_item_media->num_attrs * sizeof(btrc_element_attr_val_t)); 4047 4048 /* Extract each attribute */ 4049 for (int i = 0; i < avrc_item_media->attr_count; i++) { 4050 btrc_element_attr_val_t* btrc_attr_pair = &(btrc_item_media->p_attrs[i]); 4051 tAVRC_ATTR_ENTRY* avrc_attr_pair = &(avrc_item_media->p_attr_list[i]); 4052 4053 BTIF_TRACE_DEBUG("%s media attr id 0x%x", __func__, 4054 avrc_attr_pair->attr_id); 4055 4056 switch (avrc_attr_pair->attr_id) { 4057 case AVRC_MEDIA_ATTR_ID_TITLE: 4058 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TITLE; 4059 break; 4060 case AVRC_MEDIA_ATTR_ID_ARTIST: 4061 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ARTIST; 4062 break; 4063 case AVRC_MEDIA_ATTR_ID_ALBUM: 4064 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ALBUM; 4065 break; 4066 case AVRC_MEDIA_ATTR_ID_TRACK_NUM: 4067 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TRACK_NUM; 4068 break; 4069 case AVRC_MEDIA_ATTR_ID_NUM_TRACKS: 4070 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_NUM_TRACKS; 4071 break; 4072 case AVRC_MEDIA_ATTR_ID_GENRE: 4073 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_GENRE; 4074 break; 4075 case AVRC_MEDIA_ATTR_ID_PLAYING_TIME: 4076 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_PLAYING_TIME; 4077 break; 4078 default: 4079 BTIF_TRACE_ERROR("%s invalid media attr id: 0x%x", __func__, 4080 avrc_attr_pair->attr_id); 4081 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_INVALID; 4082 } 4083 4084 memset(btrc_attr_pair->text, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t)); 4085 memcpy(btrc_attr_pair->text, avrc_attr_pair->name.p_str, 4086 avrc_attr_pair->name.str_len); 4087 } 4088} 4089 4090/*************************************************************************** 4091 * 4092 * Function get_folder_item_type_folder 4093 * 4094 * Description Converts the AVRC representation of a folder item with 4095 * TYPE folder to BTIF representation. 4096 * Returns None 4097 * 4098 **************************************************************************/ 4099void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, 4100 btrc_folder_items_t* btrc_item) { 4101 btrc_item->item_type = BTRC_ITEM_FOLDER; 4102 const tAVRC_ITEM_FOLDER* avrc_item_folder = &(avrc_item->u.folder); 4103 btrc_item_folder_t* btrc_item_folder = &(btrc_item->folder); 4104 /* Copy the UID */ 4105 memset(btrc_item_folder->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t)); 4106 memcpy(btrc_item_folder->uid, avrc_item_folder->uid, 4107 sizeof(uint8_t) * BTRC_UID_SIZE); 4108 4109 /* Copy the type */ 4110 switch (avrc_item_folder->type) { 4111 case AVRC_FOLDER_TYPE_MIXED: 4112 btrc_item_folder->type = BTRC_FOLDER_TYPE_MIXED; 4113 break; 4114 case AVRC_FOLDER_TYPE_TITLES: 4115 btrc_item_folder->type = BTRC_FOLDER_TYPE_TITLES; 4116 break; 4117 case AVRC_FOLDER_TYPE_ALNUMS: 4118 btrc_item_folder->type = BTRC_FOLDER_TYPE_ALBUMS; 4119 break; 4120 case AVRC_FOLDER_TYPE_ARTISTS: 4121 btrc_item_folder->type = BTRC_FOLDER_TYPE_ARTISTS; 4122 break; 4123 case AVRC_FOLDER_TYPE_GENRES: 4124 btrc_item_folder->type = BTRC_FOLDER_TYPE_GENRES; 4125 break; 4126 case AVRC_FOLDER_TYPE_PLAYLISTS: 4127 btrc_item_folder->type = BTRC_FOLDER_TYPE_PLAYLISTS; 4128 break; 4129 case AVRC_FOLDER_TYPE_YEARS: 4130 btrc_item_folder->type = BTRC_FOLDER_TYPE_YEARS; 4131 break; 4132 } 4133 4134 /* Copy if playable */ 4135 btrc_item_folder->playable = avrc_item_folder->playable; 4136 4137 /* Copy name */ 4138 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN, 4139 avrc_item_folder->name.str_len); 4140 memset(btrc_item_folder->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t)); 4141 memcpy(btrc_item_folder->name, avrc_item_folder->name.p_str, 4142 avrc_item_folder->name.str_len * sizeof(uint8_t)); 4143 4144 /* Copy charset */ 4145 btrc_item_folder->charset_id = avrc_item_folder->name.charset_id; 4146} 4147 4148/*************************************************************************** 4149 * 4150 * Function get_folder_item_type_player 4151 * 4152 * Description Converts the AVRC representation of a folder item with 4153 * TYPE player to BTIF representation. 4154 * Returns None 4155 * 4156 **************************************************************************/ 4157void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, 4158 btrc_folder_items_t* btrc_item) { 4159 btrc_item->item_type = BTRC_ITEM_PLAYER; 4160 const tAVRC_ITEM_PLAYER* avrc_item_player = &(avrc_item->u.player); 4161 btrc_item_player_t* btrc_item_player = &(btrc_item->player); 4162 /* Player ID */ 4163 btrc_item_player->player_id = avrc_item_player->player_id; 4164 /* Major type */ 4165 btrc_item_player->major_type = avrc_item_player->major_type; 4166 /* Sub type */ 4167 btrc_item_player->sub_type = avrc_item_player->sub_type; 4168 /* Features */ 4169 memcpy(btrc_item_player->features, avrc_item_player->features, 4170 BTRC_FEATURE_BIT_MASK_SIZE); 4171 4172 memset(btrc_item_player->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t)); 4173 memcpy(btrc_item_player->name, avrc_item_player->name.p_str, 4174 avrc_item_player->name.str_len); 4175} 4176 4177/*************************************************************************** 4178 * 4179 * Function handle_change_path_response 4180 * 4181 * Description handles the the change path response, calls 4182 * HAL callback to send the updated folder 4183 * Returns None 4184 * 4185 **************************************************************************/ 4186static void handle_change_path_response(tBTA_AV_META_MSG* pmeta_msg, 4187 tAVRC_CHG_PATH_RSP* p_rsp) { 4188 btif_rc_device_cb_t* p_dev = 4189 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 4190 bt_bdaddr_t rc_addr; 4191 bdcpy(rc_addr.address, p_dev->rc_addr); 4192 4193 if (p_rsp->status == AVRC_STS_NO_ERROR) { 4194 HAL_CBACK(bt_rc_ctrl_callbacks, change_folder_path_cb, &rc_addr, 4195 p_rsp->num_items); 4196 } else { 4197 BTIF_TRACE_ERROR("%s error in handle_change_path_response %d", __func__, 4198 p_rsp->status); 4199 } 4200} 4201 4202/*************************************************************************** 4203 * 4204 * Function handle_set_browsed_player_response 4205 * 4206 * Description handles the the change path response, calls 4207 * HAL callback to send the updated folder 4208 * Returns None 4209 * 4210 **************************************************************************/ 4211static void handle_set_browsed_player_response(tBTA_AV_META_MSG* pmeta_msg, 4212 tAVRC_SET_BR_PLAYER_RSP* p_rsp) { 4213 btif_rc_device_cb_t* p_dev = 4214 btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 4215 bt_bdaddr_t rc_addr; 4216 bdcpy(rc_addr.address, p_dev->rc_addr); 4217 4218 if (p_rsp->status == AVRC_STS_NO_ERROR) { 4219 HAL_CBACK(bt_rc_ctrl_callbacks, set_browsed_player_cb, &rc_addr, 4220 p_rsp->num_items, p_rsp->folder_depth); 4221 } else { 4222 BTIF_TRACE_ERROR("%s error %d", __func__, p_rsp->status); 4223 } 4224} 4225 4226/*************************************************************************** 4227 * 4228 * Function clear_cmd_timeout 4229 * 4230 * Description helper function to stop the command timeout timer 4231 * Returns None 4232 * 4233 **************************************************************************/ 4234static void clear_cmd_timeout(uint8_t label) { 4235 rc_transaction_t* p_txn; 4236 4237 p_txn = get_transaction_by_lbl(label); 4238 if (p_txn == NULL) { 4239 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __func__); 4240 return; 4241 } 4242 4243 if (p_txn->txn_timer != NULL) alarm_cancel(p_txn->txn_timer); 4244} 4245 4246/*************************************************************************** 4247 * 4248 * Function handle_avk_rc_metamsg_rsp 4249 * 4250 * Description Handle RC metamessage response 4251 * 4252 * Returns void 4253 * 4254 **************************************************************************/ 4255static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) { 4256 tAVRC_RESPONSE avrc_response = {0}; 4257 uint8_t scratch_buf[512] = {0}; // this variable is unused 4258 uint16_t buf_len; 4259 tAVRC_STS status; 4260 4261 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d ", __func__, 4262 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code); 4263 4264 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, 4265 &buf_len); 4266 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) && 4267 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) && 4268 (pmeta_msg->code <= AVRC_RSP_INTERIM)) { 4269 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d", __func__, 4270 status, avrc_response.pdu, 4271 pmeta_msg->p_msg->vendor.hdr.ctype); 4272 4273 switch (avrc_response.pdu) { 4274 case AVRC_PDU_REGISTER_NOTIFICATION: 4275 handle_notification_response(pmeta_msg, &avrc_response.reg_notif); 4276 if (pmeta_msg->code == AVRC_RSP_INTERIM) { 4277 /* Don't free the transaction Id */ 4278 clear_cmd_timeout(pmeta_msg->label); 4279 return; 4280 } 4281 break; 4282 4283 case AVRC_PDU_GET_CAPABILITIES: 4284 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps); 4285 break; 4286 4287 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 4288 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr); 4289 break; 4290 4291 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 4292 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values); 4293 break; 4294 4295 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: 4296 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val); 4297 break; 4298 4299 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: 4300 handle_app_attr_txt_response(pmeta_msg, 4301 &avrc_response.get_app_attr_txt); 4302 break; 4303 4304 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: 4305 handle_app_attr_val_txt_response(pmeta_msg, 4306 &avrc_response.get_app_val_txt); 4307 break; 4308 4309 case AVRC_PDU_SET_PLAYER_APP_VALUE: 4310 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val); 4311 break; 4312 4313 case AVRC_PDU_GET_ELEMENT_ATTR: 4314 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_attrs); 4315 break; 4316 4317 case AVRC_PDU_GET_PLAY_STATUS: 4318 handle_get_playstatus_response(pmeta_msg, 4319 &avrc_response.get_play_status); 4320 break; 4321 4322 case AVRC_PDU_SET_ADDRESSED_PLAYER: 4323 handle_set_addressed_player_response(pmeta_msg, &avrc_response.rsp); 4324 break; 4325 } 4326 } else if (AVRC_OP_BROWSE == pmeta_msg->p_msg->hdr.opcode) { 4327 BTIF_TRACE_DEBUG("%s AVRC_OP_BROWSE pdu %d", __func__, avrc_response.pdu); 4328 /* check what kind of command it is for browsing */ 4329 switch (avrc_response.pdu) { 4330 case AVRC_PDU_GET_FOLDER_ITEMS: 4331 handle_get_folder_items_response(pmeta_msg, &avrc_response.get_items); 4332 break; 4333 case AVRC_PDU_CHANGE_PATH: 4334 handle_change_path_response(pmeta_msg, &avrc_response.chg_path); 4335 break; 4336 case AVRC_PDU_SET_BROWSED_PLAYER: 4337 handle_set_browsed_player_response(pmeta_msg, &avrc_response.br_player); 4338 break; 4339 default: 4340 BTIF_TRACE_ERROR("%s cannot handle browse pdu %d", __func__, 4341 pmeta_msg->p_msg->hdr.opcode); 4342 } 4343 } else { 4344 BTIF_TRACE_DEBUG( 4345 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.", 4346 __func__, pmeta_msg->code, pmeta_msg->len); 4347 return; 4348 } 4349 BTIF_TRACE_DEBUG("XX __func__ release transaction %d", pmeta_msg->label); 4350 release_transaction(pmeta_msg->label); 4351} 4352 4353/*************************************************************************** 4354 * 4355 * Function handle_avk_rc_metamsg_cmd 4356 * 4357 * Description Handle RC metamessage response 4358 * 4359 * Returns void 4360 * 4361 **************************************************************************/ 4362static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) { 4363 tAVRC_COMMAND avrc_cmd = {0}; 4364 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 4365 btif_rc_device_cb_t* p_dev = NULL; 4366 4367 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d", __func__, 4368 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code); 4369 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd); 4370 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) && 4371 (pmeta_msg->code <= AVRC_CMD_GEN_INQ)) { 4372 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d", 4373 __func__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label); 4374 4375 if (status != AVRC_STS_NO_ERROR) { 4376 /* return error */ 4377 BTIF_TRACE_WARNING( 4378 "%s: Error in parsing received metamsg command. status: 0x%02x", 4379 __func__, status); 4380 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, 4381 status, pmeta_msg->p_msg->hdr.opcode); 4382 } else { 4383 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle); 4384 if (p_dev == NULL) { 4385 BTIF_TRACE_ERROR("%s: avk rc meta msg cmd for Invalid rc handle", 4386 __func__); 4387 return; 4388 } 4389 4390 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) { 4391 uint8_t event_id = avrc_cmd.reg_notif.event_id; 4392 BTIF_TRACE_EVENT("%s: Register notification event_id: %s", __func__, 4393 dump_rc_notification_event_id(event_id)); 4394 } else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) { 4395 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __func__); 4396 } 4397 4398 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label, 4399 p_dev); 4400 } 4401 } else { 4402 BTIF_TRACE_DEBUG( 4403 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.", 4404 __func__, pmeta_msg->code, pmeta_msg->len); 4405 return; 4406 } 4407} 4408 4409/*************************************************************************** 4410 * 4411 * Function cleanup 4412 * 4413 * Description Closes the AVRC interface 4414 * 4415 * Returns void 4416 * 4417 **************************************************************************/ 4418static void cleanup() { 4419 BTIF_TRACE_EVENT("%s: ", __func__); 4420 if (bt_rc_callbacks) { 4421 bt_rc_callbacks = NULL; 4422 } 4423 4424 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 4425 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer); 4426 memset(&btif_rc_cb.rc_multi_cb[idx], 0, 4427 sizeof(btif_rc_cb.rc_multi_cb[idx])); 4428 } 4429 4430 BTIF_TRACE_EVENT("%s: completed", __func__); 4431} 4432 4433/*************************************************************************** 4434 * 4435 * Function cleanup_ctrl 4436 * 4437 * Description Closes the AVRC Controller interface 4438 * 4439 * Returns void 4440 * 4441 **************************************************************************/ 4442static void cleanup_ctrl() { 4443 BTIF_TRACE_EVENT("%s: ", __func__); 4444 4445 if (bt_rc_ctrl_callbacks) { 4446 bt_rc_ctrl_callbacks = NULL; 4447 } 4448 4449 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { 4450 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer); 4451 memset(&btif_rc_cb.rc_multi_cb[idx], 0, 4452 sizeof(btif_rc_cb.rc_multi_cb[idx])); 4453 } 4454 4455 memset(&btif_rc_cb.rc_multi_cb, 0, sizeof(btif_rc_cb.rc_multi_cb)); 4456 BTIF_TRACE_EVENT("%s: completed", __func__); 4457} 4458 4459/*************************************************************************** 4460 * 4461 * Function getcapabilities_cmd 4462 * 4463 * Description GetCapabilties from Remote(Company_ID, Events_Supported) 4464 * 4465 * Returns void 4466 * 4467 **************************************************************************/ 4468static bt_status_t getcapabilities_cmd(uint8_t cap_id, 4469 btif_rc_device_cb_t* p_dev) { 4470 BTIF_TRACE_DEBUG("%s: cap_id: %d", __func__, cap_id); 4471 CHECK_RC_CONNECTED(p_dev); 4472 4473 tAVRC_COMMAND avrc_cmd = {0}; 4474 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR; 4475 avrc_cmd.get_caps.capability_id = cap_id; 4476 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES; 4477 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR; 4478 4479 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4480} 4481 4482/*************************************************************************** 4483 * 4484 * Function list_player_app_setting_attrib_cmd 4485 * 4486 * Description Get supported List Player Attributes 4487 * 4488 * Returns void 4489 * 4490 **************************************************************************/ 4491static bt_status_t list_player_app_setting_attrib_cmd( 4492 btif_rc_device_cb_t* p_dev) { 4493 BTIF_TRACE_DEBUG("%s", __func__); 4494 CHECK_RC_CONNECTED(p_dev); 4495 4496 tAVRC_COMMAND avrc_cmd = {0}; 4497 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR; 4498 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR; 4499 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR; 4500 4501 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4502} 4503 4504/*************************************************************************** 4505 * 4506 * Function list_player_app_setting_value_cmd 4507 * 4508 * Description Get values of supported Player Attributes 4509 * 4510 * Returns void 4511 * 4512 **************************************************************************/ 4513static bt_status_t list_player_app_setting_value_cmd( 4514 uint8_t attrib_id, btif_rc_device_cb_t* p_dev) { 4515 BTIF_TRACE_DEBUG("%s: attrib_id: %d", __func__, attrib_id); 4516 CHECK_RC_CONNECTED(p_dev); 4517 4518 tAVRC_COMMAND avrc_cmd = {0}; 4519 avrc_cmd.list_app_values.attr_id = attrib_id; 4520 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR; 4521 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES; 4522 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR; 4523 4524 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4525} 4526 4527/*************************************************************************** 4528 * 4529 * Function get_player_app_setting_cmd 4530 * 4531 * Description Get current values of Player Attributes 4532 * 4533 * Returns void 4534 * 4535 **************************************************************************/ 4536static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, 4537 uint8_t* attrib_ids, 4538 btif_rc_device_cb_t* p_dev) { 4539 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib); 4540 CHECK_RC_CONNECTED(p_dev); 4541 4542 tAVRC_COMMAND avrc_cmd = {0}; 4543 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR; 4544 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR; 4545 avrc_cmd.get_cur_app_val.num_attr = num_attrib; 4546 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE; 4547 4548 for (int count = 0; count < num_attrib; count++) { 4549 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count]; 4550 } 4551 4552 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4553} 4554 4555/*************************************************************************** 4556 * 4557 * Function get_playback_state_cmd 4558 * 4559 * Description Fetch the current playback state for the device 4560 * 4561 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4562 * BT_STATUS_FAIL. 4563 * 4564 **************************************************************************/ 4565static bt_status_t get_playback_state_cmd(bt_bdaddr_t* bd_addr) { 4566 BTIF_TRACE_DEBUG("%s", __func__); 4567 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4568 return get_play_status_cmd(p_dev); 4569} 4570 4571/*************************************************************************** 4572 * 4573 * Function get_now_playing_list_cmd 4574 * 4575 * Description Fetch the now playing list 4576 * 4577 * Paramters start_item: First item to fetch (0 to fetch from beganning) 4578 * end_item: Last item to fetch (0xff to fetch until end) 4579 * 4580 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4581 * BT_STATUS_FAIL. 4582 * 4583 **************************************************************************/ 4584static bt_status_t get_now_playing_list_cmd(bt_bdaddr_t* bd_addr, 4585 uint8_t start_item, 4586 uint8_t num_items) { 4587 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items); 4588 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item, 4589 num_items); 4590} 4591 4592/*************************************************************************** 4593 * 4594 * Function get_folder_list_cmd 4595 * 4596 * Description Fetch the currently selected folder list 4597 * 4598 * Paramters start_item: First item to fetch (0 to fetch from beganning) 4599 * end_item: Last item to fetch (0xff to fetch until end) 4600 * 4601 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4602 * BT_STATUS_FAIL. 4603 * 4604 **************************************************************************/ 4605static bt_status_t get_folder_list_cmd(bt_bdaddr_t* bd_addr, uint8_t start_item, 4606 uint8_t num_items) { 4607 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items); 4608 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item, 4609 num_items); 4610} 4611 4612/*************************************************************************** 4613 * 4614 * Function get_player_list_cmd 4615 * 4616 * Description Fetch the player list 4617 * 4618 * Paramters start_item: First item to fetch (0 to fetch from beganning) 4619 * end_item: Last item to fetch (0xff to fetch until end) 4620 * 4621 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4622 * BT_STATUS_FAIL. 4623 * 4624 **************************************************************************/ 4625static bt_status_t get_player_list_cmd(bt_bdaddr_t* bd_addr, uint8_t start_item, 4626 uint8_t num_items) { 4627 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items); 4628 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item, 4629 num_items); 4630} 4631 4632/*************************************************************************** 4633 * 4634 * Function change_folder_path_cmd 4635 * 4636 * Description Change the folder. 4637 * 4638 * Paramters direction: Direction (Up/Down) to change folder 4639 * uid: The UID of folder to move to 4640 * start_item: First item to fetch (0 to fetch from beganning) 4641 * end_item: Last item to fetch (0xff to fetch until end) 4642 * 4643 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4644 * BT_STATUS_FAIL. 4645 * 4646 **************************************************************************/ 4647static bt_status_t change_folder_path_cmd(bt_bdaddr_t* bd_addr, 4648 uint8_t direction, uint8_t* uid) { 4649 BTIF_TRACE_DEBUG("%s: direction %d", __func__, direction); 4650 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4651 CHECK_RC_CONNECTED(p_dev); 4652 CHECK_BR_CONNECTED(p_dev); 4653 4654 tAVRC_COMMAND avrc_cmd = {0}; 4655 4656 avrc_cmd.chg_path.pdu = AVRC_PDU_CHANGE_PATH; 4657 avrc_cmd.chg_path.status = AVRC_STS_NO_ERROR; 4658 // TODO(sanketa): Improve for database aware clients. 4659 avrc_cmd.chg_path.uid_counter = 0; 4660 avrc_cmd.chg_path.direction = direction; 4661 4662 memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t)); 4663 memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t)); 4664 4665 BT_HDR* p_msg = NULL; 4666 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg); 4667 if (status != AVRC_STS_NO_ERROR) { 4668 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status); 4669 return BT_STATUS_FAIL; 4670 } 4671 4672 rc_transaction_t* p_transaction = NULL; 4673 bt_status_t tran_status = get_transaction(&p_transaction); 4674 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) { 4675 osi_free(p_msg); 4676 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x", 4677 __func__, tran_status); 4678 return BT_STATUS_FAIL; 4679 } 4680 4681 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__, 4682 p_transaction->lbl); 4683 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg); 4684 return BT_STATUS_SUCCESS; 4685} 4686 4687/*************************************************************************** 4688 * 4689 * Function set_browsed_player_cmd 4690 * 4691 * Description Change the browsed player. 4692 * 4693 * Paramters id: The UID of player to move to 4694 * 4695 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4696 * BT_STATUS_FAIL. 4697 * 4698 **************************************************************************/ 4699static bt_status_t set_browsed_player_cmd(bt_bdaddr_t* bd_addr, uint16_t id) { 4700 BTIF_TRACE_DEBUG("%s: id %d", __func__, id); 4701 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4702 CHECK_RC_CONNECTED(p_dev); 4703 CHECK_BR_CONNECTED(p_dev); 4704 4705 rc_transaction_t* p_transaction = NULL; 4706 4707 tAVRC_COMMAND avrc_cmd = {0}; 4708 avrc_cmd.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER; 4709 avrc_cmd.br_player.status = AVRC_STS_NO_ERROR; 4710 // TODO(sanketa): Improve for database aware clients. 4711 avrc_cmd.br_player.player_id = id; 4712 4713 BT_HDR* p_msg = NULL; 4714 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg); 4715 if (status != AVRC_STS_NO_ERROR) { 4716 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status); 4717 return BT_STATUS_FAIL; 4718 } 4719 4720 bt_status_t tran_status = get_transaction(&p_transaction); 4721 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) { 4722 osi_free(p_msg); 4723 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x", 4724 __func__, tran_status); 4725 return BT_STATUS_FAIL; 4726 } 4727 4728 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__, 4729 p_transaction->lbl); 4730 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg); 4731 return BT_STATUS_SUCCESS; 4732} 4733 4734/*************************************************************************** 4735 ** 4736 ** Function set_addressed_player_cmd 4737 ** 4738 ** Description Change the addressed player. 4739 ** 4740 ** Paramters id: The UID of player to move to 4741 ** 4742 ** Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4743 ** BT_STATUS_FAIL. 4744 ** 4745 ***************************************************************************/ 4746static bt_status_t set_addressed_player_cmd(bt_bdaddr_t* bd_addr, uint16_t id) { 4747 BTIF_TRACE_DEBUG("%s: id %d", __func__, id); 4748 4749 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4750 CHECK_RC_CONNECTED(p_dev); 4751 CHECK_BR_CONNECTED(p_dev); 4752 4753 tAVRC_COMMAND avrc_cmd = {0}; 4754 BT_HDR* p_msg = NULL; 4755 4756 avrc_cmd.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER; 4757 avrc_cmd.addr_player.status = AVRC_STS_NO_ERROR; 4758 // TODO(sanketa): Improve for database aware clients. 4759 avrc_cmd.addr_player.player_id = id; 4760 4761 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg); 4762 if (status != AVRC_STS_NO_ERROR) { 4763 BTIF_TRACE_ERROR("%s: failed to build command status %d", __func__, status); 4764 return BT_STATUS_FAIL; 4765 } 4766 4767 rc_transaction_t* p_transaction = NULL; 4768 bt_status_t tran_status = get_transaction(&p_transaction); 4769 4770 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) { 4771 osi_free(p_msg); 4772 BTIF_TRACE_ERROR("%s: failed to obtain txn details. status: 0x%02x", 4773 __func__, tran_status); 4774 return BT_STATUS_FAIL; 4775 } 4776 4777 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__, 4778 p_transaction->lbl); 4779 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg); 4780 return BT_STATUS_SUCCESS; 4781} 4782 4783/*************************************************************************** 4784 * 4785 * Function get_folder_items_cmd 4786 * 4787 * Description Helper function to browse the content hierarchy of the 4788 * TG device. 4789 * 4790 * Paramters scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable 4791 * content 4792 * start_item: First item to fetch (0 to fetch from beganning) 4793 * end_item: Last item to fetch (0xff to fetch until end) 4794 * 4795 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise 4796 * BT_STATUS_FAIL. 4797 * 4798 **************************************************************************/ 4799static bt_status_t get_folder_items_cmd(bt_bdaddr_t* bd_addr, uint8_t scope, 4800 uint8_t start_item, uint8_t end_item) { 4801 /* Check that both avrcp and browse channel are connected. */ 4802 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4803 BTIF_TRACE_DEBUG("%s", __func__); 4804 CHECK_RC_CONNECTED(p_dev); 4805 CHECK_BR_CONNECTED(p_dev); 4806 4807 tAVRC_COMMAND avrc_cmd = {0}; 4808 4809 /* Set the layer specific to point to browse although this should really 4810 * be done by lower layers and looking at the PDU 4811 */ 4812 avrc_cmd.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS; 4813 avrc_cmd.get_items.status = AVRC_STS_NO_ERROR; 4814 avrc_cmd.get_items.scope = scope; 4815 avrc_cmd.get_items.start_item = start_item; 4816 avrc_cmd.get_items.end_item = end_item; 4817 avrc_cmd.get_items.attr_count = 0; /* p_attr_list does not matter hence */ 4818 4819 BT_HDR* p_msg = NULL; 4820 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg); 4821 if (status != AVRC_STS_NO_ERROR) { 4822 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status); 4823 return BT_STATUS_FAIL; 4824 } 4825 4826 rc_transaction_t* p_transaction = NULL; 4827 bt_status_t tran_status = get_transaction(&p_transaction); 4828 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) { 4829 osi_free(p_msg); 4830 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x", 4831 __func__, tran_status); 4832 return BT_STATUS_FAIL; 4833 } 4834 4835 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__, 4836 p_transaction->lbl); 4837 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg); 4838 return BT_STATUS_SUCCESS; 4839} 4840 4841/*************************************************************************** 4842 * 4843 * Function change_player_app_setting 4844 * 4845 * Description Set current values of Player Attributes 4846 * 4847 * Returns void 4848 * 4849 **************************************************************************/ 4850static bt_status_t change_player_app_setting(bt_bdaddr_t* bd_addr, 4851 uint8_t num_attrib, 4852 uint8_t* attrib_ids, 4853 uint8_t* attrib_vals) { 4854 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib); 4855 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4856 CHECK_RC_CONNECTED(p_dev); 4857 4858 tAVRC_COMMAND avrc_cmd = {0}; 4859 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR; 4860 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR; 4861 avrc_cmd.set_app_val.num_val = num_attrib; 4862 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE; 4863 avrc_cmd.set_app_val.p_vals = 4864 (tAVRC_APP_SETTING*)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib); 4865 for (int count = 0; count < num_attrib; count++) { 4866 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count]; 4867 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count]; 4868 } 4869 4870 bt_status_t st = build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev); 4871 osi_free_and_reset((void**)&avrc_cmd.set_app_val.p_vals); 4872 return st; 4873} 4874 4875/*************************************************************************** 4876 * 4877 * Function play_item_cmd 4878 * 4879 * Description Play the item specified by UID & scope 4880 * 4881 * Returns void 4882 * 4883 **************************************************************************/ 4884static bt_status_t play_item_cmd(bt_bdaddr_t* bd_addr, uint8_t scope, 4885 uint8_t* uid, uint16_t uid_counter) { 4886 BTIF_TRACE_DEBUG("%s: scope %d uid_counter %d", __func__, scope, uid_counter); 4887 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 4888 CHECK_RC_CONNECTED(p_dev); 4889 CHECK_BR_CONNECTED(p_dev); 4890 4891 tAVRC_COMMAND avrc_cmd = {0}; 4892 avrc_cmd.pdu = AVRC_PDU_PLAY_ITEM; 4893 avrc_cmd.play_item.opcode = AVRC_OP_VENDOR; 4894 avrc_cmd.play_item.status = AVRC_STS_NO_ERROR; 4895 avrc_cmd.play_item.scope = scope; 4896 memcpy(avrc_cmd.play_item.uid, uid, AVRC_UID_SIZE); 4897 avrc_cmd.play_item.uid_counter = uid_counter; 4898 4899 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev); 4900} 4901 4902/*************************************************************************** 4903 * 4904 * Function get_player_app_setting_attr_text_cmd 4905 * 4906 * Description Get text description for app attribute 4907 * 4908 * Returns void 4909 * 4910 **************************************************************************/ 4911static bt_status_t get_player_app_setting_attr_text_cmd( 4912 uint8_t* attrs, uint8_t num_attrs, btif_rc_device_cb_t* p_dev) { 4913 BTIF_TRACE_DEBUG("%s: num attrs: %d", __func__, num_attrs); 4914 CHECK_RC_CONNECTED(p_dev); 4915 4916 tAVRC_COMMAND avrc_cmd = {0}; 4917 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT; 4918 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR; 4919 avrc_cmd.get_app_attr_txt.num_attr = num_attrs; 4920 4921 for (int count = 0; count < num_attrs; count++) { 4922 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count]; 4923 } 4924 4925 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4926} 4927 4928/*************************************************************************** 4929 * 4930 * Function get_player_app_setting_val_text_cmd 4931 * 4932 * Description Get text description for app attribute values 4933 * 4934 * Returns void 4935 * 4936 **************************************************************************/ 4937static bt_status_t get_player_app_setting_value_text_cmd( 4938 uint8_t* vals, uint8_t num_vals, btif_rc_device_cb_t* p_dev) { 4939 BTIF_TRACE_DEBUG("%s: num_vals: %d", __func__, num_vals); 4940 CHECK_RC_CONNECTED(p_dev); 4941 4942 tAVRC_COMMAND avrc_cmd = {0}; 4943 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT; 4944 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR; 4945 avrc_cmd.get_app_val_txt.num_val = num_vals; 4946 4947 for (int count = 0; count < num_vals; count++) { 4948 avrc_cmd.get_app_val_txt.vals[count] = vals[count]; 4949 } 4950 4951 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 4952} 4953 4954/*************************************************************************** 4955 * 4956 * Function register_notification_cmd 4957 * 4958 * Description Send Command to register for a Notification ID 4959 * 4960 * Returns void 4961 * 4962 **************************************************************************/ 4963static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id, 4964 uint32_t event_value, 4965 btif_rc_device_cb_t* p_dev) { 4966 BTIF_TRACE_DEBUG("%s: event_id: %d event_value %d", __func__, event_id, 4967 event_value); 4968 CHECK_RC_CONNECTED(p_dev); 4969 4970 tAVRC_COMMAND avrc_cmd = {0}; 4971 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR; 4972 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR; 4973 avrc_cmd.reg_notif.event_id = event_id; 4974 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION; 4975 avrc_cmd.reg_notif.param = event_value; 4976 4977 BT_HDR* p_msg = NULL; 4978 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg); 4979 if (status == AVRC_STS_NO_ERROR) { 4980 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset; 4981 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__, 4982 label); 4983 if (p_msg != NULL) { 4984 BTA_AvVendorCmd(p_dev->rc_handle, label, AVRC_CMD_NOTIF, data_start, 4985 p_msg->len); 4986 status = BT_STATUS_SUCCESS; 4987 } 4988 } else { 4989 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__, 4990 status); 4991 } 4992 osi_free(p_msg); 4993 return (bt_status_t)status; 4994} 4995 4996/*************************************************************************** 4997 * 4998 * Function get_element_attribute_cmd 4999 * 5000 * Description Get Element Attribute for attributeIds 5001 * 5002 * Returns void 5003 * 5004 **************************************************************************/ 5005static bt_status_t get_element_attribute_cmd(uint8_t num_attribute, 5006 uint32_t* p_attr_ids, 5007 btif_rc_device_cb_t* p_dev) { 5008 BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__, 5009 num_attribute, p_attr_ids[0]); 5010 CHECK_RC_CONNECTED(p_dev); 5011 5012 tAVRC_COMMAND avrc_cmd = {0}; 5013 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR; 5014 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR; 5015 avrc_cmd.get_elem_attrs.num_attr = num_attribute; 5016 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR; 5017 for (int count = 0; count < num_attribute; count++) { 5018 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count]; 5019 } 5020 5021 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 5022} 5023 5024/*************************************************************************** 5025 * 5026 * Function get_play_status_cmd 5027 * 5028 * Description Get Playing Status of a Device 5029 * 5030 * Returns bt_status_t 5031 * 5032 **************************************************************************/ 5033static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev) { 5034 BTIF_TRACE_DEBUG("%s", __func__); 5035 CHECK_RC_CONNECTED(p_dev); 5036 5037 tAVRC_COMMAND avrc_cmd = {0}; 5038 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR; 5039 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS; 5040 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR; 5041 5042 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev); 5043} 5044 5045/*************************************************************************** 5046 * 5047 * Function set_volume_rsp 5048 * 5049 * Description Rsp for SetAbsoluteVolume Command 5050 * 5051 * Returns void 5052 * 5053 **************************************************************************/ 5054static bt_status_t set_volume_rsp(bt_bdaddr_t* bd_addr, uint8_t abs_vol, 5055 uint8_t label) { 5056 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 5057 tAVRC_RESPONSE avrc_rsp; 5058 BT_HDR* p_msg = NULL; 5059 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 5060 5061 CHECK_RC_CONNECTED(p_dev); 5062 5063 BTIF_TRACE_DEBUG("%s: abs_vol: %d", __func__, abs_vol); 5064 5065 avrc_rsp.volume.opcode = AVRC_OP_VENDOR; 5066 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME; 5067 avrc_rsp.volume.status = AVRC_STS_NO_ERROR; 5068 avrc_rsp.volume.volume = abs_vol; 5069 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); 5070 if (status == AVRC_STS_NO_ERROR) { 5071 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset; 5072 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__, 5073 p_dev->rc_vol_label); 5074 if (p_msg != NULL) { 5075 BTA_AvVendorRsp(p_dev->rc_handle, label, BTA_AV_RSP_ACCEPT, data_start, 5076 p_msg->len, 0); 5077 status = BT_STATUS_SUCCESS; 5078 } 5079 } else { 5080 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__, 5081 status); 5082 } 5083 osi_free(p_msg); 5084 return (bt_status_t)status; 5085} 5086 5087/*************************************************************************** 5088 * 5089 * Function send_register_abs_vol_rsp 5090 * 5091 * Description Rsp for Notification of Absolute Volume 5092 * 5093 * Returns void 5094 * 5095 **************************************************************************/ 5096static bt_status_t volume_change_notification_rsp( 5097 bt_bdaddr_t* bd_addr, btrc_notification_type_t rsp_type, uint8_t abs_vol, 5098 uint8_t label) { 5099 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 5100 tAVRC_RESPONSE avrc_rsp; 5101 BT_HDR* p_msg = NULL; 5102 BTIF_TRACE_DEBUG("%s: rsp_type: %d abs_vol: %d", __func__, rsp_type, abs_vol); 5103 5104 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 5105 5106 CHECK_RC_CONNECTED(p_dev); 5107 5108 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR; 5109 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION; 5110 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR; 5111 avrc_rsp.reg_notif.param.volume = abs_vol; 5112 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE; 5113 5114 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); 5115 if (status == AVRC_STS_NO_ERROR) { 5116 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__, 5117 label); 5118 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset; 5119 BTA_AvVendorRsp(p_dev->rc_handle, label, 5120 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) 5121 ? AVRC_RSP_INTERIM 5122 : AVRC_RSP_CHANGED, 5123 data_start, p_msg->len, 0); 5124 status = BT_STATUS_SUCCESS; 5125 } else { 5126 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__, 5127 status); 5128 } 5129 osi_free(p_msg); 5130 5131 return (bt_status_t)status; 5132} 5133 5134/*************************************************************************** 5135 * 5136 * Function send_groupnavigation_cmd 5137 * 5138 * Description Send Pass-Through command 5139 * 5140 * Returns void 5141 * 5142 **************************************************************************/ 5143static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t* bd_addr, 5144 uint8_t key_code, 5145 uint8_t key_state) { 5146 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 5147 rc_transaction_t* p_transaction = NULL; 5148 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code, 5149 key_state); 5150 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr); 5151 5152 CHECK_RC_CONNECTED(p_dev); 5153 5154 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) { 5155 bt_status_t tran_status = get_transaction(&p_transaction); 5156 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) { 5157 uint8_t buffer[AVRC_PASS_THRU_GROUP_LEN] = {0}; 5158 uint8_t* start = buffer; 5159 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA); 5160 *(start)++ = 0; 5161 UINT8_TO_BE_STREAM(start, key_code); 5162 BTA_AvRemoteVendorUniqueCmd(p_dev->rc_handle, p_transaction->lbl, 5163 (tBTA_AV_STATE)key_state, buffer, 5164 AVRC_PASS_THRU_GROUP_LEN); 5165 status = BT_STATUS_SUCCESS; 5166 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA", 5167 __func__); 5168 } else { 5169 status = BT_STATUS_FAIL; 5170 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__); 5171 } 5172 } else { 5173 status = BT_STATUS_FAIL; 5174 BTIF_TRACE_DEBUG("%s: feature not supported", __func__); 5175 } 5176 return (bt_status_t)status; 5177} 5178 5179/*************************************************************************** 5180 * 5181 * Function send_passthrough_cmd 5182 * 5183 * Description Send Pass-Through command 5184 * 5185 * Returns void 5186 * 5187 **************************************************************************/ 5188static bt_status_t send_passthrough_cmd(bt_bdaddr_t* bd_addr, uint8_t key_code, 5189 uint8_t key_state) { 5190 tAVRC_STS status = BT_STATUS_UNSUPPORTED; 5191 btif_rc_device_cb_t* p_dev = NULL; 5192 BTIF_TRACE_ERROR("%s: calling btif_rc_get_device_by_bda", __func__); 5193 p_dev = btif_rc_get_device_by_bda(bd_addr); 5194 5195 CHECK_RC_CONNECTED(p_dev); 5196 5197 rc_transaction_t* p_transaction = NULL; 5198 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code, 5199 key_state); 5200 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) { 5201 bt_status_t tran_status = get_transaction(&p_transaction); 5202 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) { 5203 BTA_AvRemoteCmd(p_dev->rc_handle, p_transaction->lbl, 5204 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state); 5205 status = BT_STATUS_SUCCESS; 5206 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", 5207 __func__); 5208 } else { 5209 status = BT_STATUS_FAIL; 5210 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__); 5211 } 5212 } else { 5213 status = BT_STATUS_FAIL; 5214 BTIF_TRACE_DEBUG("%s: feature not supported", __func__); 5215 } 5216 return (bt_status_t)status; 5217} 5218 5219static const btrc_interface_t bt_rc_interface = { 5220 sizeof(bt_rc_interface), 5221 init, 5222 get_play_status_rsp, 5223 NULL, /* list_player_app_attr_rsp */ 5224 NULL, /* list_player_app_value_rsp */ 5225 NULL, /* get_player_app_value_rsp */ 5226 NULL, /* get_player_app_attr_text_rsp */ 5227 NULL, /* get_player_app_value_text_rsp */ 5228 get_element_attr_rsp, 5229 NULL, /* set_player_app_value_rsp */ 5230 register_notification_rsp, 5231 set_volume, 5232 set_addressed_player_rsp, 5233 set_browsed_player_rsp, 5234 get_folder_items_list_rsp, 5235 change_path_rsp, 5236 get_item_attr_rsp, 5237 play_item_rsp, 5238 get_total_num_of_items_rsp, 5239 search_rsp, 5240 add_to_now_playing_rsp, 5241 cleanup, 5242}; 5243 5244static const btrc_ctrl_interface_t bt_rc_ctrl_interface = { 5245 sizeof(bt_rc_ctrl_interface), 5246 init_ctrl, 5247 send_passthrough_cmd, 5248 send_groupnavigation_cmd, 5249 change_player_app_setting, 5250 play_item_cmd, 5251 get_playback_state_cmd, 5252 get_now_playing_list_cmd, 5253 get_folder_list_cmd, 5254 get_player_list_cmd, 5255 change_folder_path_cmd, 5256 set_browsed_player_cmd, 5257 set_addressed_player_cmd, 5258 set_volume_rsp, 5259 volume_change_notification_rsp, 5260 cleanup_ctrl, 5261}; 5262 5263/******************************************************************************* 5264 * 5265 * Function btif_rc_get_interface 5266 * 5267 * Description Get the AVRCP Target callback interface 5268 * 5269 * Returns btrc_interface_t 5270 * 5271 ******************************************************************************/ 5272const btrc_interface_t* btif_rc_get_interface(void) { 5273 BTIF_TRACE_EVENT("%s: ", __func__); 5274 return &bt_rc_interface; 5275} 5276 5277/******************************************************************************* 5278 * 5279 * Function btif_rc_ctrl_get_interface 5280 * 5281 * Description Get the AVRCP Controller callback interface 5282 * 5283 * Returns btrc_ctrl_interface_t 5284 * 5285 ******************************************************************************/ 5286const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) { 5287 BTIF_TRACE_EVENT("%s: ", __func__); 5288 return &bt_rc_ctrl_interface; 5289} 5290 5291/******************************************************************************* 5292 * Function initialize_transaction 5293 * 5294 * Description Initializes fields of the transaction structure 5295 * 5296 * Returns void 5297 ******************************************************************************/ 5298static void initialize_transaction(int lbl) { 5299 std::unique_lock<std::recursive_mutex>(device.lbllock); 5300 if (lbl < MAX_TRANSACTIONS_PER_SESSION) { 5301 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) { 5302 clear_cmd_timeout(lbl); 5303 } 5304 device.transaction[lbl].lbl = lbl; 5305 device.transaction[lbl].in_use = false; 5306 device.transaction[lbl].handle = 0; 5307 } 5308} 5309 5310/******************************************************************************* 5311 * Function lbl_init 5312 * 5313 * Description Initializes label structures and mutexes. 5314 * 5315 * Returns void 5316 ******************************************************************************/ 5317void lbl_init() { 5318 memset(&device.transaction, 0, sizeof(device.transaction)); 5319 init_all_transactions(); 5320} 5321 5322/******************************************************************************* 5323 * 5324 * Function init_all_transactions 5325 * 5326 * Description Initializes all transactions 5327 * 5328 * Returns void 5329 ******************************************************************************/ 5330void init_all_transactions() { 5331 uint8_t txn_indx = 0; 5332 for (txn_indx = 0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++) { 5333 initialize_transaction(txn_indx); 5334 } 5335} 5336 5337/******************************************************************************* 5338 * 5339 * Function get_transaction_by_lbl 5340 * 5341 * Description Will return a transaction based on the label. If not inuse 5342 * will return an error. 5343 * 5344 * Returns bt_status_t 5345 ******************************************************************************/ 5346rc_transaction_t* get_transaction_by_lbl(uint8_t lbl) { 5347 rc_transaction_t* transaction = NULL; 5348 std::unique_lock<std::recursive_mutex> lock(device.lbllock); 5349 5350 /* Determine if this is a valid label */ 5351 if (lbl < MAX_TRANSACTIONS_PER_SESSION) { 5352 if (false == device.transaction[lbl].in_use) { 5353 transaction = NULL; 5354 } else { 5355 transaction = &(device.transaction[lbl]); 5356 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__, lbl); 5357 } 5358 } 5359 5360 return transaction; 5361} 5362 5363/******************************************************************************* 5364 * 5365 * Function get_transaction 5366 * 5367 * Description Obtains the transaction details. 5368 * 5369 * Returns bt_status_t 5370 ******************************************************************************/ 5371 5372static bt_status_t get_transaction(rc_transaction_t** ptransaction) { 5373 std::unique_lock<std::recursive_mutex> lock(device.lbllock); 5374 5375 // Check for unused transactions 5376 for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; i++) { 5377 if (false == device.transaction[i].in_use) { 5378 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__, 5379 device.transaction[i].lbl); 5380 device.transaction[i].in_use = true; 5381 *ptransaction = &(device.transaction[i]); 5382 return BT_STATUS_SUCCESS; 5383 } 5384 } 5385 return BT_STATUS_NOMEM; 5386} 5387 5388/******************************************************************************* 5389 * 5390 * Function release_transaction 5391 * 5392 * Description Will release a transaction for reuse 5393 * 5394 * Returns bt_status_t 5395 ******************************************************************************/ 5396void release_transaction(uint8_t lbl) { 5397 BTIF_TRACE_DEBUG("%s %d", __func__, lbl); 5398 rc_transaction_t* transaction = get_transaction_by_lbl(lbl); 5399 5400 /* If the transaction is in use... */ 5401 if (transaction != NULL) { 5402 BTIF_TRACE_DEBUG("%s: lbl: %d", __func__, lbl); 5403 initialize_transaction(lbl); 5404 } 5405} 5406 5407/******************************************************************************* 5408 * Function sleep_ms 5409 * 5410 * Description Sleep the calling thread unconditionally for 5411 * |timeout_ms| milliseconds. 5412 * 5413 * Returns void 5414 ******************************************************************************/ 5415static void sleep_ms(period_ms_t timeout_ms) { 5416 struct timespec delay; 5417 delay.tv_sec = timeout_ms / 1000; 5418 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000); 5419 5420 OSI_NO_INTR(nanosleep(&delay, &delay)); 5421} 5422 5423static bool absolute_volume_disabled() { 5424 char volume_disabled[PROPERTY_VALUE_MAX] = {0}; 5425 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false"); 5426 if (strncmp(volume_disabled, "true", 4) == 0) { 5427 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__); 5428 return true; 5429 } 5430 return false; 5431} 5432