2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /*****************************************************************************
21 * Description: Bluetooth AVRC implementation
23 *****************************************************************************/
25 #define LOG_TAG "bt_btif_avrc"
34 #include <hardware/bluetooth.h>
35 #include <hardware/bt_rc.h>
37 #include "avrc_defs.h"
39 #include "bta_av_api.h"
41 #include "btif_common.h"
42 #include "btif_util.h"
43 #include "bt_common.h"
44 #include "device/include/interop.h"
47 #include "osi/include/list.h"
48 #include "osi/include/properties.h"
50 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
52 /*****************************************************************************
54 ******************************************************************************/
56 /* cod value for Headsets */
57 #define COD_AV_HEADSETS 0x0404
58 /* for AVRC 1.4 need to change this */
59 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
61 #define IDX_GET_PLAY_STATUS_RSP 0
62 #define IDX_LIST_APP_ATTR_RSP 1
63 #define IDX_LIST_APP_VALUE_RSP 2
64 #define IDX_GET_CURR_APP_VAL_RSP 3
65 #define IDX_SET_APP_VAL_RSP 4
66 #define IDX_GET_APP_ATTR_TXT_RSP 5
67 #define IDX_GET_APP_VAL_TXT_RSP 6
68 #define IDX_GET_ELEMENT_ATTR_RSP 7
69 #define MAX_VOLUME 128
71 #define MAX_TRANSACTIONS_PER_SESSION 16
72 #define MAX_CMD_QUEUE_LEN 8
73 #define PLAY_STATUS_PLAYING 1
75 #define CHECK_RC_CONNECTED \
76 BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
77 if (btif_rc_cb.rc_connected == FALSE) \
79 BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
80 return BT_STATUS_NOT_READY; \
83 #define FILL_PDU_QUEUE(index, ctype, label, pending) \
85 btif_rc_cb.rc_pdu_info[index].ctype = ctype; \
86 btif_rc_cb.rc_pdu_info[index].label = label; \
87 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
90 #define SEND_METAMSG_RSP(index, avrc_rsp) \
92 if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE) \
94 BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
95 return BT_STATUS_UNHANDLED; \
97 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label, \
98 btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp); \
99 btif_rc_cb.rc_pdu_info[index].ctype = 0; \
100 btif_rc_cb.rc_pdu_info[index].label = 0; \
101 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE; \
104 /*****************************************************************************
105 ** Local type definitions
106 ******************************************************************************/
110 } btif_rc_reg_notifications_t;
116 BOOLEAN is_rsp_pending;
117 } btif_rc_cmd_ctxt_t;
119 /* 2 second timeout to get interim response */
120 #define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000)
121 #define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000)
122 #define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000)
130 } btif_rc_nfn_reg_status_t;
135 btif_rc_nfn_reg_status_t status;
136 } btif_rc_supported_event_t;
138 #define BTIF_RC_STS_TIMEOUT 0xFE
142 } btif_rc_status_cmd_timer_t;
147 } btif_rc_control_cmd_timer_t;
151 btif_rc_status_cmd_timer_t rc_status_cmd;
152 btif_rc_control_cmd_timer_t rc_control_cmd;
154 } btif_rc_timer_context_t;
157 BOOLEAN query_started;
162 UINT8 ext_attr_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;
168 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single struct */
170 BOOLEAN rc_connected;
172 tBTA_AV_FEAT rc_features;
174 UINT16 rc_pending_play;
175 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
176 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
177 unsigned int rc_volume;
178 uint8_t rc_vol_label;
179 list_t *rc_supported_event_list;
180 btif_rc_player_app_settings_t rc_app_settings;
181 alarm_t *rc_play_status_timer;
182 BOOLEAN rc_features_processed;
183 UINT64 rc_playing_uid;
184 BOOLEAN rc_procedure_complete;
191 btif_rc_timer_context_t txn_timer_context;
197 pthread_mutex_t lbllock;
198 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
203 #define MAX_UINPUT_PATHS 3
204 static const char* uinput_dev_path[] =
205 {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
206 static int uinput_fd = -1;
208 static int send_event (int fd, uint16_t type, uint16_t code, int32_t value);
209 static void send_key (int fd, uint16_t key, int pressed);
210 static int uinput_driver_check();
211 static int uinput_create(char *name);
212 static int init_uinput (void);
213 static void close_uinput (void);
214 static void sleep_ms(period_ms_t timeout_ms);
216 static const struct {
220 uint8_t release_quirk;
222 { "PLAY", AVRC_ID_PLAY, KEY_PLAYCD, 1 },
223 { "STOP", AVRC_ID_STOP, KEY_STOPCD, 0 },
224 { "PAUSE", AVRC_ID_PAUSE, KEY_PAUSECD, 1 },
225 { "FORWARD", AVRC_ID_FORWARD, KEY_NEXTSONG, 0 },
226 { "BACKWARD", AVRC_ID_BACKWARD, KEY_PREVIOUSSONG, 0 },
227 { "REWIND", AVRC_ID_REWIND, KEY_REWIND, 0 },
228 { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FAST_FORWARD, 0 },
232 static void send_reject_response (UINT8 rc_handle, UINT8 label,
233 UINT8 pdu, UINT8 status);
234 static UINT8 opcode_from_pdu(UINT8 pdu);
235 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
236 tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
237 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
238 static void register_volumechange(UINT8 label);
240 static void lbl_init();
241 static void lbl_destroy();
242 static void init_all_transactions();
243 static bt_status_t get_transaction(rc_transaction_t **ptransaction);
244 static void release_transaction(UINT8 label);
245 static rc_transaction_t* get_transaction_by_lbl(UINT8 label);
246 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
247 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
249 #if (AVRC_CTLR_INCLUDED == TRUE)
250 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg);
251 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
252 static void btif_rc_ctrl_upstreams_rsp_cmd(
253 UINT8 event, tAVRC_COMMAND *pavrc_cmd, UINT8 label);
254 static void rc_ctrl_procedure_complete();
255 static void rc_stop_play_status_timer();
256 static void register_for_event_notification (btif_rc_supported_event_t *p_event);
257 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp);
258 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp);
259 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp);
260 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp);
261 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
262 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
263 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp);
264 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
265 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
266 static bt_status_t get_play_status_cmd(void);
267 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
268 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
269 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
270 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
271 static bt_status_t getcapabilities_cmd (uint8_t cap_id);
272 static bt_status_t list_player_app_setting_attrib_cmd(void);
273 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
274 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
276 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
277 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
278 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
280 static void rc_start_play_status_timer(void);
281 static bool absolute_volume_disabled(void);
283 /*****************************************************************************
285 ******************************************************************************/
286 static btif_rc_cb_t btif_rc_cb;
287 static btrc_callbacks_t *bt_rc_callbacks = NULL;
288 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
290 /*****************************************************************************
292 ******************************************************************************/
294 /*****************************************************************************
296 ******************************************************************************/
297 extern BOOLEAN btif_hf_call_terminated_recently();
298 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
300 extern fixed_queue_t *btu_general_alarm_queue;
302 /*****************************************************************************
304 ******************************************************************************/
306 /*****************************************************************************
307 ** Local uinput helper functions
308 ******************************************************************************/
309 int send_event (int fd, uint16_t type, uint16_t code, int32_t value)
311 struct uinput_event event;
312 BTIF_TRACE_DEBUG("%s type:%u code:%u value:%d", __FUNCTION__,
314 memset(&event, 0, sizeof(event));
320 OSI_NO_INTR(ret = write(fd, &event, sizeof(event)));
324 void send_key (int fd, uint16_t key, int pressed)
326 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
334 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
335 send_event(fd, EV_KEY, key, pressed);
336 send_event(fd, EV_SYN, SYN_REPORT, 0);
339 /************** uinput related functions **************/
340 int uinput_driver_check()
343 for (i=0; i < MAX_UINPUT_PATHS; i++)
345 if (access(uinput_dev_path[i], O_RDWR) == 0) {
349 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
353 int uinput_create(char *name)
355 struct uinput_dev dev;
358 for(x=0; x < MAX_UINPUT_PATHS; x++)
360 fd = open(uinput_dev_path[x], O_RDWR);
365 if (x == MAX_UINPUT_PATHS) {
366 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
369 memset(&dev, 0, sizeof(dev));
371 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
373 dev.id.bustype = BUS_BLUETOOTH;
374 dev.id.vendor = 0x0000;
375 dev.id.product = 0x0000;
376 dev.id.version = 0x0000;
379 OSI_NO_INTR(ret = write(fd, &dev, sizeof(dev)));
381 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
386 ioctl(fd, UI_SET_EVBIT, EV_KEY);
387 ioctl(fd, UI_SET_EVBIT, EV_REL);
388 ioctl(fd, UI_SET_EVBIT, EV_SYN);
390 for (x = 0; key_map[x].name != NULL; x++)
391 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
393 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
394 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
401 int init_uinput (void)
403 char *name = "AVRCP";
405 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
406 uinput_fd = uinput_create(name);
408 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
409 __FUNCTION__, name, uinput_fd);
411 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
412 __FUNCTION__, name, uinput_fd);
417 void close_uinput (void)
419 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
421 ioctl(uinput_fd, UI_DEV_DESTROY);
428 #if (AVRC_CTLR_INCLUDED == TRUE)
429 void rc_cleanup_sent_cmd (void *p_data)
431 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
435 void handle_rc_ctrl_features(BD_ADDR bd_addr)
437 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
438 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
439 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
443 bdcpy(rc_addr.address,bd_addr);
445 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
446 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
448 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
450 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
451 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
452 (btif_rc_cb.rc_features_processed != TRUE))
454 rc_features |= BTRC_FEAT_METADATA;
455 /* Mark rc features processed to avoid repeating
456 * the AVRCP procedure every time on receiving this
459 btif_rc_cb.rc_features_processed = TRUE;
460 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
462 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
463 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
468 void handle_rc_features(BD_ADDR bd_addr)
470 if (bt_rc_callbacks != NULL)
472 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
475 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
476 bt_bdaddr_t avdtp_addr = btif_av_get_addr();
478 bdstr_t addr1, addr2;
479 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
480 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
481 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
483 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
484 || absolute_volume_disabled()
485 || bdcmp(avdtp_addr.address, rc_addr.address))
486 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
488 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
490 rc_features |= BTRC_FEAT_BROWSE;
493 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
494 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
495 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
497 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
501 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
503 rc_features |= BTRC_FEAT_METADATA;
506 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
507 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
509 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
510 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
511 __FUNCTION__, btif_rc_cb.rc_vol_label);
512 // Register for volume change on connect
513 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
514 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
516 rc_transaction_t *p_transaction=NULL;
517 bt_status_t status = BT_STATUS_NOT_READY;
518 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
520 status=get_transaction(&p_transaction);
524 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
525 if (NULL!=p_transaction)
527 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
528 __FUNCTION__, btif_rc_cb.rc_vol_label);
532 status=get_transaction(&p_transaction);
535 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
537 btif_rc_cb.rc_vol_label=p_transaction->lbl;
538 register_volumechange(btif_rc_cb.rc_vol_label);
545 /***************************************************************************
546 * Function handle_rc_connect
548 * - Argument: tBTA_AV_RC_OPEN RC open data structure
550 * - Description: RC connection event handler
552 ***************************************************************************/
553 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
555 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
556 bt_status_t result = BT_STATUS_SUCCESS;
557 #if (AVRC_CTLR_INCLUDED == TRUE)
561 if (p_rc_open->status == BTA_AV_SUCCESS)
563 //check if already some RC is connected
564 if (btif_rc_cb.rc_connected)
566 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
567 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
568 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
569 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
571 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
572 BTA_AvCloseRc(p_rc_open->rc_handle);
576 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
577 btif_rc_cb.rc_features = p_rc_open->peer_features;
578 btif_rc_cb.rc_vol_label=MAX_LABEL;
579 btif_rc_cb.rc_volume=MAX_VOLUME;
581 btif_rc_cb.rc_connected = TRUE;
582 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
584 /* on locally initiated connection we will get remote features as part of connect */
585 if (btif_rc_cb.rc_features != 0)
586 handle_rc_features(btif_rc_cb.rc_addr);
589 result = uinput_driver_check();
590 if (result == BT_STATUS_SUCCESS)
597 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
600 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
601 #if (AVRC_CTLR_INCLUDED == TRUE)
602 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
603 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
604 if (bt_rc_ctrl_callbacks != NULL)
606 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
608 /* report connection state if remote device is AVRCP target */
609 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
610 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
611 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
613 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
619 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
620 __FUNCTION__, p_rc_open->status);
621 btif_rc_cb.rc_connected = FALSE;
625 /***************************************************************************
626 * Function handle_rc_disconnect
628 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
630 * - Description: RC disconnection event handler
632 ***************************************************************************/
633 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
635 #if (AVRC_CTLR_INCLUDED == TRUE)
637 tBTA_AV_FEAT features;
639 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
640 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
641 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
643 BTIF_TRACE_ERROR("Got disconnect of unknown device");
646 #if (AVRC_CTLR_INCLUDED == TRUE)
647 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
648 features = btif_rc_cb.rc_features;
649 /* Clean up AVRCP procedure flags */
650 memset(&btif_rc_cb.rc_app_settings, 0,
651 sizeof(btif_rc_player_app_settings_t));
652 btif_rc_cb.rc_features_processed = FALSE;
653 btif_rc_cb.rc_procedure_complete = FALSE;
654 rc_stop_play_status_timer();
655 /* Check and clear the notification event list */
656 if (btif_rc_cb.rc_supported_event_list != NULL)
658 list_clear(btif_rc_cb.rc_supported_event_list);
659 btif_rc_cb.rc_supported_event_list = NULL;
662 btif_rc_cb.rc_handle = 0;
663 btif_rc_cb.rc_connected = FALSE;
664 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
665 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
667 btif_rc_cb.rc_features = 0;
668 btif_rc_cb.rc_vol_label=MAX_LABEL;
669 btif_rc_cb.rc_volume=MAX_VOLUME;
670 init_all_transactions();
671 if (bt_rc_callbacks != NULL)
677 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
680 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
681 #if (AVRC_CTLR_INCLUDED == TRUE)
682 /* report connection state if device is AVRCP target */
683 if (bt_rc_ctrl_callbacks != NULL)
685 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
690 /***************************************************************************
691 * Function handle_rc_passthrough_cmd
693 * - Argument: tBTA_AV_RC rc_id remote control command ID
694 * tBTA_AV_STATE key_state status of key press
696 * - Description: Remote control command handler
698 ***************************************************************************/
699 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
704 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
706 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
709 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
710 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
712 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
714 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
715 btif_rc_cb.rc_pending_play = TRUE;
720 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
722 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
723 btif_rc_cb.rc_pending_play = FALSE;
726 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
727 return; // this command is not to be sent to UINPUT, only needed for PTS
730 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
732 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
736 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
744 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
745 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
749 for (i = 0; key_map[i].name != NULL; i++) {
750 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
751 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
753 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
754 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
755 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
756 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
757 * The fix is to generate a release right after the press and drown the 'actual'
760 if ((key_map[i].release_quirk == 1) && (pressed == 0))
762 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
763 __FUNCTION__, key_map[i].name);
766 send_key(uinput_fd, key_map[i].mapped_id, pressed);
767 if ((key_map[i].release_quirk == 1) && (pressed == 1))
770 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
771 __FUNCTION__, key_map[i].name);
772 send_key(uinput_fd, key_map[i].mapped_id, 0);
778 if (key_map[i].name == NULL)
779 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
780 p_remote_cmd->rc_id, status);
783 /***************************************************************************
784 * Function handle_rc_passthrough_rsp
786 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
788 * - Description: Remote control passthrough response handler
790 ***************************************************************************/
791 void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
793 #if (AVRC_CTLR_INCLUDED == TRUE)
795 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
798 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
809 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
811 release_transaction(p_remote_rsp->label);
812 if (bt_rc_ctrl_callbacks != NULL) {
813 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
818 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
821 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
825 /***************************************************************************
826 * Function handle_rc_vendorunique_rsp
828 * - Argument: tBTA_AV_REMOTE_RSP command response
830 * - Description: Remote control vendor unique response handler
832 ***************************************************************************/
833 void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
835 #if (AVRC_CTLR_INCLUDED == TRUE)
838 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
841 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
852 if (p_remote_rsp->len > 0)
854 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
855 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
856 osi_free_and_reset((void **)&p_remote_rsp->p_data);
858 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
860 release_transaction(p_remote_rsp->label);
861 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
865 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
868 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
872 void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
874 tAVRC_RESPONSE avrc_rsp = {0};
875 avrc_rsp.rsp.pdu = pavrc_command->pdu;
876 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
877 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
879 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
880 avrc_rsp.reg_notif.param.uid_counter = 0;
882 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
883 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
887 /***************************************************************************
888 * Function handle_rc_metamsg_cmd
890 * - Argument: tBTA_AV_VENDOR Structure containing the received
893 * - Description: Remote control metamsg command handler (AVRCP 1.3)
895 ***************************************************************************/
896 void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
898 /* Parse the metamsg command and pass it on to BTL-IFS */
899 UINT8 scratch_buf[512] = {0};
900 tAVRC_COMMAND avrc_command = {0};
903 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
905 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
907 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
910 if (pmeta_msg->len < 3)
912 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
917 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
919 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
921 rc_transaction_t *transaction=NULL;
922 transaction=get_transaction_by_lbl(pmeta_msg->label);
923 if (NULL!=transaction)
925 handle_rc_metamsg_rsp(pmeta_msg);
929 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
930 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
936 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
937 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
943 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
944 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
945 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
947 if (status != AVRC_STS_NO_ERROR)
950 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
951 __FUNCTION__, status);
952 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
956 /* if RegisterNotification, add it to our registered queue */
958 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
960 UINT8 event_id = avrc_command.reg_notif.event_id;
961 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
962 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
963 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
964 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
966 if (event_id == AVRC_EVT_UIDS_CHANGE)
968 handle_uid_changed_notification(pmeta_msg, &avrc_command);
974 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
975 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
977 /* Since handle_rc_metamsg_cmd() itself is called from
978 *btif context, no context switching is required. Invoke
979 * btif_rc_upstreams_evt directly from here. */
980 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
985 /***************************************************************************
987 ** Function btif_rc_handler
989 ** Description RC event handler
991 ***************************************************************************/
992 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
994 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
997 case BTA_AV_RC_OPEN_EVT:
999 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
1000 handle_rc_connect( &(p_data->rc_open) );
1003 case BTA_AV_RC_CLOSE_EVT:
1005 handle_rc_disconnect( &(p_data->rc_close) );
1008 case BTA_AV_REMOTE_CMD_EVT:
1010 if (bt_rc_callbacks != NULL)
1012 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1013 __FUNCTION__, p_data->remote_cmd.rc_id,
1014 p_data->remote_cmd.key_state);
1015 /** In race conditions just after 2nd AVRCP is connected
1016 * remote might send pass through commands, so check for
1017 * Rc handle before processing pass through commands
1019 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1021 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1025 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1030 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1035 #if (AVRC_CTLR_INCLUDED == TRUE)
1036 case BTA_AV_REMOTE_RSP_EVT:
1038 BTIF_TRACE_DEBUG("%s RSP: rc_id:0x%x key_state:%d",
1039 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1040 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1042 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1046 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1052 case BTA_AV_RC_FEAT_EVT:
1054 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
1055 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
1056 handle_rc_features(p_data->rc_feat.peer_addr);
1057 #if (AVRC_CTLR_INCLUDED == TRUE)
1058 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1060 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1066 case BTA_AV_META_MSG_EVT:
1068 if (bt_rc_callbacks != NULL)
1070 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1072 p_data->meta_msg.code,
1073 p_data->meta_msg.label);
1074 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1076 p_data->meta_msg.company_id,
1077 p_data->meta_msg.len,
1078 p_data->meta_msg.rc_handle);
1079 /* handle the metamsg command */
1080 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1081 /* Free the Memory allocated for tAVRC_MSG */
1083 #if (AVRC_CTLR_INCLUDED == TRUE)
1084 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1086 /* This is case of Sink + CT + TG(for abs vol)) */
1087 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1089 p_data->meta_msg.code,
1090 p_data->meta_msg.label);
1091 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1093 p_data->meta_msg.company_id,
1094 p_data->meta_msg.len,
1095 p_data->meta_msg.rc_handle);
1096 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1097 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1099 /* Its a response */
1100 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1102 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1105 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1112 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1118 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
1122 /***************************************************************************
1124 ** Function btif_rc_get_connected_peer
1126 ** Description Fetches the connected headset's BD_ADDR if any
1128 ***************************************************************************/
1129 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1131 if (btif_rc_cb.rc_connected == TRUE) {
1132 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1138 /***************************************************************************
1140 ** Function btif_rc_get_connected_peer_handle
1142 ** Description Fetches the connected headset's handle if any
1144 ***************************************************************************/
1145 UINT8 btif_rc_get_connected_peer_handle(void)
1147 return btif_rc_cb.rc_handle;
1150 /***************************************************************************
1152 ** Function btif_rc_check_handle_pending_play
1154 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1156 ***************************************************************************/
1158 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
1159 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1163 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
1164 if (btif_rc_cb.rc_pending_play)
1168 tBTA_AV_REMOTE_CMD remote_cmd;
1169 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
1171 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1172 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1173 remote_cmd.rc_id = AVRC_ID_PLAY;
1174 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1175 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1177 /* delay sending to app, else there is a timing issue in the framework,
1178 ** which causes the audio to be on th device's speaker. Delay between
1182 /* send to app - both PRESSED & RELEASED */
1183 remote_cmd.key_state = AVRC_STATE_PRESS;
1184 handle_rc_passthrough_cmd( &remote_cmd );
1188 remote_cmd.key_state = AVRC_STATE_RELEASE;
1189 handle_rc_passthrough_cmd( &remote_cmd );
1191 btif_rc_cb.rc_pending_play = FALSE;
1195 /* Generic reject response */
1196 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1198 UINT8 ctype = AVRC_RSP_REJ;
1199 tAVRC_RESPONSE avrc_rsp;
1200 BT_HDR *p_msg = NULL;
1201 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1203 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1204 avrc_rsp.rsp.pdu = pdu;
1205 avrc_rsp.rsp.status = status;
1207 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1209 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
1210 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1211 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1215 /***************************************************************************
1216 * Function send_metamsg_rsp
1219 * rc_handle RC handle corresponding to the connected RC
1220 * label Label of the RC response
1221 * code Response type
1222 * pmetamsg_resp Vendor response
1224 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1226 ***************************************************************************/
1227 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1228 tAVRC_RESPONSE *pmetamsg_resp)
1234 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
1238 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
1239 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1241 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1243 ctype = AVRC_RSP_REJ;
1247 if ( code < AVRC_RSP_NOT_IMPL)
1249 if (code == AVRC_CMD_NOTIF)
1251 ctype = AVRC_RSP_INTERIM;
1253 else if (code == AVRC_CMD_STATUS)
1255 ctype = AVRC_RSP_IMPL_STBL;
1259 ctype = AVRC_RSP_ACCEPT;
1267 /* if response is for register_notification, make sure the rc has
1268 actually registered for this */
1269 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
1271 BOOLEAN bSent = FALSE;
1272 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1273 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1275 /* de-register this notification for a CHANGED response */
1276 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
1277 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
1278 btif_rc_cb.rc_handle, event_id, bNotify);
1281 BT_HDR *p_msg = NULL;
1284 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1285 pmetamsg_resp, &p_msg)) )
1287 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
1288 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1290 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1295 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
1296 __FUNCTION__, status);
1303 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
1304 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1309 /* All other commands go here */
1311 BT_HDR *p_msg = NULL;
1314 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1316 if (status == AVRC_STS_NO_ERROR)
1318 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1322 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1323 __FUNCTION__, status);
1328 static UINT8 opcode_from_pdu(UINT8 pdu)
1334 case AVRC_PDU_NEXT_GROUP:
1335 case AVRC_PDU_PREV_GROUP: /* pass thru */
1336 opcode = AVRC_OP_PASS_THRU;
1339 default: /* vendor */
1340 opcode = AVRC_OP_VENDOR;
1347 /*******************************************************************************
1349 ** Function btif_rc_upstreams_evt
1351 ** Description Executes AVRC UPSTREAMS events in btif context.
1355 *******************************************************************************/
1356 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1358 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1359 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1363 case AVRC_PDU_GET_PLAY_STATUS:
1365 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1366 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1369 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1370 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1371 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1372 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1373 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1374 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1376 /* TODO: Add support for Application Settings */
1377 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
1380 case AVRC_PDU_GET_ELEMENT_ATTR:
1382 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1384 memset(&element_attrs, 0, sizeof(element_attrs));
1385 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1387 /* CT requests for all attributes */
1389 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1390 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
1392 element_attrs[attr_cnt] = attr_cnt + 1;
1395 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1397 /* 0xff indicates, no attributes requested - reject */
1398 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1399 AVRC_STS_BAD_PARAM);
1404 int attr_cnt, filled_attr_count;
1407 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1408 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1409 * Fill only valid entries.
1411 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1412 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1414 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1415 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1417 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1419 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1421 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1424 if (filled_attr_count == num_attr)
1426 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1432 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1433 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1436 case AVRC_PDU_REGISTER_NOTIFICATION:
1438 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1439 pavrc_cmd->reg_notif.param == 0)
1441 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
1443 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1444 /* de-register this notification for a rejected response */
1445 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1448 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1449 pavrc_cmd->reg_notif.param);
1452 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1454 tAVRC_RESPONSE avrc_rsp;
1455 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
1456 if (btif_rc_cb.rc_connected == TRUE)
1458 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1459 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1460 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1461 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1462 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1468 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1469 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1476 #if (AVRC_CTLR_INCLUDED == TRUE)
1477 /*******************************************************************************
1479 ** Function btif_rc_ctrl_upstreams_rsp_cmd
1481 ** Description Executes AVRC UPSTREAMS response events in btif context.
1485 *******************************************************************************/
1486 static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1489 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1490 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1491 bt_bdaddr_t rc_addr;
1492 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1493 #if (AVRC_CTLR_INCLUDED == TRUE)
1496 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1497 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1498 pavrc_cmd->volume.volume, label);
1500 case AVRC_PDU_REGISTER_NOTIFICATION:
1501 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1503 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1512 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1513 /*******************************************************************************
1515 ** Function btif_rc_upstreams_rsp_evt
1517 ** Description Executes AVRC UPSTREAMS response events in btif context.
1521 *******************************************************************************/
1522 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1524 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1525 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1529 case AVRC_PDU_REGISTER_NOTIFICATION:
1531 if (AVRC_RSP_CHANGED==ctype)
1532 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1533 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1537 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1539 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1540 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1541 if (AVRC_RSP_ACCEPT==ctype)
1542 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1543 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1553 /************************************************************************************
1554 ** AVRCP API Functions
1555 ************************************************************************************/
1557 /*******************************************************************************
1561 ** Description Initializes the AVRC interface
1563 ** Returns bt_status_t
1565 *******************************************************************************/
1566 static bt_status_t init(btrc_callbacks_t* callbacks )
1568 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1569 bt_status_t result = BT_STATUS_SUCCESS;
1571 if (bt_rc_callbacks)
1572 return BT_STATUS_DONE;
1574 bt_rc_callbacks = callbacks;
1575 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1576 btif_rc_cb.rc_vol_label=MAX_LABEL;
1577 btif_rc_cb.rc_volume=MAX_VOLUME;
1583 /*******************************************************************************
1585 ** Function init_ctrl
1587 ** Description Initializes the AVRC interface
1589 ** Returns bt_status_t
1591 *******************************************************************************/
1592 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1594 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1595 bt_status_t result = BT_STATUS_SUCCESS;
1597 if (bt_rc_ctrl_callbacks)
1598 return BT_STATUS_DONE;
1600 bt_rc_ctrl_callbacks = callbacks;
1601 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1602 btif_rc_cb.rc_vol_label=MAX_LABEL;
1603 btif_rc_cb.rc_volume=MAX_VOLUME;
1609 static void rc_ctrl_procedure_complete ()
1611 if (btif_rc_cb.rc_procedure_complete == TRUE)
1615 btif_rc_cb.rc_procedure_complete = TRUE;
1616 UINT32 attr_list[] = {
1617 AVRC_MEDIA_ATTR_ID_TITLE,
1618 AVRC_MEDIA_ATTR_ID_ARTIST,
1619 AVRC_MEDIA_ATTR_ID_ALBUM,
1620 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1621 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1622 AVRC_MEDIA_ATTR_ID_GENRE,
1623 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1625 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1628 /***************************************************************************
1630 ** Function get_play_status_rsp
1632 ** Description Returns the current play status.
1633 ** This method is called in response to
1634 ** GetPlayStatus request.
1636 ** Returns bt_status_t
1638 ***************************************************************************/
1639 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1642 tAVRC_RESPONSE avrc_rsp;
1644 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1645 avrc_rsp.get_play_status.song_len = song_len;
1646 avrc_rsp.get_play_status.song_pos = song_pos;
1647 avrc_rsp.get_play_status.play_status = play_status;
1649 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1650 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1651 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1652 /* Send the response */
1653 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1654 return BT_STATUS_SUCCESS;
1657 /***************************************************************************
1659 ** Function get_element_attr_rsp
1661 ** Description Returns the current songs' element attributes
1664 ** Returns bt_status_t
1666 ***************************************************************************/
1667 static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1669 tAVRC_RESPONSE avrc_rsp;
1671 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1673 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1677 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1681 for (i=0; i<num_attr; i++) {
1682 element_attrs[i].attr_id = p_attrs[i].attr_id;
1683 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1684 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1685 element_attrs[i].name.p_str = p_attrs[i].text;
1686 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
1687 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1688 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1689 element_attrs[i].name.p_str);
1691 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1693 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1694 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1695 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1696 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1697 /* Send the response */
1698 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1699 return BT_STATUS_SUCCESS;
1702 /***************************************************************************
1704 ** Function register_notification_rsp
1706 ** Description Response to the register notification request.
1709 ** Returns bt_status_t
1711 ***************************************************************************/
1712 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1713 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1715 tAVRC_RESPONSE avrc_rsp;
1717 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1718 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1720 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
1721 return BT_STATUS_NOT_READY;
1723 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1724 avrc_rsp.reg_notif.event_id = event_id;
1728 case BTRC_EVT_PLAY_STATUS_CHANGED:
1729 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1730 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1731 btif_av_clear_remote_suspend_flag();
1733 case BTRC_EVT_TRACK_CHANGE:
1734 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1736 case BTRC_EVT_PLAY_POS_CHANGED:
1737 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1740 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1741 return BT_STATUS_UNHANDLED;
1744 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1745 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1746 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1748 /* Send the response. */
1749 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1750 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1751 return BT_STATUS_SUCCESS;
1754 /***************************************************************************
1756 ** Function set_volume
1758 ** Description Send current volume setting to remote side.
1759 ** Support limited to SetAbsoluteVolume
1760 ** This can be enhanced to support Relative Volume (AVRCP 1.0).
1761 ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1762 ** as opposed to absolute volume level
1763 ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1765 ** Returns bt_status_t
1767 ***************************************************************************/
1768 static bt_status_t set_volume(uint8_t volume)
1770 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1772 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1773 rc_transaction_t *p_transaction=NULL;
1775 if (btif_rc_cb.rc_volume==volume)
1777 status=BT_STATUS_DONE;
1778 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
1782 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1783 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1785 tAVRC_COMMAND avrc_cmd = {0};
1786 BT_HDR *p_msg = NULL;
1788 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
1789 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1790 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1791 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1792 avrc_cmd.volume.volume = volume;
1794 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1796 bt_status_t tran_status=get_transaction(&p_transaction);
1797 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
1799 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
1800 __FUNCTION__,p_transaction->lbl);
1801 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1802 status = BT_STATUS_SUCCESS;
1807 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
1808 __FUNCTION__, tran_status);
1809 status = BT_STATUS_FAIL;
1814 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
1815 __FUNCTION__, status);
1816 status = BT_STATUS_FAIL;
1820 status=BT_STATUS_NOT_READY;
1824 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1825 /***************************************************************************
1827 ** Function register_volumechange
1829 ** Description Register for volume change notification from remote side.
1833 ***************************************************************************/
1835 static void register_volumechange (UINT8 lbl)
1837 tAVRC_COMMAND avrc_cmd = {0};
1838 BT_HDR *p_msg = NULL;
1839 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
1840 rc_transaction_t *p_transaction=NULL;
1842 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
1844 avrc_cmd.cmd.opcode=0x00;
1845 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1846 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1847 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1848 avrc_cmd.reg_notif.param = 0;
1850 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
1851 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1852 p_transaction = get_transaction_by_lbl(lbl);
1853 if (p_transaction != NULL) {
1854 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1855 AVRC_CMD_NOTIF, p_msg);
1856 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1859 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1863 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
1867 /***************************************************************************
1869 ** Function handle_rc_metamsg_rsp
1871 ** Description Handle RC metamessage response
1875 ***************************************************************************/
1876 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1878 tAVRC_RESPONSE avrc_response = {0};
1879 UINT8 scratch_buf[512] = {0};
1880 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1882 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
1883 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1884 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1886 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
1887 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
1888 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1889 status, pmeta_msg->label);
1891 if (status != AVRC_STS_NO_ERROR)
1893 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1894 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1895 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1897 btif_rc_cb.rc_vol_label=MAX_LABEL;
1898 release_transaction(btif_rc_cb.rc_vol_label);
1900 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1902 release_transaction(pmeta_msg->label);
1906 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1907 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1908 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1910 // Just discard the message, if the device sends back with an incorrect label
1911 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
1912 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1918 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
1919 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1923 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1924 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1925 && AVRC_RSP_CHANGED==pmeta_msg->code)
1927 /* re-register for volume change notification */
1928 // Do not re-register for rejected case, as it might get into endless loop
1929 register_volumechange(btif_rc_cb.rc_vol_label);
1931 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1933 /* free up the label here */
1934 release_transaction(pmeta_msg->label);
1937 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
1938 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1939 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1944 #if (AVRC_CTLR_INCLUDED == TRUE)
1945 /***************************************************************************
1947 ** Function iterate_supported_event_list_for_interim_rsp
1949 ** Description iterator callback function to match the event and handle
1951 ** Returns true to continue iterating, false to stop
1953 ***************************************************************************/
1954 bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1957 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1959 p_event_id = (UINT8*)cb_data;
1961 if (p_event->event_id == *p_event_id)
1963 p_event->status = eINTERIM;
1969 /***************************************************************************
1971 ** Function iterate_supported_event_list_for_timeout
1973 ** Description Iterator callback function for timeout handling.
1974 ** As part of the failure handling, it releases the
1975 ** transaction label and removes the event from list,
1976 ** this event will not be requested again during
1977 ** the lifetime of the connection.
1978 ** Returns false to stop iterating, true to continue
1980 ***************************************************************************/
1981 bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1984 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1986 label = (*(UINT8*)cb_data) & 0xFF;
1988 if (p_event->label == label)
1990 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
1996 /***************************************************************************
1998 ** Function rc_notification_interim_timout
2000 ** Description Interim response timeout handler.
2001 ** Runs the iterator to check and clear the timed out event.
2002 ** Proceeds to register for the unregistered events.
2005 ***************************************************************************/
2006 static void rc_notification_interim_timout (UINT8 label)
2010 list_foreach(btif_rc_cb.rc_supported_event_list,
2011 iterate_supported_event_list_for_timeout, &label);
2012 /* Timeout happened for interim response for the registered event,
2013 * check if there are any pending for registration
2015 node = list_begin(btif_rc_cb.rc_supported_event_list);
2016 while (node != NULL)
2018 btif_rc_supported_event_t *p_event;
2020 p_event = (btif_rc_supported_event_t *)list_node(node);
2021 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2023 register_for_event_notification(p_event);
2026 node = list_next (node);
2028 /* Todo. Need to initiate application settings query if this
2029 * is the last event registration.
2033 /***************************************************************************
2035 ** Function btif_rc_status_cmd_timeout_handler
2037 ** Description RC status command timeout handler (Runs in BTIF context).
2040 ***************************************************************************/
2041 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2044 btif_rc_timer_context_t *p_context;
2045 tAVRC_RESPONSE avrc_response = {0};
2046 tBTA_AV_META_MSG meta_msg;
2048 p_context = (btif_rc_timer_context_t *)data;
2049 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2050 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2052 switch (p_context->rc_status_cmd.pdu_id) {
2053 case AVRC_PDU_REGISTER_NOTIFICATION:
2054 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2057 case AVRC_PDU_GET_CAPABILITIES:
2058 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2059 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2062 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2063 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2064 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2067 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2068 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2069 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2072 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2073 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2074 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2077 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2078 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2079 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2082 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2083 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2084 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2087 case AVRC_PDU_GET_ELEMENT_ATTR:
2088 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2089 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2092 case AVRC_PDU_GET_PLAY_STATUS:
2093 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2094 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2097 release_transaction(p_context->rc_status_cmd.label);
2100 /***************************************************************************
2102 ** Function btif_rc_status_cmd_timer_timeout
2104 ** Description RC status command timeout callback.
2105 ** This is called from BTU context and switches to BTIF
2106 ** context to handle the timeout events
2109 ***************************************************************************/
2110 static void btif_rc_status_cmd_timer_timeout(void *data)
2112 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2114 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2115 (char *)p_data, sizeof(btif_rc_timer_context_t),
2119 /***************************************************************************
2121 ** Function btif_rc_control_cmd_timeout_handler
2123 ** Description RC control command timeout handler (Runs in BTIF context).
2126 ***************************************************************************/
2127 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2130 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2131 tAVRC_RESPONSE avrc_response = {0};
2132 tBTA_AV_META_MSG meta_msg;
2134 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2135 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2137 switch (p_context->rc_control_cmd.pdu_id) {
2138 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2139 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2140 handle_set_app_attr_val_response(&meta_msg,
2141 &avrc_response.set_app_val);
2144 release_transaction(p_context->rc_control_cmd.label);
2147 /***************************************************************************
2149 ** Function btif_rc_control_cmd_timer_timeout
2151 ** Description RC control command timeout callback.
2152 ** This is called from BTU context and switches to BTIF
2153 ** context to handle the timeout events
2156 ***************************************************************************/
2157 static void btif_rc_control_cmd_timer_timeout(void *data)
2159 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2161 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2162 (char *)p_data, sizeof(btif_rc_timer_context_t),
2166 /***************************************************************************
2168 ** Function btif_rc_play_status_timeout_handler
2170 ** Description RC play status timeout handler (Runs in BTIF context).
2173 ***************************************************************************/
2174 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2175 UNUSED_ATTR char *p_data)
2177 get_play_status_cmd();
2178 rc_start_play_status_timer();
2181 /***************************************************************************
2183 ** Function btif_rc_play_status_timer_timeout
2185 ** Description RC play status timeout callback.
2186 ** This is called from BTU context and switches to BTIF
2187 ** context to handle the timeout events
2190 ***************************************************************************/
2191 static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2193 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
2196 /***************************************************************************
2198 ** Function rc_start_play_status_timer
2200 ** Description Helper function to start the timer to fetch play status.
2203 ***************************************************************************/
2204 static void rc_start_play_status_timer(void)
2206 /* Start the Play status timer only if it is not started */
2207 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2208 if (btif_rc_cb.rc_play_status_timer == NULL) {
2209 btif_rc_cb.rc_play_status_timer =
2210 alarm_new("btif_rc.rc_play_status_timer");
2212 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2213 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2214 btif_rc_play_status_timer_timeout, NULL,
2215 btu_general_alarm_queue);
2219 /***************************************************************************
2221 ** Function rc_stop_play_status_timer
2223 ** Description Helper function to stop the play status timer.
2226 ***************************************************************************/
2227 void rc_stop_play_status_timer()
2229 if (btif_rc_cb.rc_play_status_timer != NULL)
2230 alarm_cancel(btif_rc_cb.rc_play_status_timer);
2233 /***************************************************************************
2235 ** Function register_for_event_notification
2237 ** Description Helper function registering notification events
2238 ** sets an interim response timeout to handle if the remote
2239 ** does not respond.
2242 ***************************************************************************/
2243 static void register_for_event_notification(btif_rc_supported_event_t *p_event)
2246 rc_transaction_t *p_transaction;
2248 status = get_transaction(&p_transaction);
2249 if (status == BT_STATUS_SUCCESS)
2251 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
2253 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2254 if (status != BT_STATUS_SUCCESS)
2256 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2257 __FUNCTION__, status);
2258 release_transaction (p_transaction->lbl);
2261 p_event->label = p_transaction->lbl;
2262 p_event->status = eREGISTERED;
2263 p_context->rc_status_cmd.label = p_transaction->lbl;
2264 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2266 alarm_free(p_transaction->txn_timer);
2267 p_transaction->txn_timer =
2268 alarm_new("btif_rc.status_command_txn_timer");
2269 alarm_set_on_queue(p_transaction->txn_timer,
2270 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2271 btif_rc_status_cmd_timer_timeout, p_context,
2272 btu_general_alarm_queue);
2276 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2277 __FUNCTION__, status);
2281 static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2283 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2284 p_context->rc_status_cmd.label = p_txn->lbl;
2285 p_context->rc_status_cmd.pdu_id = pdu_id;
2287 alarm_free(p_txn->txn_timer);
2288 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2289 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2290 btif_rc_status_cmd_timer_timeout, p_context,
2291 btu_general_alarm_queue);
2294 static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2296 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2297 p_context->rc_control_cmd.label = p_txn->lbl;
2298 p_context->rc_control_cmd.pdu_id = pdu_id;
2300 alarm_free(p_txn->txn_timer);
2301 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2302 alarm_set_on_queue(p_txn->txn_timer,
2303 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2304 btif_rc_control_cmd_timer_timeout, p_context,
2305 btu_general_alarm_queue);
2308 /***************************************************************************
2310 ** Function handle_get_capability_response
2312 ** Description Handles the get_cap_response to populate company id info
2313 ** and query the supported events.
2314 ** Initiates Notification registration for events supported
2317 ***************************************************************************/
2318 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2322 /* Todo: Do we need to retry on command timeout */
2323 if (p_rsp->status != AVRC_STS_NO_ERROR)
2325 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2326 __FUNCTION__, p_rsp->status);
2330 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2332 btif_rc_supported_event_t *p_event;
2334 /* Todo: Check if list can be active when we hit here */
2335 btif_rc_cb.rc_supported_event_list = list_new(osi_free);
2336 for (xx = 0; xx < p_rsp->count; xx++)
2338 /* Skip registering for Play position change notification */
2339 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2340 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2341 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2343 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
2344 p_event->event_id = p_rsp->param.event_id[xx];
2345 p_event->status = eNOT_REGISTERED;
2346 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2349 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2350 if (p_event != NULL)
2352 register_for_event_notification(p_event);
2355 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2357 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2358 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2359 for (xx = 0; xx < p_rsp->count; xx++)
2361 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2366 bool rc_is_track_id_valid (tAVRC_UID uid)
2368 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2370 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2380 /***************************************************************************
2382 ** Function handle_notification_response
2384 ** Description Main handler for notification responses to registered events
2385 ** 1. Register for unregistered event(in interim response path)
2386 ** 2. After registering for all supported events, start
2387 ** retrieving application settings and values
2388 ** 3. Reregister for events on getting changed response
2389 ** 4. Run play status timer for getting position when the
2390 ** status changes to playing
2391 ** 5. Get the Media details when the track change happens
2392 ** or track change interim response is received with
2394 ** 6. HAL callback for play status change and application
2398 ***************************************************************************/
2399 static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2401 bt_bdaddr_t rc_addr;
2402 UINT32 attr_list[] = {
2403 AVRC_MEDIA_ATTR_ID_TITLE,
2404 AVRC_MEDIA_ATTR_ID_ARTIST,
2405 AVRC_MEDIA_ATTR_ID_ALBUM,
2406 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2407 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2408 AVRC_MEDIA_ATTR_ID_GENRE,
2409 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2413 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2415 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2417 btif_rc_supported_event_t *p_event;
2420 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2421 switch (p_rsp->event_id)
2423 case AVRC_EVT_PLAY_STATUS_CHANGE:
2424 /* Start timer to get play status periodically
2425 * if the play state is playing.
2427 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2429 rc_start_play_status_timer();
2431 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2432 &rc_addr, p_rsp->param.play_status);
2435 case AVRC_EVT_TRACK_CHANGE:
2436 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2442 UINT8 *p_data = p_rsp->param.track;
2443 /* Update the UID for current track
2444 * Attributes will be fetched after the AVRCP procedure
2446 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2450 case AVRC_EVT_APP_SETTING_CHANGE:
2453 case AVRC_EVT_NOW_PLAYING_CHANGE:
2456 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2459 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2462 case AVRC_EVT_UIDS_CHANGE:
2465 case AVRC_EVT_TRACK_REACHED_END:
2466 case AVRC_EVT_TRACK_REACHED_START:
2467 case AVRC_EVT_PLAY_POS_CHANGED:
2468 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2469 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2471 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2475 list_foreach(btif_rc_cb.rc_supported_event_list,
2476 iterate_supported_event_list_for_interim_rsp,
2479 node = list_begin(btif_rc_cb.rc_supported_event_list);
2480 while (node != NULL)
2482 p_event = (btif_rc_supported_event_t *)list_node(node);
2483 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2485 register_for_event_notification(p_event);
2488 node = list_next (node);
2491 /* Registered for all events, we can request application settings */
2492 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2494 /* we need to do this only if remote TG supports
2495 * player application settings
2497 btif_rc_cb.rc_app_settings.query_started = TRUE;
2498 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2500 list_player_app_setting_attrib_cmd();
2504 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2505 rc_ctrl_procedure_complete();
2509 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2511 btif_rc_supported_event_t *p_event;
2514 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2517 node = list_begin(btif_rc_cb.rc_supported_event_list);
2518 while (node != NULL)
2520 p_event = (btif_rc_supported_event_t *)list_node(node);
2521 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2523 p_event->status = eNOT_REGISTERED;
2524 register_for_event_notification(p_event);
2527 node = list_next (node);
2530 switch (p_rsp->event_id)
2532 case AVRC_EVT_PLAY_STATUS_CHANGE:
2533 /* Start timer to get play status periodically
2534 * if the play state is playing.
2536 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2538 rc_start_play_status_timer();
2542 rc_stop_play_status_timer();
2544 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2545 &rc_addr, p_rsp->param.play_status);
2548 case AVRC_EVT_TRACK_CHANGE:
2549 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2553 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2556 case AVRC_EVT_APP_SETTING_CHANGE:
2558 btrc_player_settings_t app_settings;
2561 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2562 for (xx = 0; xx < app_settings.num_attr; xx++)
2564 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2565 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2567 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2568 &rc_addr, &app_settings);
2572 case AVRC_EVT_NOW_PLAYING_CHANGE:
2575 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2578 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2581 case AVRC_EVT_UIDS_CHANGE:
2584 case AVRC_EVT_TRACK_REACHED_END:
2585 case AVRC_EVT_TRACK_REACHED_START:
2586 case AVRC_EVT_PLAY_POS_CHANGED:
2587 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2588 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2590 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2591 __FUNCTION__, p_rsp->event_id);
2597 /***************************************************************************
2599 ** Function handle_app_attr_response
2601 ** Description handles the the application attributes response and
2602 ** initiates procedure to fetch the attribute values
2605 ***************************************************************************/
2606 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2610 if (p_rsp->status != AVRC_STS_NO_ERROR)
2612 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2613 __FUNCTION__, p_rsp->status);
2614 rc_ctrl_procedure_complete();
2618 for (xx = 0; xx < p_rsp->num_attr; xx++)
2622 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2624 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2625 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2626 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2630 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2631 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2632 btif_rc_cb.rc_app_settings.num_attrs++;
2635 btif_rc_cb.rc_app_settings.attr_index = 0;
2636 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2637 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2638 if (p_rsp->num_attr)
2640 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2644 BTIF_TRACE_ERROR("%s No Player application settings found",
2649 /***************************************************************************
2651 ** Function handle_app_val_response
2653 ** Description handles the the attributes value response and if extended
2654 ** menu is available, it initiates query for the attribute
2655 ** text. If not, it initiates procedure to get the current
2656 ** attribute values and calls the HAL callback for provding
2657 ** application settings information.
2660 ***************************************************************************/
2661 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2663 UINT8 xx, attr_index;
2664 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2665 btif_rc_player_app_settings_t *p_app_settings;
2666 bt_bdaddr_t rc_addr;
2668 /* Todo: Do we need to retry on command timeout */
2669 if (p_rsp->status != AVRC_STS_NO_ERROR)
2671 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2672 __FUNCTION__, p_rsp->status);
2676 p_app_settings = &btif_rc_cb.rc_app_settings;
2677 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2679 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2681 attr_index = p_app_settings->attr_index;
2682 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2683 for (xx = 0; xx < p_rsp->num_val; xx++)
2685 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2688 p_app_settings->attr_index++;
2689 if (attr_index < p_app_settings->num_attrs)
2691 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2693 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2696 p_app_settings->ext_attr_index = 0;
2697 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2701 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2703 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2705 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2706 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2707 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2710 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2712 attr_index = p_app_settings->ext_attr_index;
2713 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2714 for (xx = 0; xx < p_rsp->num_val; xx++)
2716 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2719 p_app_settings->ext_attr_index++;
2720 if (attr_index < p_app_settings->num_ext_attrs)
2722 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2726 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2729 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2731 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2733 get_player_app_setting_attr_text_cmd(attr, xx);
2738 /***************************************************************************
2740 ** Function handle_app_cur_val_response
2742 ** Description handles the the get attributes value response.
2746 ***************************************************************************/
2747 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2749 btrc_player_settings_t app_settings;
2750 bt_bdaddr_t rc_addr;
2753 /* Todo: Do we need to retry on command timeout */
2754 if (p_rsp->status != AVRC_STS_NO_ERROR)
2756 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2757 __FUNCTION__, p_rsp->status);
2761 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2763 app_settings.num_attr = p_rsp->num_val;
2764 for (xx = 0; xx < app_settings.num_attr; xx++)
2766 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2767 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2769 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2770 &rc_addr, &app_settings);
2771 /* Application settings are fetched only once for initial values
2772 * initiate anything that follows after RC procedure.
2773 * Defer it if browsing is supported till players query
2775 rc_ctrl_procedure_complete ();
2776 osi_free_and_reset((void **)&p_rsp->p_vals);
2779 /***************************************************************************
2781 ** Function handle_app_attr_txt_response
2783 ** Description handles the the get attributes text response, if fails
2784 ** calls HAL callback with just normal settings and initiates
2785 ** query for current settings else initiates query for value text
2788 ***************************************************************************/
2789 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2792 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2793 btif_rc_player_app_settings_t *p_app_settings;
2794 bt_bdaddr_t rc_addr;
2796 p_app_settings = &btif_rc_cb.rc_app_settings;
2797 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2799 /* Todo: Do we need to retry on command timeout */
2800 if (p_rsp->status != AVRC_STS_NO_ERROR)
2802 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2804 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2805 __FUNCTION__, p_rsp->status);
2806 /* Not able to fetch Text for extended Menu, skip the process
2807 * and cleanup used memory. Proceed to get the current settings
2808 * for standard attributes.
2810 p_app_settings->num_ext_attrs = 0;
2811 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2812 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2813 p_app_settings->ext_attr_index = 0;
2815 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2817 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2819 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2820 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2822 get_player_app_setting_cmd (xx, attrs);
2826 for (xx = 0; xx < p_rsp->num_attr; xx++)
2829 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2831 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2833 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2834 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2835 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2841 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2843 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2845 get_player_app_setting_value_text_cmd(vals, xx);
2849 /***************************************************************************
2851 ** Function handle_app_attr_val_txt_response
2853 ** Description handles the the get attributes value text response, if fails
2854 ** calls HAL callback with just normal settings and initiates
2855 ** query for current settings
2858 ***************************************************************************/
2859 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2861 UINT8 xx, attr_index;
2862 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2863 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2864 btif_rc_player_app_settings_t *p_app_settings;
2865 bt_bdaddr_t rc_addr;
2867 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2868 p_app_settings = &btif_rc_cb.rc_app_settings;
2870 /* Todo: Do we need to retry on command timeout */
2871 if (p_rsp->status != AVRC_STS_NO_ERROR)
2873 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2875 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2876 __FUNCTION__, p_rsp->status);
2878 /* Not able to fetch Text for extended Menu, skip the process
2879 * and cleanup used memory. Proceed to get the current settings
2880 * for standard attributes.
2882 p_app_settings->num_ext_attrs = 0;
2883 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2886 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2888 for (x = 0; x < p_ext_attr->num_val; x++)
2889 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2890 p_ext_attr->num_val = 0;
2891 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2893 p_app_settings->ext_attr_index = 0;
2895 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2897 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2899 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2900 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2902 get_player_app_setting_cmd (xx, attrs);
2906 for (xx = 0; xx < p_rsp->num_attr; xx++)
2909 btrc_player_app_ext_attr_t *p_ext_attr;
2910 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2911 for (x = 0; x < p_rsp->num_attr; x++)
2913 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2915 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2916 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2917 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2922 p_app_settings->ext_val_index++;
2924 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2926 attr_index = p_app_settings->ext_val_index;
2927 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2929 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2931 get_player_app_setting_value_text_cmd(vals, xx);
2937 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2939 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2941 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2943 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2945 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2946 p_app_settings->num_attrs, p_app_settings->attrs,
2947 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
2948 get_player_app_setting_cmd (xx + x, attrs);
2950 /* Free the application settings information after sending to
2953 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2956 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2958 for (x = 0; x < p_ext_attr->num_val; x++)
2959 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2960 p_ext_attr->num_val = 0;
2961 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2963 p_app_settings->num_attrs = 0;
2967 /***************************************************************************
2969 ** Function handle_set_app_attr_val_response
2971 ** Description handles the the set attributes value response, if fails
2972 ** calls HAL callback to indicate the failure
2975 ***************************************************************************/
2976 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2978 uint8_t accepted = 0;
2979 bt_bdaddr_t rc_addr;
2981 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2983 /* For timeout pmeta_msg will be NULL, else we need to
2984 * check if this is accepted by TG
2986 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2990 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2993 /***************************************************************************
2995 ** Function handle_get_elem_attr_response
2997 ** Description handles the the element attributes response, calls
2998 ** HAL callback to update track change information.
3001 ***************************************************************************/
3002 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg,
3003 tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
3005 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3006 bt_bdaddr_t rc_addr;
3007 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
3008 btrc_element_attr_val_t *p_attr =
3009 (btrc_element_attr_val_t *)osi_calloc(buf_size);
3011 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3013 for (int i = 0; i < p_rsp->num_attr; i++) {
3014 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3015 /* Todo. Legth limit check to include null */
3016 if (p_rsp->p_attrs[i].name.str_len &&
3017 p_rsp->p_attrs[i].name.p_str) {
3018 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3019 p_rsp->p_attrs[i].name.str_len);
3020 osi_free_and_reset((void **)&p_rsp->p_attrs[i].name.p_str);
3023 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3024 &rc_addr, p_rsp->num_attr, p_attr);
3026 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3027 /* Retry for timeout case, this covers error handling
3028 * for continuation failure also.
3030 UINT32 attr_list[] = {
3031 AVRC_MEDIA_ATTR_ID_TITLE,
3032 AVRC_MEDIA_ATTR_ID_ARTIST,
3033 AVRC_MEDIA_ATTR_ID_ALBUM,
3034 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3035 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3036 AVRC_MEDIA_ATTR_ID_GENRE,
3037 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3039 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
3041 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
3042 __func__, p_rsp->status);
3046 /***************************************************************************
3048 ** Function handle_get_playstatus_response
3050 ** Description handles the the play status response, calls
3051 ** HAL callback to update play position.
3054 ***************************************************************************/
3055 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3057 bt_bdaddr_t rc_addr;
3059 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3061 if (p_rsp->status == AVRC_STS_NO_ERROR)
3063 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3064 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3068 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3069 __FUNCTION__, p_rsp->status);
3073 /***************************************************************************
3075 ** Function clear_cmd_timeout
3077 ** Description helper function to stop the command timeout timer
3080 ***************************************************************************/
3081 static void clear_cmd_timeout (UINT8 label)
3083 rc_transaction_t *p_txn;
3085 p_txn = get_transaction_by_lbl (label);
3088 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3092 if (p_txn->txn_timer != NULL)
3093 alarm_cancel(p_txn->txn_timer);
3096 /***************************************************************************
3098 ** Function handle_avk_rc_metamsg_rsp
3100 ** Description Handle RC metamessage response
3104 ***************************************************************************/
3105 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3107 tAVRC_RESPONSE avrc_response = {0};
3108 UINT8 scratch_buf[512] = {0};// this variable is unused
3112 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3113 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3115 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3116 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3117 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3119 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3120 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3121 __FUNCTION__, status, avrc_response.pdu,
3122 pmeta_msg->p_msg->vendor.hdr.ctype);
3124 switch (avrc_response.pdu)
3126 case AVRC_PDU_REGISTER_NOTIFICATION:
3127 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3128 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3130 /* Don't free the transaction Id */
3131 clear_cmd_timeout (pmeta_msg->label);
3136 case AVRC_PDU_GET_CAPABILITIES:
3137 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3140 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3141 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3144 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3145 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3148 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3149 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3152 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3153 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3156 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3157 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3160 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3161 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3164 case AVRC_PDU_GET_ELEMENT_ATTR:
3165 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3168 case AVRC_PDU_GET_PLAY_STATUS:
3169 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3172 release_transaction(pmeta_msg->label);
3176 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3177 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3182 /***************************************************************************
3184 ** Function handle_avk_rc_metamsg_cmd
3186 ** Description Handle RC metamessage response
3190 ***************************************************************************/
3191 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3193 tAVRC_COMMAND avrc_cmd = {0};
3194 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3195 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3196 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3197 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3198 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3200 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3201 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3202 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3204 if (status != AVRC_STS_NO_ERROR)
3207 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3208 __FUNCTION__, status);
3209 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3213 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3215 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3216 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3217 __FUNCTION__, dump_rc_notification_event_id(event_id));
3219 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3221 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3223 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3228 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3229 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3235 /***************************************************************************
3239 ** Description Closes the AVRC interface
3243 ***************************************************************************/
3244 static void cleanup()
3246 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3248 if (bt_rc_callbacks)
3250 bt_rc_callbacks = NULL;
3252 alarm_free(btif_rc_cb.rc_play_status_timer);
3253 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3255 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3258 /***************************************************************************
3260 ** Function cleanup_ctrl
3262 ** Description Closes the AVRC Controller interface
3266 ***************************************************************************/
3267 static void cleanup_ctrl()
3269 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3271 if (bt_rc_ctrl_callbacks)
3273 bt_rc_ctrl_callbacks = NULL;
3275 alarm_free(btif_rc_cb.rc_play_status_timer);
3276 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3278 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3281 /***************************************************************************
3283 ** Function getcapabilities_cmd
3285 ** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3289 ***************************************************************************/
3290 static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3292 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3293 rc_transaction_t *p_transaction = NULL;
3294 #if (AVRC_CTLR_INCLUDED == TRUE)
3295 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3297 bt_status_t tran_status=get_transaction(&p_transaction);
3298 if (BT_STATUS_SUCCESS != tran_status)
3299 return BT_STATUS_FAIL;
3301 tAVRC_COMMAND avrc_cmd = {0};
3302 BT_HDR *p_msg = NULL;
3303 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3304 avrc_cmd.get_caps.capability_id = cap_id;
3305 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3306 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3307 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3308 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3310 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3311 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3312 __FUNCTION__,p_transaction->lbl);
3313 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3314 data_start, p_msg->len);
3315 status = BT_STATUS_SUCCESS;
3316 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3320 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3321 __FUNCTION__, status);
3325 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3330 /***************************************************************************
3332 ** Function list_player_app_setting_attrib_cmd
3334 ** Description Get supported List Player Attributes
3338 ***************************************************************************/
3339 static bt_status_t list_player_app_setting_attrib_cmd(void)
3341 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3342 rc_transaction_t *p_transaction = NULL;
3343 #if (AVRC_CTLR_INCLUDED == TRUE)
3344 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3346 bt_status_t tran_status=get_transaction(&p_transaction);
3347 if (BT_STATUS_SUCCESS != tran_status)
3348 return BT_STATUS_FAIL;
3350 tAVRC_COMMAND avrc_cmd = {0};
3351 BT_HDR *p_msg = NULL;
3352 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3353 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3354 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3355 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3356 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3358 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3359 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3360 __FUNCTION__,p_transaction->lbl);
3361 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3362 data_start, p_msg->len);
3363 status = BT_STATUS_SUCCESS;
3364 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3369 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3370 __FUNCTION__, status);
3374 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3379 /***************************************************************************
3381 ** Function list_player_app_setting_value_cmd
3383 ** Description Get values of supported Player Attributes
3387 ***************************************************************************/
3388 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3390 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3391 rc_transaction_t *p_transaction=NULL;
3392 #if (AVRC_CTLR_INCLUDED == TRUE)
3393 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3395 bt_status_t tran_status=get_transaction(&p_transaction);
3396 if (BT_STATUS_SUCCESS != tran_status)
3397 return BT_STATUS_FAIL;
3399 tAVRC_COMMAND avrc_cmd = {0};
3400 BT_HDR *p_msg = NULL;
3401 avrc_cmd.list_app_values.attr_id = attrib_id;
3402 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3403 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3404 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3405 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3406 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3408 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3409 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3410 __FUNCTION__,p_transaction->lbl);
3411 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3412 data_start, p_msg->len);
3413 status = BT_STATUS_SUCCESS;
3414 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3418 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3422 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3427 /***************************************************************************
3429 ** Function get_player_app_setting_cmd
3431 ** Description Get current values of Player Attributes
3435 ***************************************************************************/
3436 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3438 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3439 rc_transaction_t *p_transaction = NULL;
3441 #if (AVRC_CTLR_INCLUDED == TRUE)
3442 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3444 bt_status_t tran_status=get_transaction(&p_transaction);
3445 if (BT_STATUS_SUCCESS != tran_status)
3446 return BT_STATUS_FAIL;
3448 tAVRC_COMMAND avrc_cmd = {0};
3449 BT_HDR *p_msg = NULL;
3450 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3451 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3452 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3453 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3455 for (count = 0; count < num_attrib; count++)
3457 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3459 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3460 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3462 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3463 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3464 __FUNCTION__,p_transaction->lbl);
3465 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3466 data_start, p_msg->len);
3467 status = BT_STATUS_SUCCESS;
3468 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3472 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3473 __FUNCTION__, status);
3477 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3482 /***************************************************************************
3484 ** Function change_player_app_setting
3486 ** Description Set current values of Player Attributes
3490 ***************************************************************************/
3491 static bt_status_t change_player_app_setting(bt_bdaddr_t *bd_addr, uint8_t num_attrib, uint8_t* attrib_ids, uint8_t* attrib_vals)
3493 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3494 rc_transaction_t *p_transaction = NULL;
3496 #if (AVRC_CTLR_INCLUDED == TRUE)
3497 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3499 bt_status_t tran_status=get_transaction(&p_transaction);
3500 if (BT_STATUS_SUCCESS != tran_status)
3501 return BT_STATUS_FAIL;
3503 tAVRC_COMMAND avrc_cmd = {0};
3504 BT_HDR *p_msg = NULL;
3505 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3506 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3507 avrc_cmd.set_app_val.num_val = num_attrib;
3508 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3509 avrc_cmd.set_app_val.p_vals =
3510 (tAVRC_APP_SETTING *)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
3511 for (count = 0; count < num_attrib; count++)
3513 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3514 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3516 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3517 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3519 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3520 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3521 __FUNCTION__,p_transaction->lbl);
3522 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3523 data_start, p_msg->len);
3524 status = BT_STATUS_SUCCESS;
3525 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3529 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3530 __FUNCTION__, status);
3533 osi_free_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
3535 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3540 /***************************************************************************
3542 ** Function get_player_app_setting_attr_text_cmd
3544 ** Description Get text description for app attribute
3548 ***************************************************************************/
3549 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3551 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3552 rc_transaction_t *p_transaction = NULL;
3554 #if (AVRC_CTLR_INCLUDED == TRUE)
3555 tAVRC_COMMAND avrc_cmd = {0};
3556 BT_HDR *p_msg = NULL;
3557 bt_status_t tran_status;
3560 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3562 tran_status = get_transaction(&p_transaction);
3563 if (BT_STATUS_SUCCESS != tran_status)
3564 return BT_STATUS_FAIL;
3566 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3567 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3568 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3570 for (count = 0; count < num_attrs; count++)
3572 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3574 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3575 if (status == AVRC_STS_NO_ERROR)
3577 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3578 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3579 __FUNCTION__, p_transaction->lbl);
3580 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3581 AVRC_CMD_STATUS, data_start, p_msg->len);
3583 status = BT_STATUS_SUCCESS;
3584 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3588 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3592 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3597 /***************************************************************************
3599 ** Function get_player_app_setting_val_text_cmd
3601 ** Description Get text description for app attribute values
3605 ***************************************************************************/
3606 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3608 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3609 rc_transaction_t *p_transaction = NULL;
3611 #if (AVRC_CTLR_INCLUDED == TRUE)
3612 tAVRC_COMMAND avrc_cmd = {0};
3613 BT_HDR *p_msg = NULL;
3614 bt_status_t tran_status;
3617 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3619 tran_status = get_transaction(&p_transaction);
3620 if (BT_STATUS_SUCCESS != tran_status)
3621 return BT_STATUS_FAIL;
3623 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3624 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3625 avrc_cmd.get_app_val_txt.num_val = num_vals;
3627 for (count = 0; count < num_vals; count++)
3629 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3631 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3632 if (status == AVRC_STS_NO_ERROR)
3634 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3635 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3636 __FUNCTION__, p_transaction->lbl);
3639 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3640 AVRC_CMD_STATUS, data_start, p_msg->len);
3641 status = BT_STATUS_SUCCESS;
3642 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3647 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3648 __FUNCTION__, status);
3652 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3657 /***************************************************************************
3659 ** Function register_notification_cmd
3661 ** Description Send Command to register for a Notification ID
3665 ***************************************************************************/
3666 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3669 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3670 #if (AVRC_CTLR_INCLUDED == TRUE)
3671 tAVRC_COMMAND avrc_cmd = {0};
3672 BT_HDR *p_msg = NULL;
3676 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3678 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3679 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3680 avrc_cmd.reg_notif.event_id = event_id;
3681 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3682 avrc_cmd.reg_notif.param = event_value;
3683 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3684 if (status == AVRC_STS_NO_ERROR)
3686 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3687 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3688 __FUNCTION__, label);
3691 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3692 data_start, p_msg->len);
3693 status = BT_STATUS_SUCCESS;
3698 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3699 __FUNCTION__, status);
3703 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3708 /***************************************************************************
3710 ** Function get_element_attribute_cmd
3712 ** Description Get Element Attribute for attributeIds
3716 ***************************************************************************/
3717 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3719 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3720 rc_transaction_t *p_transaction=NULL;
3722 #if (AVRC_CTLR_INCLUDED == TRUE)
3723 tAVRC_COMMAND avrc_cmd = {0};
3724 BT_HDR *p_msg = NULL;
3725 bt_status_t tran_status;
3728 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3729 __FUNCTION__, num_attribute, p_attr_ids[0]);
3731 tran_status = get_transaction(&p_transaction);
3732 if (BT_STATUS_SUCCESS != tran_status)
3733 return BT_STATUS_FAIL;
3735 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3736 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3737 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3738 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3739 for (count = 0; count < num_attribute; count++)
3741 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3744 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3745 if (status == AVRC_STS_NO_ERROR)
3747 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3748 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3749 __FUNCTION__, p_transaction->lbl);
3752 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3753 AVRC_CMD_STATUS, data_start, p_msg->len);
3754 status = BT_STATUS_SUCCESS;
3755 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3761 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3762 __FUNCTION__, status);
3766 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3771 /***************************************************************************
3773 ** Function get_play_status_cmd
3775 ** Description Get Element Attribute for attributeIds
3779 ***************************************************************************/
3780 static bt_status_t get_play_status_cmd(void)
3782 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3783 rc_transaction_t *p_transaction = NULL;
3784 #if (AVRC_CTLR_INCLUDED == TRUE)
3785 tAVRC_COMMAND avrc_cmd = {0};
3786 BT_HDR *p_msg = NULL;
3787 bt_status_t tran_status;
3790 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3791 tran_status = get_transaction(&p_transaction);
3792 if (BT_STATUS_SUCCESS != tran_status)
3793 return BT_STATUS_FAIL;
3795 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3796 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3797 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3798 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3799 if (status == AVRC_STS_NO_ERROR)
3801 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3802 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3803 __FUNCTION__, p_transaction->lbl);
3806 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3807 AVRC_CMD_STATUS, data_start, p_msg->len);
3808 status = BT_STATUS_SUCCESS;
3809 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3814 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3815 __FUNCTION__, status);
3819 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3825 /***************************************************************************
3827 ** Function set_volume_rsp
3829 ** Description Rsp for SetAbsoluteVolume Command
3833 ***************************************************************************/
3834 static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3836 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3837 #if (AVRC_CTLR_INCLUDED == TRUE)
3838 tAVRC_RESPONSE avrc_rsp;
3839 BT_HDR *p_msg = NULL;
3842 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3844 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3845 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3846 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3847 avrc_rsp.volume.volume = abs_vol;
3848 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3849 if (status == AVRC_STS_NO_ERROR)
3851 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3852 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3853 __FUNCTION__, btif_rc_cb.rc_vol_label);
3856 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3857 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3858 status = BT_STATUS_SUCCESS;
3863 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3864 __FUNCTION__, status);
3868 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3873 /***************************************************************************
3875 ** Function send_register_abs_vol_rsp
3877 ** Description Rsp for Notification of Absolute Volume
3881 ***************************************************************************/
3882 static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3883 uint8_t abs_vol, uint8_t label)
3885 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3886 tAVRC_RESPONSE avrc_rsp;
3887 BT_HDR *p_msg = NULL;
3888 #if (AVRC_CTLR_INCLUDED == TRUE)
3889 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
3892 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3893 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3894 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3895 avrc_rsp.reg_notif.param.volume = abs_vol;
3896 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
3898 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3899 if (status == AVRC_STS_NO_ERROR) {
3900 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3902 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3903 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3904 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3905 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3906 data_start, p_msg->len, 0);
3907 status = BT_STATUS_SUCCESS;
3909 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3915 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
3920 /***************************************************************************
3922 ** Function send_groupnavigation_cmd
3924 ** Description Send Pass-Through command
3928 ***************************************************************************/
3929 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3932 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3933 #if (AVRC_CTLR_INCLUDED == TRUE)
3934 rc_transaction_t *p_transaction=NULL;
3935 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3936 key_code, key_state);
3938 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3940 bt_status_t tran_status = get_transaction(&p_transaction);
3941 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
3942 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3943 UINT8* start = buffer;
3944 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3946 UINT8_TO_BE_STREAM(start, key_code);
3947 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3949 (tBTA_AV_STATE)key_state, buffer,
3950 AVRC_PASS_THRU_GROUP_LEN);
3951 status = BT_STATUS_SUCCESS;
3952 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3957 status = BT_STATUS_FAIL;
3958 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3963 status = BT_STATUS_FAIL;
3964 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3967 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3972 /***************************************************************************
3974 ** Function send_passthrough_cmd
3976 ** Description Send Pass-Through command
3980 ***************************************************************************/
3981 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3983 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3984 #if (AVRC_CTLR_INCLUDED == TRUE)
3986 rc_transaction_t *p_transaction=NULL;
3987 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3988 key_code, key_state);
3989 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3991 bt_status_t tran_status = get_transaction(&p_transaction);
3992 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
3994 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3995 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
3996 status = BT_STATUS_SUCCESS;
3997 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
4001 status = BT_STATUS_FAIL;
4002 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
4007 status = BT_STATUS_FAIL;
4008 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
4011 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
4016 static const btrc_interface_t bt_rc_interface = {
4017 sizeof(bt_rc_interface),
4019 get_play_status_rsp,
4020 NULL, /* list_player_app_attr_rsp */
4021 NULL, /* list_player_app_value_rsp */
4022 NULL, /* get_player_app_value_rsp */
4023 NULL, /* get_player_app_attr_text_rsp */
4024 NULL, /* get_player_app_value_text_rsp */
4025 get_element_attr_rsp,
4026 NULL, /* set_player_app_value_rsp */
4027 register_notification_rsp,
4032 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4033 sizeof(bt_rc_ctrl_interface),
4035 send_passthrough_cmd,
4036 send_groupnavigation_cmd,
4037 change_player_app_setting,
4039 volume_change_notification_rsp,
4043 /*******************************************************************************
4045 ** Function btif_rc_get_interface
4047 ** Description Get the AVRCP Target callback interface
4049 ** Returns btav_interface_t
4051 *******************************************************************************/
4052 const btrc_interface_t *btif_rc_get_interface(void)
4054 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4055 return &bt_rc_interface;
4058 /*******************************************************************************
4060 ** Function btif_rc_ctrl_get_interface
4062 ** Description Get the AVRCP Controller callback interface
4064 ** Returns btav_interface_t
4066 *******************************************************************************/
4067 const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4069 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4070 return &bt_rc_ctrl_interface;
4073 /*******************************************************************************
4074 ** Function initialize_transaction
4076 ** Description Initializes fields of the transaction structure
4079 *******************************************************************************/
4080 static void initialize_transaction(int lbl)
4082 pthread_mutex_lock(&device.lbllock);
4083 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4084 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4085 clear_cmd_timeout(lbl);
4087 device.transaction[lbl].lbl = lbl;
4088 device.transaction[lbl].in_use=FALSE;
4089 device.transaction[lbl].handle=0;
4091 pthread_mutex_unlock(&device.lbllock);
4094 /*******************************************************************************
4095 ** Function lbl_init
4097 ** Description Initializes label structures and mutexes.
4100 *******************************************************************************/
4103 memset(&device,0,sizeof(rc_device_t));
4104 pthread_mutexattr_t attr;
4105 pthread_mutexattr_init(&attr);
4106 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4107 pthread_mutex_init(&(device.lbllock), &attr);
4108 pthread_mutexattr_destroy(&attr);
4109 init_all_transactions();
4112 /*******************************************************************************
4114 ** Function init_all_transactions
4116 ** Description Initializes all transactions
4119 *******************************************************************************/
4120 void init_all_transactions()
4123 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4125 initialize_transaction(txn_indx);
4129 /*******************************************************************************
4131 ** Function get_transaction_by_lbl
4133 ** Description Will return a transaction based on the label. If not inuse
4134 ** will return an error.
4136 ** Returns bt_status_t
4137 *******************************************************************************/
4138 rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4140 rc_transaction_t *transaction = NULL;
4141 pthread_mutex_lock(&device.lbllock);
4143 /* Determine if this is a valid label */
4144 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4146 if (FALSE==device.transaction[lbl].in_use)
4152 transaction = &(device.transaction[lbl]);
4153 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
4157 pthread_mutex_unlock(&device.lbllock);
4161 /*******************************************************************************
4163 ** Function get_transaction
4165 ** Description Obtains the transaction details.
4167 ** Returns bt_status_t
4168 *******************************************************************************/
4170 bt_status_t get_transaction(rc_transaction_t **ptransaction)
4172 bt_status_t result = BT_STATUS_NOMEM;
4174 pthread_mutex_lock(&device.lbllock);
4176 // Check for unused transactions
4177 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4179 if (FALSE==device.transaction[i].in_use)
4181 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
4182 device.transaction[i].in_use = TRUE;
4183 *ptransaction = &(device.transaction[i]);
4184 result = BT_STATUS_SUCCESS;
4189 pthread_mutex_unlock(&device.lbllock);
4193 /*******************************************************************************
4195 ** Function release_transaction
4197 ** Description Will release a transaction for reuse
4199 ** Returns bt_status_t
4200 *******************************************************************************/
4201 void release_transaction(UINT8 lbl)
4203 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4205 /* If the transaction is in use... */
4206 if (transaction != NULL)
4208 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
4209 initialize_transaction(lbl);
4213 /*******************************************************************************
4215 ** Function lbl_destroy
4217 ** Description Cleanup of the mutex
4220 *******************************************************************************/
4223 pthread_mutex_destroy(&(device.lbllock));
4226 /*******************************************************************************
4227 ** Function sleep_ms
4229 ** Description Sleep the calling thread unconditionally for
4230 ** |timeout_ms| milliseconds.
4233 *******************************************************************************/
4234 static void sleep_ms(period_ms_t timeout_ms) {
4235 struct timespec delay;
4236 delay.tv_sec = timeout_ms / 1000;
4237 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4239 OSI_NO_INTR(nanosleep(&delay, &delay));
4242 static bool absolute_volume_disabled() {
4243 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
4244 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
4245 if (strncmp(volume_disabled, "true", 4) == 0) {
4246 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);