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));
319 return write(fd, &event, sizeof(event));
322 void send_key (int fd, uint16_t key, int pressed)
324 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
332 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
333 send_event(fd, EV_KEY, key, pressed);
334 send_event(fd, EV_SYN, SYN_REPORT, 0);
337 /************** uinput related functions **************/
338 int uinput_driver_check()
341 for (i=0; i < MAX_UINPUT_PATHS; i++)
343 if (access(uinput_dev_path[i], O_RDWR) == 0) {
347 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
351 int uinput_create(char *name)
353 struct uinput_dev dev;
356 for(x=0; x < MAX_UINPUT_PATHS; x++)
358 fd = open(uinput_dev_path[x], O_RDWR);
363 if (x == MAX_UINPUT_PATHS) {
364 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
367 memset(&dev, 0, sizeof(dev));
369 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
371 dev.id.bustype = BUS_BLUETOOTH;
372 dev.id.vendor = 0x0000;
373 dev.id.product = 0x0000;
374 dev.id.version = 0x0000;
376 if (write(fd, &dev, sizeof(dev)) < 0) {
377 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
382 ioctl(fd, UI_SET_EVBIT, EV_KEY);
383 ioctl(fd, UI_SET_EVBIT, EV_REL);
384 ioctl(fd, UI_SET_EVBIT, EV_SYN);
386 for (x = 0; key_map[x].name != NULL; x++)
387 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
389 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
390 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
397 int init_uinput (void)
399 char *name = "AVRCP";
401 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
402 uinput_fd = uinput_create(name);
404 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
405 __FUNCTION__, name, uinput_fd);
407 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
408 __FUNCTION__, name, uinput_fd);
413 void close_uinput (void)
415 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
417 ioctl(uinput_fd, UI_DEV_DESTROY);
424 #if (AVRC_CTLR_INCLUDED == TRUE)
425 void rc_cleanup_sent_cmd (void *p_data)
427 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
431 void handle_rc_ctrl_features(BD_ADDR bd_addr)
433 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
434 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
435 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
439 bdcpy(rc_addr.address,bd_addr);
441 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
442 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
444 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
446 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
447 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
448 (btif_rc_cb.rc_features_processed != TRUE))
450 rc_features |= BTRC_FEAT_METADATA;
451 /* Mark rc features processed to avoid repeating
452 * the AVRCP procedure every time on receiving this
455 btif_rc_cb.rc_features_processed = TRUE;
456 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
458 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
459 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
464 void handle_rc_features(BD_ADDR bd_addr)
466 if (bt_rc_callbacks != NULL)
468 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
471 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
472 bt_bdaddr_t avdtp_addr = btif_av_get_addr();
474 bdstr_t addr1, addr2;
475 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
476 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
477 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
479 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
480 || absolute_volume_disabled()
481 || bdcmp(avdtp_addr.address, rc_addr.address))
482 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
484 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
486 rc_features |= BTRC_FEAT_BROWSE;
489 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
490 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
491 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
493 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
497 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
499 rc_features |= BTRC_FEAT_METADATA;
502 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
503 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
505 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
506 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
507 __FUNCTION__, btif_rc_cb.rc_vol_label);
508 // Register for volume change on connect
509 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
510 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
512 rc_transaction_t *p_transaction=NULL;
513 bt_status_t status = BT_STATUS_NOT_READY;
514 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
516 status=get_transaction(&p_transaction);
520 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
521 if (NULL!=p_transaction)
523 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
524 __FUNCTION__, btif_rc_cb.rc_vol_label);
528 status=get_transaction(&p_transaction);
531 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
533 btif_rc_cb.rc_vol_label=p_transaction->lbl;
534 register_volumechange(btif_rc_cb.rc_vol_label);
541 /***************************************************************************
542 * Function handle_rc_connect
544 * - Argument: tBTA_AV_RC_OPEN RC open data structure
546 * - Description: RC connection event handler
548 ***************************************************************************/
549 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
551 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
552 bt_status_t result = BT_STATUS_SUCCESS;
553 #if (AVRC_CTLR_INCLUDED == TRUE)
557 if (p_rc_open->status == BTA_AV_SUCCESS)
559 //check if already some RC is connected
560 if (btif_rc_cb.rc_connected)
562 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
563 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
564 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
565 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
567 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
568 BTA_AvCloseRc(p_rc_open->rc_handle);
572 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
573 btif_rc_cb.rc_features = p_rc_open->peer_features;
574 btif_rc_cb.rc_vol_label=MAX_LABEL;
575 btif_rc_cb.rc_volume=MAX_VOLUME;
577 btif_rc_cb.rc_connected = TRUE;
578 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
580 /* on locally initiated connection we will get remote features as part of connect */
581 if (btif_rc_cb.rc_features != 0)
582 handle_rc_features(btif_rc_cb.rc_addr);
585 result = uinput_driver_check();
586 if (result == BT_STATUS_SUCCESS)
593 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
596 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
597 #if (AVRC_CTLR_INCLUDED == TRUE)
598 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
599 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
600 if (bt_rc_ctrl_callbacks != NULL)
602 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
604 /* report connection state if remote device is AVRCP target */
605 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
606 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
607 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
609 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
615 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
616 __FUNCTION__, p_rc_open->status);
617 btif_rc_cb.rc_connected = FALSE;
621 /***************************************************************************
622 * Function handle_rc_disconnect
624 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
626 * - Description: RC disconnection event handler
628 ***************************************************************************/
629 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
631 #if (AVRC_CTLR_INCLUDED == TRUE)
633 tBTA_AV_FEAT features;
635 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
636 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
637 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
639 BTIF_TRACE_ERROR("Got disconnect of unknown device");
642 #if (AVRC_CTLR_INCLUDED == TRUE)
643 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
644 features = btif_rc_cb.rc_features;
645 /* Clean up AVRCP procedure flags */
646 memset(&btif_rc_cb.rc_app_settings, 0,
647 sizeof(btif_rc_player_app_settings_t));
648 btif_rc_cb.rc_features_processed = FALSE;
649 btif_rc_cb.rc_procedure_complete = FALSE;
650 rc_stop_play_status_timer();
651 /* Check and clear the notification event list */
652 if (btif_rc_cb.rc_supported_event_list != NULL)
654 list_clear(btif_rc_cb.rc_supported_event_list);
655 btif_rc_cb.rc_supported_event_list = NULL;
658 btif_rc_cb.rc_handle = 0;
659 btif_rc_cb.rc_connected = FALSE;
660 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
661 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
663 btif_rc_cb.rc_features = 0;
664 btif_rc_cb.rc_vol_label=MAX_LABEL;
665 btif_rc_cb.rc_volume=MAX_VOLUME;
666 init_all_transactions();
667 if (bt_rc_callbacks != NULL)
673 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
676 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
677 #if (AVRC_CTLR_INCLUDED == TRUE)
678 /* report connection state if device is AVRCP target */
679 if (bt_rc_ctrl_callbacks != NULL)
681 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
686 /***************************************************************************
687 * Function handle_rc_passthrough_cmd
689 * - Argument: tBTA_AV_RC rc_id remote control command ID
690 * tBTA_AV_STATE key_state status of key press
692 * - Description: Remote control command handler
694 ***************************************************************************/
695 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
700 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
702 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
705 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
706 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
708 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
710 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
711 btif_rc_cb.rc_pending_play = TRUE;
716 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
718 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
719 btif_rc_cb.rc_pending_play = FALSE;
722 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
723 return; // this command is not to be sent to UINPUT, only needed for PTS
726 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
728 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
732 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
740 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
741 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
745 for (i = 0; key_map[i].name != NULL; i++) {
746 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
747 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
749 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
750 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
751 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
752 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
753 * The fix is to generate a release right after the press and drown the 'actual'
756 if ((key_map[i].release_quirk == 1) && (pressed == 0))
758 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
759 __FUNCTION__, key_map[i].name);
762 send_key(uinput_fd, key_map[i].mapped_id, pressed);
763 if ((key_map[i].release_quirk == 1) && (pressed == 1))
766 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
767 __FUNCTION__, key_map[i].name);
768 send_key(uinput_fd, key_map[i].mapped_id, 0);
774 if (key_map[i].name == NULL)
775 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
776 p_remote_cmd->rc_id, status);
779 /***************************************************************************
780 * Function handle_rc_passthrough_rsp
782 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
784 * - Description: Remote control passthrough response handler
786 ***************************************************************************/
787 void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
789 #if (AVRC_CTLR_INCLUDED == TRUE)
791 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
794 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
805 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
807 release_transaction(p_remote_rsp->label);
808 if (bt_rc_ctrl_callbacks != NULL) {
809 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
814 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
817 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
821 /***************************************************************************
822 * Function handle_rc_vendorunique_rsp
824 * - Argument: tBTA_AV_REMOTE_RSP command response
826 * - Description: Remote control vendor unique response handler
828 ***************************************************************************/
829 void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
831 #if (AVRC_CTLR_INCLUDED == TRUE)
834 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
837 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
848 if (p_remote_rsp->len > 0)
850 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
851 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
852 osi_free_and_reset((void **)&p_remote_rsp->p_data);
854 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
856 release_transaction(p_remote_rsp->label);
857 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
861 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
864 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
868 void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
870 tAVRC_RESPONSE avrc_rsp = {0};
871 avrc_rsp.rsp.pdu = pavrc_command->pdu;
872 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
873 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
875 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
876 avrc_rsp.reg_notif.param.uid_counter = 0;
878 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
879 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
883 /***************************************************************************
884 * Function handle_rc_metamsg_cmd
886 * - Argument: tBTA_AV_VENDOR Structure containing the received
889 * - Description: Remote control metamsg command handler (AVRCP 1.3)
891 ***************************************************************************/
892 void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
894 /* Parse the metamsg command and pass it on to BTL-IFS */
895 UINT8 scratch_buf[512] = {0};
896 tAVRC_COMMAND avrc_command = {0};
899 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
901 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
903 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
906 if (pmeta_msg->len < 3)
908 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
913 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
915 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
917 rc_transaction_t *transaction=NULL;
918 transaction=get_transaction_by_lbl(pmeta_msg->label);
919 if (NULL!=transaction)
921 handle_rc_metamsg_rsp(pmeta_msg);
925 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
926 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
932 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
933 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
939 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
940 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
941 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
943 if (status != AVRC_STS_NO_ERROR)
946 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
947 __FUNCTION__, status);
948 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
952 /* if RegisterNotification, add it to our registered queue */
954 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
956 UINT8 event_id = avrc_command.reg_notif.event_id;
957 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
958 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
959 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
960 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
962 if (event_id == AVRC_EVT_UIDS_CHANGE)
964 handle_uid_changed_notification(pmeta_msg, &avrc_command);
970 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
971 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
973 /* Since handle_rc_metamsg_cmd() itself is called from
974 *btif context, no context switching is required. Invoke
975 * btif_rc_upstreams_evt directly from here. */
976 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
981 /***************************************************************************
983 ** Function btif_rc_handler
985 ** Description RC event handler
987 ***************************************************************************/
988 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
990 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
993 case BTA_AV_RC_OPEN_EVT:
995 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
996 handle_rc_connect( &(p_data->rc_open) );
999 case BTA_AV_RC_CLOSE_EVT:
1001 handle_rc_disconnect( &(p_data->rc_close) );
1004 case BTA_AV_REMOTE_CMD_EVT:
1006 if (bt_rc_callbacks != NULL)
1008 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1009 __FUNCTION__, p_data->remote_cmd.rc_id,
1010 p_data->remote_cmd.key_state);
1011 /** In race conditions just after 2nd AVRCP is connected
1012 * remote might send pass through commands, so check for
1013 * Rc handle before processing pass through commands
1015 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1017 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1021 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1026 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1031 #if (AVRC_CTLR_INCLUDED == TRUE)
1032 case BTA_AV_REMOTE_RSP_EVT:
1034 BTIF_TRACE_DEBUG("%s RSP: rc_id:0x%x key_state:%d",
1035 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1036 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1038 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1042 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1048 case BTA_AV_RC_FEAT_EVT:
1050 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
1051 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
1052 handle_rc_features(p_data->rc_feat.peer_addr);
1053 #if (AVRC_CTLR_INCLUDED == TRUE)
1054 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1056 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1062 case BTA_AV_META_MSG_EVT:
1064 if (bt_rc_callbacks != NULL)
1066 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1068 p_data->meta_msg.code,
1069 p_data->meta_msg.label);
1070 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1072 p_data->meta_msg.company_id,
1073 p_data->meta_msg.len,
1074 p_data->meta_msg.rc_handle);
1075 /* handle the metamsg command */
1076 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1077 /* Free the Memory allocated for tAVRC_MSG */
1079 #if (AVRC_CTLR_INCLUDED == TRUE)
1080 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1082 /* This is case of Sink + CT + TG(for abs vol)) */
1083 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1085 p_data->meta_msg.code,
1086 p_data->meta_msg.label);
1087 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1089 p_data->meta_msg.company_id,
1090 p_data->meta_msg.len,
1091 p_data->meta_msg.rc_handle);
1092 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1093 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1095 /* Its a response */
1096 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1098 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1101 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1108 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1114 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
1118 /***************************************************************************
1120 ** Function btif_rc_get_connected_peer
1122 ** Description Fetches the connected headset's BD_ADDR if any
1124 ***************************************************************************/
1125 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1127 if (btif_rc_cb.rc_connected == TRUE) {
1128 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1134 /***************************************************************************
1136 ** Function btif_rc_get_connected_peer_handle
1138 ** Description Fetches the connected headset's handle if any
1140 ***************************************************************************/
1141 UINT8 btif_rc_get_connected_peer_handle(void)
1143 return btif_rc_cb.rc_handle;
1146 /***************************************************************************
1148 ** Function btif_rc_check_handle_pending_play
1150 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1152 ***************************************************************************/
1154 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
1155 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1159 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
1160 if (btif_rc_cb.rc_pending_play)
1164 tBTA_AV_REMOTE_CMD remote_cmd;
1165 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
1167 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1168 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1169 remote_cmd.rc_id = AVRC_ID_PLAY;
1170 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1171 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1173 /* delay sending to app, else there is a timing issue in the framework,
1174 ** which causes the audio to be on th device's speaker. Delay between
1178 /* send to app - both PRESSED & RELEASED */
1179 remote_cmd.key_state = AVRC_STATE_PRESS;
1180 handle_rc_passthrough_cmd( &remote_cmd );
1184 remote_cmd.key_state = AVRC_STATE_RELEASE;
1185 handle_rc_passthrough_cmd( &remote_cmd );
1187 btif_rc_cb.rc_pending_play = FALSE;
1191 /* Generic reject response */
1192 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1194 UINT8 ctype = AVRC_RSP_REJ;
1195 tAVRC_RESPONSE avrc_rsp;
1196 BT_HDR *p_msg = NULL;
1197 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1199 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1200 avrc_rsp.rsp.pdu = pdu;
1201 avrc_rsp.rsp.status = status;
1203 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1205 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
1206 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1207 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1211 /***************************************************************************
1212 * Function send_metamsg_rsp
1215 * rc_handle RC handle corresponding to the connected RC
1216 * label Label of the RC response
1217 * code Response type
1218 * pmetamsg_resp Vendor response
1220 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1222 ***************************************************************************/
1223 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1224 tAVRC_RESPONSE *pmetamsg_resp)
1230 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
1234 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
1235 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1237 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1239 ctype = AVRC_RSP_REJ;
1243 if ( code < AVRC_RSP_NOT_IMPL)
1245 if (code == AVRC_CMD_NOTIF)
1247 ctype = AVRC_RSP_INTERIM;
1249 else if (code == AVRC_CMD_STATUS)
1251 ctype = AVRC_RSP_IMPL_STBL;
1255 ctype = AVRC_RSP_ACCEPT;
1263 /* if response is for register_notification, make sure the rc has
1264 actually registered for this */
1265 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
1267 BOOLEAN bSent = FALSE;
1268 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1269 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1271 /* de-register this notification for a CHANGED response */
1272 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
1273 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
1274 btif_rc_cb.rc_handle, event_id, bNotify);
1277 BT_HDR *p_msg = NULL;
1280 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1281 pmetamsg_resp, &p_msg)) )
1283 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
1284 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1286 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1291 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
1292 __FUNCTION__, status);
1299 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
1300 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1305 /* All other commands go here */
1307 BT_HDR *p_msg = NULL;
1310 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1312 if (status == AVRC_STS_NO_ERROR)
1314 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1318 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1319 __FUNCTION__, status);
1324 static UINT8 opcode_from_pdu(UINT8 pdu)
1330 case AVRC_PDU_NEXT_GROUP:
1331 case AVRC_PDU_PREV_GROUP: /* pass thru */
1332 opcode = AVRC_OP_PASS_THRU;
1335 default: /* vendor */
1336 opcode = AVRC_OP_VENDOR;
1343 /*******************************************************************************
1345 ** Function btif_rc_upstreams_evt
1347 ** Description Executes AVRC UPSTREAMS events in btif context.
1351 *******************************************************************************/
1352 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1354 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1355 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1359 case AVRC_PDU_GET_PLAY_STATUS:
1361 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1362 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1365 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1366 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1367 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1368 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1369 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1370 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1372 /* TODO: Add support for Application Settings */
1373 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
1376 case AVRC_PDU_GET_ELEMENT_ATTR:
1378 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1380 memset(&element_attrs, 0, sizeof(element_attrs));
1381 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1383 /* CT requests for all attributes */
1385 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1386 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
1388 element_attrs[attr_cnt] = attr_cnt + 1;
1391 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1393 /* 0xff indicates, no attributes requested - reject */
1394 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1395 AVRC_STS_BAD_PARAM);
1400 int attr_cnt, filled_attr_count;
1403 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1404 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1405 * Fill only valid entries.
1407 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1408 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1410 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1411 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1413 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1415 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1417 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1420 if (filled_attr_count == num_attr)
1422 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1428 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1429 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1432 case AVRC_PDU_REGISTER_NOTIFICATION:
1434 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1435 pavrc_cmd->reg_notif.param == 0)
1437 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
1439 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1440 /* de-register this notification for a rejected response */
1441 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1444 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1445 pavrc_cmd->reg_notif.param);
1448 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1450 tAVRC_RESPONSE avrc_rsp;
1451 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
1452 if (btif_rc_cb.rc_connected == TRUE)
1454 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1455 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1456 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1457 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1458 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1464 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1465 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1472 #if (AVRC_CTLR_INCLUDED == TRUE)
1473 /*******************************************************************************
1475 ** Function btif_rc_ctrl_upstreams_rsp_cmd
1477 ** Description Executes AVRC UPSTREAMS response events in btif context.
1481 *******************************************************************************/
1482 static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1485 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1486 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1487 bt_bdaddr_t rc_addr;
1488 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1489 #if (AVRC_CTLR_INCLUDED == TRUE)
1492 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1493 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1494 pavrc_cmd->volume.volume, label);
1496 case AVRC_PDU_REGISTER_NOTIFICATION:
1497 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1499 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1508 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1509 /*******************************************************************************
1511 ** Function btif_rc_upstreams_rsp_evt
1513 ** Description Executes AVRC UPSTREAMS response events in btif context.
1517 *******************************************************************************/
1518 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1520 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1521 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1525 case AVRC_PDU_REGISTER_NOTIFICATION:
1527 if (AVRC_RSP_CHANGED==ctype)
1528 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1529 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1533 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1535 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1536 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1537 if (AVRC_RSP_ACCEPT==ctype)
1538 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1539 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1549 /************************************************************************************
1550 ** AVRCP API Functions
1551 ************************************************************************************/
1553 /*******************************************************************************
1557 ** Description Initializes the AVRC interface
1559 ** Returns bt_status_t
1561 *******************************************************************************/
1562 static bt_status_t init(btrc_callbacks_t* callbacks )
1564 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1565 bt_status_t result = BT_STATUS_SUCCESS;
1567 if (bt_rc_callbacks)
1568 return BT_STATUS_DONE;
1570 bt_rc_callbacks = callbacks;
1571 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1572 btif_rc_cb.rc_vol_label=MAX_LABEL;
1573 btif_rc_cb.rc_volume=MAX_VOLUME;
1579 /*******************************************************************************
1581 ** Function init_ctrl
1583 ** Description Initializes the AVRC interface
1585 ** Returns bt_status_t
1587 *******************************************************************************/
1588 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1590 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1591 bt_status_t result = BT_STATUS_SUCCESS;
1593 if (bt_rc_ctrl_callbacks)
1594 return BT_STATUS_DONE;
1596 bt_rc_ctrl_callbacks = callbacks;
1597 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1598 btif_rc_cb.rc_vol_label=MAX_LABEL;
1599 btif_rc_cb.rc_volume=MAX_VOLUME;
1605 static void rc_ctrl_procedure_complete ()
1607 if (btif_rc_cb.rc_procedure_complete == TRUE)
1611 btif_rc_cb.rc_procedure_complete = TRUE;
1612 UINT32 attr_list[] = {
1613 AVRC_MEDIA_ATTR_ID_TITLE,
1614 AVRC_MEDIA_ATTR_ID_ARTIST,
1615 AVRC_MEDIA_ATTR_ID_ALBUM,
1616 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1617 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1618 AVRC_MEDIA_ATTR_ID_GENRE,
1619 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1621 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1624 /***************************************************************************
1626 ** Function get_play_status_rsp
1628 ** Description Returns the current play status.
1629 ** This method is called in response to
1630 ** GetPlayStatus request.
1632 ** Returns bt_status_t
1634 ***************************************************************************/
1635 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1638 tAVRC_RESPONSE avrc_rsp;
1640 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1641 avrc_rsp.get_play_status.song_len = song_len;
1642 avrc_rsp.get_play_status.song_pos = song_pos;
1643 avrc_rsp.get_play_status.play_status = play_status;
1645 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1646 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1647 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1648 /* Send the response */
1649 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1650 return BT_STATUS_SUCCESS;
1653 /***************************************************************************
1655 ** Function get_element_attr_rsp
1657 ** Description Returns the current songs' element attributes
1660 ** Returns bt_status_t
1662 ***************************************************************************/
1663 static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1665 tAVRC_RESPONSE avrc_rsp;
1667 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1669 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1673 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1677 for (i=0; i<num_attr; i++) {
1678 element_attrs[i].attr_id = p_attrs[i].attr_id;
1679 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1680 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1681 element_attrs[i].name.p_str = p_attrs[i].text;
1682 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
1683 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1684 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1685 element_attrs[i].name.p_str);
1687 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1689 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1690 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1691 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1692 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1693 /* Send the response */
1694 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1695 return BT_STATUS_SUCCESS;
1698 /***************************************************************************
1700 ** Function register_notification_rsp
1702 ** Description Response to the register notification request.
1705 ** Returns bt_status_t
1707 ***************************************************************************/
1708 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1709 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1711 tAVRC_RESPONSE avrc_rsp;
1713 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1714 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1716 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
1717 return BT_STATUS_NOT_READY;
1719 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1720 avrc_rsp.reg_notif.event_id = event_id;
1724 case BTRC_EVT_PLAY_STATUS_CHANGED:
1725 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1726 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1727 btif_av_clear_remote_suspend_flag();
1729 case BTRC_EVT_TRACK_CHANGE:
1730 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1732 case BTRC_EVT_PLAY_POS_CHANGED:
1733 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1736 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1737 return BT_STATUS_UNHANDLED;
1740 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1741 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1742 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1744 /* Send the response. */
1745 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1746 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1747 return BT_STATUS_SUCCESS;
1750 /***************************************************************************
1752 ** Function set_volume
1754 ** Description Send current volume setting to remote side.
1755 ** Support limited to SetAbsoluteVolume
1756 ** This can be enhanced to support Relative Volume (AVRCP 1.0).
1757 ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1758 ** as opposed to absolute volume level
1759 ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1761 ** Returns bt_status_t
1763 ***************************************************************************/
1764 static bt_status_t set_volume(uint8_t volume)
1766 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1768 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1769 rc_transaction_t *p_transaction=NULL;
1771 if (btif_rc_cb.rc_volume==volume)
1773 status=BT_STATUS_DONE;
1774 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
1778 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1779 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1781 tAVRC_COMMAND avrc_cmd = {0};
1782 BT_HDR *p_msg = NULL;
1784 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
1785 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1786 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1787 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1788 avrc_cmd.volume.volume = volume;
1790 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1792 bt_status_t tran_status=get_transaction(&p_transaction);
1793 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
1795 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
1796 __FUNCTION__,p_transaction->lbl);
1797 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1798 status = BT_STATUS_SUCCESS;
1803 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
1804 __FUNCTION__, tran_status);
1805 status = BT_STATUS_FAIL;
1810 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
1811 __FUNCTION__, status);
1812 status = BT_STATUS_FAIL;
1816 status=BT_STATUS_NOT_READY;
1820 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1821 /***************************************************************************
1823 ** Function register_volumechange
1825 ** Description Register for volume change notification from remote side.
1829 ***************************************************************************/
1831 static void register_volumechange (UINT8 lbl)
1833 tAVRC_COMMAND avrc_cmd = {0};
1834 BT_HDR *p_msg = NULL;
1835 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
1836 rc_transaction_t *p_transaction=NULL;
1838 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
1840 avrc_cmd.cmd.opcode=0x00;
1841 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1842 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1843 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1844 avrc_cmd.reg_notif.param = 0;
1846 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
1847 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1848 p_transaction = get_transaction_by_lbl(lbl);
1849 if (p_transaction != NULL) {
1850 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1851 AVRC_CMD_NOTIF, p_msg);
1852 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1855 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1859 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
1863 /***************************************************************************
1865 ** Function handle_rc_metamsg_rsp
1867 ** Description Handle RC metamessage response
1871 ***************************************************************************/
1872 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1874 tAVRC_RESPONSE avrc_response = {0};
1875 UINT8 scratch_buf[512] = {0};
1876 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1878 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
1879 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1880 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1882 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
1883 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
1884 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1885 status, pmeta_msg->label);
1887 if (status != AVRC_STS_NO_ERROR)
1889 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1890 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1891 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1893 btif_rc_cb.rc_vol_label=MAX_LABEL;
1894 release_transaction(btif_rc_cb.rc_vol_label);
1896 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1898 release_transaction(pmeta_msg->label);
1902 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1903 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1904 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1906 // Just discard the message, if the device sends back with an incorrect label
1907 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
1908 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1914 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
1915 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1919 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1920 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1921 && AVRC_RSP_CHANGED==pmeta_msg->code)
1923 /* re-register for volume change notification */
1924 // Do not re-register for rejected case, as it might get into endless loop
1925 register_volumechange(btif_rc_cb.rc_vol_label);
1927 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1929 /* free up the label here */
1930 release_transaction(pmeta_msg->label);
1933 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
1934 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1935 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1940 #if (AVRC_CTLR_INCLUDED == TRUE)
1941 /***************************************************************************
1943 ** Function iterate_supported_event_list_for_interim_rsp
1945 ** Description iterator callback function to match the event and handle
1947 ** Returns true to continue iterating, false to stop
1949 ***************************************************************************/
1950 bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1953 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1955 p_event_id = (UINT8*)cb_data;
1957 if (p_event->event_id == *p_event_id)
1959 p_event->status = eINTERIM;
1965 /***************************************************************************
1967 ** Function iterate_supported_event_list_for_timeout
1969 ** Description Iterator callback function for timeout handling.
1970 ** As part of the failure handling, it releases the
1971 ** transaction label and removes the event from list,
1972 ** this event will not be requested again during
1973 ** the lifetime of the connection.
1974 ** Returns false to stop iterating, true to continue
1976 ***************************************************************************/
1977 bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1980 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1982 label = (*(UINT8*)cb_data) & 0xFF;
1984 if (p_event->label == label)
1986 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
1992 /***************************************************************************
1994 ** Function rc_notification_interim_timout
1996 ** Description Interim response timeout handler.
1997 ** Runs the iterator to check and clear the timed out event.
1998 ** Proceeds to register for the unregistered events.
2001 ***************************************************************************/
2002 static void rc_notification_interim_timout (UINT8 label)
2006 list_foreach(btif_rc_cb.rc_supported_event_list,
2007 iterate_supported_event_list_for_timeout, &label);
2008 /* Timeout happened for interim response for the registered event,
2009 * check if there are any pending for registration
2011 node = list_begin(btif_rc_cb.rc_supported_event_list);
2012 while (node != NULL)
2014 btif_rc_supported_event_t *p_event;
2016 p_event = (btif_rc_supported_event_t *)list_node(node);
2017 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2019 register_for_event_notification(p_event);
2022 node = list_next (node);
2024 /* Todo. Need to initiate application settings query if this
2025 * is the last event registration.
2029 /***************************************************************************
2031 ** Function btif_rc_status_cmd_timeout_handler
2033 ** Description RC status command timeout handler (Runs in BTIF context).
2036 ***************************************************************************/
2037 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2040 btif_rc_timer_context_t *p_context;
2041 tAVRC_RESPONSE avrc_response = {0};
2042 tBTA_AV_META_MSG meta_msg;
2044 p_context = (btif_rc_timer_context_t *)data;
2045 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2046 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2048 switch (p_context->rc_status_cmd.pdu_id) {
2049 case AVRC_PDU_REGISTER_NOTIFICATION:
2050 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2053 case AVRC_PDU_GET_CAPABILITIES:
2054 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2055 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2058 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2059 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2060 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2063 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2064 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2065 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2068 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2069 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2070 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2073 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2074 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2075 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2078 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2079 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2080 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2083 case AVRC_PDU_GET_ELEMENT_ATTR:
2084 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2085 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2088 case AVRC_PDU_GET_PLAY_STATUS:
2089 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2090 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2093 release_transaction(p_context->rc_status_cmd.label);
2096 /***************************************************************************
2098 ** Function btif_rc_status_cmd_timer_timeout
2100 ** Description RC status command timeout callback.
2101 ** This is called from BTU context and switches to BTIF
2102 ** context to handle the timeout events
2105 ***************************************************************************/
2106 static void btif_rc_status_cmd_timer_timeout(void *data)
2108 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2110 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2111 (char *)p_data, sizeof(btif_rc_timer_context_t),
2115 /***************************************************************************
2117 ** Function btif_rc_control_cmd_timeout_handler
2119 ** Description RC control command timeout handler (Runs in BTIF context).
2122 ***************************************************************************/
2123 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2126 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2127 tAVRC_RESPONSE avrc_response = {0};
2128 tBTA_AV_META_MSG meta_msg;
2130 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2131 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2133 switch (p_context->rc_control_cmd.pdu_id) {
2134 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2135 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2136 handle_set_app_attr_val_response(&meta_msg,
2137 &avrc_response.set_app_val);
2140 release_transaction(p_context->rc_control_cmd.label);
2143 /***************************************************************************
2145 ** Function btif_rc_control_cmd_timer_timeout
2147 ** Description RC control command timeout callback.
2148 ** This is called from BTU context and switches to BTIF
2149 ** context to handle the timeout events
2152 ***************************************************************************/
2153 static void btif_rc_control_cmd_timer_timeout(void *data)
2155 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2157 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2158 (char *)p_data, sizeof(btif_rc_timer_context_t),
2162 /***************************************************************************
2164 ** Function btif_rc_play_status_timeout_handler
2166 ** Description RC play status timeout handler (Runs in BTIF context).
2169 ***************************************************************************/
2170 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2171 UNUSED_ATTR char *p_data)
2173 get_play_status_cmd();
2174 rc_start_play_status_timer();
2177 /***************************************************************************
2179 ** Function btif_rc_play_status_timer_timeout
2181 ** Description RC play status timeout callback.
2182 ** This is called from BTU context and switches to BTIF
2183 ** context to handle the timeout events
2186 ***************************************************************************/
2187 static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2189 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
2192 /***************************************************************************
2194 ** Function rc_start_play_status_timer
2196 ** Description Helper function to start the timer to fetch play status.
2199 ***************************************************************************/
2200 static void rc_start_play_status_timer(void)
2202 /* Start the Play status timer only if it is not started */
2203 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2204 if (btif_rc_cb.rc_play_status_timer == NULL) {
2205 btif_rc_cb.rc_play_status_timer =
2206 alarm_new("btif_rc.rc_play_status_timer");
2208 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2209 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2210 btif_rc_play_status_timer_timeout, NULL,
2211 btu_general_alarm_queue);
2215 /***************************************************************************
2217 ** Function rc_stop_play_status_timer
2219 ** Description Helper function to stop the play status timer.
2222 ***************************************************************************/
2223 void rc_stop_play_status_timer()
2225 if (btif_rc_cb.rc_play_status_timer != NULL)
2226 alarm_cancel(btif_rc_cb.rc_play_status_timer);
2229 /***************************************************************************
2231 ** Function register_for_event_notification
2233 ** Description Helper function registering notification events
2234 ** sets an interim response timeout to handle if the remote
2235 ** does not respond.
2238 ***************************************************************************/
2239 static void register_for_event_notification(btif_rc_supported_event_t *p_event)
2242 rc_transaction_t *p_transaction;
2244 status = get_transaction(&p_transaction);
2245 if (status == BT_STATUS_SUCCESS)
2247 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
2249 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2250 if (status != BT_STATUS_SUCCESS)
2252 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2253 __FUNCTION__, status);
2254 release_transaction (p_transaction->lbl);
2257 p_event->label = p_transaction->lbl;
2258 p_event->status = eREGISTERED;
2259 p_context->rc_status_cmd.label = p_transaction->lbl;
2260 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2262 alarm_free(p_transaction->txn_timer);
2263 p_transaction->txn_timer =
2264 alarm_new("btif_rc.status_command_txn_timer");
2265 alarm_set_on_queue(p_transaction->txn_timer,
2266 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2267 btif_rc_status_cmd_timer_timeout, p_context,
2268 btu_general_alarm_queue);
2272 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2273 __FUNCTION__, status);
2277 static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2279 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2280 p_context->rc_status_cmd.label = p_txn->lbl;
2281 p_context->rc_status_cmd.pdu_id = pdu_id;
2283 alarm_free(p_txn->txn_timer);
2284 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2285 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2286 btif_rc_status_cmd_timer_timeout, p_context,
2287 btu_general_alarm_queue);
2290 static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2292 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2293 p_context->rc_control_cmd.label = p_txn->lbl;
2294 p_context->rc_control_cmd.pdu_id = pdu_id;
2296 alarm_free(p_txn->txn_timer);
2297 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2298 alarm_set_on_queue(p_txn->txn_timer,
2299 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2300 btif_rc_control_cmd_timer_timeout, p_context,
2301 btu_general_alarm_queue);
2304 /***************************************************************************
2306 ** Function handle_get_capability_response
2308 ** Description Handles the get_cap_response to populate company id info
2309 ** and query the supported events.
2310 ** Initiates Notification registration for events supported
2313 ***************************************************************************/
2314 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2318 /* Todo: Do we need to retry on command timeout */
2319 if (p_rsp->status != AVRC_STS_NO_ERROR)
2321 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2322 __FUNCTION__, p_rsp->status);
2326 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2328 btif_rc_supported_event_t *p_event;
2330 /* Todo: Check if list can be active when we hit here */
2331 btif_rc_cb.rc_supported_event_list = list_new(osi_free);
2332 for (xx = 0; xx < p_rsp->count; xx++)
2334 /* Skip registering for Play position change notification */
2335 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2336 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2337 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2339 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
2340 p_event->event_id = p_rsp->param.event_id[xx];
2341 p_event->status = eNOT_REGISTERED;
2342 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2345 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2346 if (p_event != NULL)
2348 register_for_event_notification(p_event);
2351 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2353 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2354 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2355 for (xx = 0; xx < p_rsp->count; xx++)
2357 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2362 bool rc_is_track_id_valid (tAVRC_UID uid)
2364 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2366 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2376 /***************************************************************************
2378 ** Function handle_notification_response
2380 ** Description Main handler for notification responses to registered events
2381 ** 1. Register for unregistered event(in interim response path)
2382 ** 2. After registering for all supported events, start
2383 ** retrieving application settings and values
2384 ** 3. Reregister for events on getting changed response
2385 ** 4. Run play status timer for getting position when the
2386 ** status changes to playing
2387 ** 5. Get the Media details when the track change happens
2388 ** or track change interim response is received with
2390 ** 6. HAL callback for play status change and application
2394 ***************************************************************************/
2395 static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2397 bt_bdaddr_t rc_addr;
2398 UINT32 attr_list[] = {
2399 AVRC_MEDIA_ATTR_ID_TITLE,
2400 AVRC_MEDIA_ATTR_ID_ARTIST,
2401 AVRC_MEDIA_ATTR_ID_ALBUM,
2402 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2403 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2404 AVRC_MEDIA_ATTR_ID_GENRE,
2405 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2409 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2411 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2413 btif_rc_supported_event_t *p_event;
2416 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2417 switch (p_rsp->event_id)
2419 case AVRC_EVT_PLAY_STATUS_CHANGE:
2420 /* Start timer to get play status periodically
2421 * if the play state is playing.
2423 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2425 rc_start_play_status_timer();
2427 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2428 &rc_addr, p_rsp->param.play_status);
2431 case AVRC_EVT_TRACK_CHANGE:
2432 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2438 UINT8 *p_data = p_rsp->param.track;
2439 /* Update the UID for current track
2440 * Attributes will be fetched after the AVRCP procedure
2442 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2446 case AVRC_EVT_APP_SETTING_CHANGE:
2449 case AVRC_EVT_NOW_PLAYING_CHANGE:
2452 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2455 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2458 case AVRC_EVT_UIDS_CHANGE:
2461 case AVRC_EVT_TRACK_REACHED_END:
2462 case AVRC_EVT_TRACK_REACHED_START:
2463 case AVRC_EVT_PLAY_POS_CHANGED:
2464 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2465 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2467 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2471 list_foreach(btif_rc_cb.rc_supported_event_list,
2472 iterate_supported_event_list_for_interim_rsp,
2475 node = list_begin(btif_rc_cb.rc_supported_event_list);
2476 while (node != NULL)
2478 p_event = (btif_rc_supported_event_t *)list_node(node);
2479 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2481 register_for_event_notification(p_event);
2484 node = list_next (node);
2487 /* Registered for all events, we can request application settings */
2488 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2490 /* we need to do this only if remote TG supports
2491 * player application settings
2493 btif_rc_cb.rc_app_settings.query_started = TRUE;
2494 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2496 list_player_app_setting_attrib_cmd();
2500 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2501 rc_ctrl_procedure_complete();
2505 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2507 btif_rc_supported_event_t *p_event;
2510 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2513 node = list_begin(btif_rc_cb.rc_supported_event_list);
2514 while (node != NULL)
2516 p_event = (btif_rc_supported_event_t *)list_node(node);
2517 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2519 p_event->status = eNOT_REGISTERED;
2520 register_for_event_notification(p_event);
2523 node = list_next (node);
2526 switch (p_rsp->event_id)
2528 case AVRC_EVT_PLAY_STATUS_CHANGE:
2529 /* Start timer to get play status periodically
2530 * if the play state is playing.
2532 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2534 rc_start_play_status_timer();
2538 rc_stop_play_status_timer();
2540 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2541 &rc_addr, p_rsp->param.play_status);
2544 case AVRC_EVT_TRACK_CHANGE:
2545 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2549 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2552 case AVRC_EVT_APP_SETTING_CHANGE:
2554 btrc_player_settings_t app_settings;
2557 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2558 for (xx = 0; xx < app_settings.num_attr; xx++)
2560 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2561 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2563 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2564 &rc_addr, &app_settings);
2568 case AVRC_EVT_NOW_PLAYING_CHANGE:
2571 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2574 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2577 case AVRC_EVT_UIDS_CHANGE:
2580 case AVRC_EVT_TRACK_REACHED_END:
2581 case AVRC_EVT_TRACK_REACHED_START:
2582 case AVRC_EVT_PLAY_POS_CHANGED:
2583 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2584 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2586 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2587 __FUNCTION__, p_rsp->event_id);
2593 /***************************************************************************
2595 ** Function handle_app_attr_response
2597 ** Description handles the the application attributes response and
2598 ** initiates procedure to fetch the attribute values
2601 ***************************************************************************/
2602 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2606 if (p_rsp->status != AVRC_STS_NO_ERROR)
2608 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2609 __FUNCTION__, p_rsp->status);
2610 rc_ctrl_procedure_complete();
2614 for (xx = 0; xx < p_rsp->num_attr; xx++)
2618 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2620 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2621 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2622 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2626 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2627 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2628 btif_rc_cb.rc_app_settings.num_attrs++;
2631 btif_rc_cb.rc_app_settings.attr_index = 0;
2632 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2633 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2634 if (p_rsp->num_attr)
2636 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2640 BTIF_TRACE_ERROR("%s No Player application settings found",
2645 /***************************************************************************
2647 ** Function handle_app_val_response
2649 ** Description handles the the attributes value response and if extended
2650 ** menu is available, it initiates query for the attribute
2651 ** text. If not, it initiates procedure to get the current
2652 ** attribute values and calls the HAL callback for provding
2653 ** application settings information.
2656 ***************************************************************************/
2657 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2659 UINT8 xx, attr_index;
2660 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2661 btif_rc_player_app_settings_t *p_app_settings;
2662 bt_bdaddr_t rc_addr;
2664 /* Todo: Do we need to retry on command timeout */
2665 if (p_rsp->status != AVRC_STS_NO_ERROR)
2667 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2668 __FUNCTION__, p_rsp->status);
2672 p_app_settings = &btif_rc_cb.rc_app_settings;
2673 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2675 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2677 attr_index = p_app_settings->attr_index;
2678 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2679 for (xx = 0; xx < p_rsp->num_val; xx++)
2681 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2684 p_app_settings->attr_index++;
2685 if (attr_index < p_app_settings->num_attrs)
2687 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2689 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2692 p_app_settings->ext_attr_index = 0;
2693 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2697 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2699 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2701 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2702 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2703 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2706 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2708 attr_index = p_app_settings->ext_attr_index;
2709 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2710 for (xx = 0; xx < p_rsp->num_val; xx++)
2712 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2715 p_app_settings->ext_attr_index++;
2716 if (attr_index < p_app_settings->num_ext_attrs)
2718 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2722 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2725 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2727 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2729 get_player_app_setting_attr_text_cmd(attr, xx);
2734 /***************************************************************************
2736 ** Function handle_app_cur_val_response
2738 ** Description handles the the get attributes value response.
2742 ***************************************************************************/
2743 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2745 btrc_player_settings_t app_settings;
2746 bt_bdaddr_t rc_addr;
2749 /* Todo: Do we need to retry on command timeout */
2750 if (p_rsp->status != AVRC_STS_NO_ERROR)
2752 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2753 __FUNCTION__, p_rsp->status);
2757 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2759 app_settings.num_attr = p_rsp->num_val;
2760 for (xx = 0; xx < app_settings.num_attr; xx++)
2762 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2763 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2765 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2766 &rc_addr, &app_settings);
2767 /* Application settings are fetched only once for initial values
2768 * initiate anything that follows after RC procedure.
2769 * Defer it if browsing is supported till players query
2771 rc_ctrl_procedure_complete ();
2772 osi_free_and_reset((void **)&p_rsp->p_vals);
2775 /***************************************************************************
2777 ** Function handle_app_attr_txt_response
2779 ** Description handles the the get attributes text response, if fails
2780 ** calls HAL callback with just normal settings and initiates
2781 ** query for current settings else initiates query for value text
2784 ***************************************************************************/
2785 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2788 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2789 btif_rc_player_app_settings_t *p_app_settings;
2790 bt_bdaddr_t rc_addr;
2792 p_app_settings = &btif_rc_cb.rc_app_settings;
2793 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2795 /* Todo: Do we need to retry on command timeout */
2796 if (p_rsp->status != AVRC_STS_NO_ERROR)
2798 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2800 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2801 __FUNCTION__, p_rsp->status);
2802 /* Not able to fetch Text for extended Menu, skip the process
2803 * and cleanup used memory. Proceed to get the current settings
2804 * for standard attributes.
2806 p_app_settings->num_ext_attrs = 0;
2807 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2808 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2809 p_app_settings->ext_attr_index = 0;
2811 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2813 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2815 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2816 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2818 get_player_app_setting_cmd (xx, attrs);
2822 for (xx = 0; xx < p_rsp->num_attr; xx++)
2825 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2827 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2829 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2830 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2831 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2837 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2839 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2841 get_player_app_setting_value_text_cmd(vals, xx);
2845 /***************************************************************************
2847 ** Function handle_app_attr_val_txt_response
2849 ** Description handles the the get attributes value text response, if fails
2850 ** calls HAL callback with just normal settings and initiates
2851 ** query for current settings
2854 ***************************************************************************/
2855 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2857 UINT8 xx, attr_index;
2858 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2859 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2860 btif_rc_player_app_settings_t *p_app_settings;
2861 bt_bdaddr_t rc_addr;
2863 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2864 p_app_settings = &btif_rc_cb.rc_app_settings;
2866 /* Todo: Do we need to retry on command timeout */
2867 if (p_rsp->status != AVRC_STS_NO_ERROR)
2869 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2871 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2872 __FUNCTION__, p_rsp->status);
2874 /* Not able to fetch Text for extended Menu, skip the process
2875 * and cleanup used memory. Proceed to get the current settings
2876 * for standard attributes.
2878 p_app_settings->num_ext_attrs = 0;
2879 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2882 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2884 for (x = 0; x < p_ext_attr->num_val; x++)
2885 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2886 p_ext_attr->num_val = 0;
2887 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2889 p_app_settings->ext_attr_index = 0;
2891 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2893 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2895 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2896 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2898 get_player_app_setting_cmd (xx, attrs);
2902 for (xx = 0; xx < p_rsp->num_attr; xx++)
2905 btrc_player_app_ext_attr_t *p_ext_attr;
2906 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2907 for (x = 0; x < p_rsp->num_attr; x++)
2909 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2911 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2912 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2913 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2918 p_app_settings->ext_val_index++;
2920 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2922 attr_index = p_app_settings->ext_val_index;
2923 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2925 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2927 get_player_app_setting_value_text_cmd(vals, xx);
2933 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2935 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2937 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2939 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2941 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2942 p_app_settings->num_attrs, p_app_settings->attrs,
2943 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
2944 get_player_app_setting_cmd (xx + x, attrs);
2946 /* Free the application settings information after sending to
2949 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2952 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2954 for (x = 0; x < p_ext_attr->num_val; x++)
2955 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2956 p_ext_attr->num_val = 0;
2957 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2959 p_app_settings->num_attrs = 0;
2963 /***************************************************************************
2965 ** Function handle_set_app_attr_val_response
2967 ** Description handles the the set attributes value response, if fails
2968 ** calls HAL callback to indicate the failure
2971 ***************************************************************************/
2972 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2974 uint8_t accepted = 0;
2975 bt_bdaddr_t rc_addr;
2977 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2979 /* For timeout pmeta_msg will be NULL, else we need to
2980 * check if this is accepted by TG
2982 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2986 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2989 /***************************************************************************
2991 ** Function handle_get_elem_attr_response
2993 ** Description handles the the element attributes response, calls
2994 ** HAL callback to update track change information.
2997 ***************************************************************************/
2998 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg,
2999 tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
3001 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3002 bt_bdaddr_t rc_addr;
3003 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
3004 btrc_element_attr_val_t *p_attr =
3005 (btrc_element_attr_val_t *)osi_calloc(buf_size);
3007 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3009 for (int i = 0; i < p_rsp->num_attr; i++) {
3010 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3011 /* Todo. Legth limit check to include null */
3012 if (p_rsp->p_attrs[i].name.str_len &&
3013 p_rsp->p_attrs[i].name.p_str) {
3014 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3015 p_rsp->p_attrs[i].name.str_len);
3016 osi_free_and_reset((void **)&p_rsp->p_attrs[i].name.p_str);
3019 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3020 &rc_addr, p_rsp->num_attr, p_attr);
3022 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3023 /* Retry for timeout case, this covers error handling
3024 * for continuation failure also.
3026 UINT32 attr_list[] = {
3027 AVRC_MEDIA_ATTR_ID_TITLE,
3028 AVRC_MEDIA_ATTR_ID_ARTIST,
3029 AVRC_MEDIA_ATTR_ID_ALBUM,
3030 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3031 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3032 AVRC_MEDIA_ATTR_ID_GENRE,
3033 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3035 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
3037 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
3038 __func__, p_rsp->status);
3042 /***************************************************************************
3044 ** Function handle_get_playstatus_response
3046 ** Description handles the the play status response, calls
3047 ** HAL callback to update play position.
3050 ***************************************************************************/
3051 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3053 bt_bdaddr_t rc_addr;
3055 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3057 if (p_rsp->status == AVRC_STS_NO_ERROR)
3059 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3060 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3064 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3065 __FUNCTION__, p_rsp->status);
3069 /***************************************************************************
3071 ** Function clear_cmd_timeout
3073 ** Description helper function to stop the command timeout timer
3076 ***************************************************************************/
3077 static void clear_cmd_timeout (UINT8 label)
3079 rc_transaction_t *p_txn;
3081 p_txn = get_transaction_by_lbl (label);
3084 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3088 if (p_txn->txn_timer != NULL)
3089 alarm_cancel(p_txn->txn_timer);
3092 /***************************************************************************
3094 ** Function handle_avk_rc_metamsg_rsp
3096 ** Description Handle RC metamessage response
3100 ***************************************************************************/
3101 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3103 tAVRC_RESPONSE avrc_response = {0};
3104 UINT8 scratch_buf[512] = {0};// this variable is unused
3108 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3109 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3111 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3112 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3113 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3115 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3116 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3117 __FUNCTION__, status, avrc_response.pdu,
3118 pmeta_msg->p_msg->vendor.hdr.ctype);
3120 switch (avrc_response.pdu)
3122 case AVRC_PDU_REGISTER_NOTIFICATION:
3123 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3124 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3126 /* Don't free the transaction Id */
3127 clear_cmd_timeout (pmeta_msg->label);
3132 case AVRC_PDU_GET_CAPABILITIES:
3133 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3136 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3137 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3140 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3141 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3144 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3145 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3148 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3149 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3152 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3153 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3156 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3157 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3160 case AVRC_PDU_GET_ELEMENT_ATTR:
3161 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3164 case AVRC_PDU_GET_PLAY_STATUS:
3165 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3168 release_transaction(pmeta_msg->label);
3172 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3173 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3178 /***************************************************************************
3180 ** Function handle_avk_rc_metamsg_cmd
3182 ** Description Handle RC metamessage response
3186 ***************************************************************************/
3187 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3189 tAVRC_COMMAND avrc_cmd = {0};
3190 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3191 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3192 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3193 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3194 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3196 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3197 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3198 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3200 if (status != AVRC_STS_NO_ERROR)
3203 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3204 __FUNCTION__, status);
3205 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3209 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3211 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3212 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3213 __FUNCTION__, dump_rc_notification_event_id(event_id));
3215 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3217 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3219 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3224 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3225 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3231 /***************************************************************************
3235 ** Description Closes the AVRC interface
3239 ***************************************************************************/
3240 static void cleanup()
3242 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3244 if (bt_rc_callbacks)
3246 bt_rc_callbacks = NULL;
3248 alarm_free(btif_rc_cb.rc_play_status_timer);
3249 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3251 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3254 /***************************************************************************
3256 ** Function cleanup_ctrl
3258 ** Description Closes the AVRC Controller interface
3262 ***************************************************************************/
3263 static void cleanup_ctrl()
3265 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3267 if (bt_rc_ctrl_callbacks)
3269 bt_rc_ctrl_callbacks = NULL;
3271 alarm_free(btif_rc_cb.rc_play_status_timer);
3272 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3274 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3277 /***************************************************************************
3279 ** Function getcapabilities_cmd
3281 ** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3285 ***************************************************************************/
3286 static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3288 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3289 rc_transaction_t *p_transaction = NULL;
3290 #if (AVRC_CTLR_INCLUDED == TRUE)
3291 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3293 bt_status_t tran_status=get_transaction(&p_transaction);
3294 if (BT_STATUS_SUCCESS != tran_status)
3295 return BT_STATUS_FAIL;
3297 tAVRC_COMMAND avrc_cmd = {0};
3298 BT_HDR *p_msg = NULL;
3299 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3300 avrc_cmd.get_caps.capability_id = cap_id;
3301 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3302 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3303 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3304 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3306 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3307 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3308 __FUNCTION__,p_transaction->lbl);
3309 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3310 data_start, p_msg->len);
3311 status = BT_STATUS_SUCCESS;
3312 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3316 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3317 __FUNCTION__, status);
3321 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3326 /***************************************************************************
3328 ** Function list_player_app_setting_attrib_cmd
3330 ** Description Get supported List Player Attributes
3334 ***************************************************************************/
3335 static bt_status_t list_player_app_setting_attrib_cmd(void)
3337 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3338 rc_transaction_t *p_transaction = NULL;
3339 #if (AVRC_CTLR_INCLUDED == TRUE)
3340 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3342 bt_status_t tran_status=get_transaction(&p_transaction);
3343 if (BT_STATUS_SUCCESS != tran_status)
3344 return BT_STATUS_FAIL;
3346 tAVRC_COMMAND avrc_cmd = {0};
3347 BT_HDR *p_msg = NULL;
3348 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3349 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3350 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3351 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3352 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3354 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3355 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3356 __FUNCTION__,p_transaction->lbl);
3357 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3358 data_start, p_msg->len);
3359 status = BT_STATUS_SUCCESS;
3360 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3365 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3366 __FUNCTION__, status);
3370 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3375 /***************************************************************************
3377 ** Function list_player_app_setting_value_cmd
3379 ** Description Get values of supported Player Attributes
3383 ***************************************************************************/
3384 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3386 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3387 rc_transaction_t *p_transaction=NULL;
3388 #if (AVRC_CTLR_INCLUDED == TRUE)
3389 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3391 bt_status_t tran_status=get_transaction(&p_transaction);
3392 if (BT_STATUS_SUCCESS != tran_status)
3393 return BT_STATUS_FAIL;
3395 tAVRC_COMMAND avrc_cmd = {0};
3396 BT_HDR *p_msg = NULL;
3397 avrc_cmd.list_app_values.attr_id = attrib_id;
3398 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3399 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3400 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3401 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3402 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3404 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3405 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3406 __FUNCTION__,p_transaction->lbl);
3407 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3408 data_start, p_msg->len);
3409 status = BT_STATUS_SUCCESS;
3410 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3414 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3418 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3423 /***************************************************************************
3425 ** Function get_player_app_setting_cmd
3427 ** Description Get current values of Player Attributes
3431 ***************************************************************************/
3432 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3434 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3435 rc_transaction_t *p_transaction = NULL;
3437 #if (AVRC_CTLR_INCLUDED == TRUE)
3438 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3440 bt_status_t tran_status=get_transaction(&p_transaction);
3441 if (BT_STATUS_SUCCESS != tran_status)
3442 return BT_STATUS_FAIL;
3444 tAVRC_COMMAND avrc_cmd = {0};
3445 BT_HDR *p_msg = NULL;
3446 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3447 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3448 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3449 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3451 for (count = 0; count < num_attrib; count++)
3453 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3455 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3456 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3458 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3459 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3460 __FUNCTION__,p_transaction->lbl);
3461 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3462 data_start, p_msg->len);
3463 status = BT_STATUS_SUCCESS;
3464 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3468 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3469 __FUNCTION__, status);
3473 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3478 /***************************************************************************
3480 ** Function change_player_app_setting
3482 ** Description Set current values of Player Attributes
3486 ***************************************************************************/
3487 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)
3489 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3490 rc_transaction_t *p_transaction = NULL;
3492 #if (AVRC_CTLR_INCLUDED == TRUE)
3493 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3495 bt_status_t tran_status=get_transaction(&p_transaction);
3496 if (BT_STATUS_SUCCESS != tran_status)
3497 return BT_STATUS_FAIL;
3499 tAVRC_COMMAND avrc_cmd = {0};
3500 BT_HDR *p_msg = NULL;
3501 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3502 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3503 avrc_cmd.set_app_val.num_val = num_attrib;
3504 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3505 avrc_cmd.set_app_val.p_vals =
3506 (tAVRC_APP_SETTING *)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
3507 for (count = 0; count < num_attrib; count++)
3509 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3510 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3512 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3513 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3515 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3516 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3517 __FUNCTION__,p_transaction->lbl);
3518 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3519 data_start, p_msg->len);
3520 status = BT_STATUS_SUCCESS;
3521 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3525 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3526 __FUNCTION__, status);
3529 osi_free_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
3531 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3536 /***************************************************************************
3538 ** Function get_player_app_setting_attr_text_cmd
3540 ** Description Get text description for app attribute
3544 ***************************************************************************/
3545 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3547 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3548 rc_transaction_t *p_transaction = NULL;
3550 #if (AVRC_CTLR_INCLUDED == TRUE)
3551 tAVRC_COMMAND avrc_cmd = {0};
3552 BT_HDR *p_msg = NULL;
3553 bt_status_t tran_status;
3556 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3558 tran_status = get_transaction(&p_transaction);
3559 if (BT_STATUS_SUCCESS != tran_status)
3560 return BT_STATUS_FAIL;
3562 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3563 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3564 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3566 for (count = 0; count < num_attrs; count++)
3568 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3570 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3571 if (status == AVRC_STS_NO_ERROR)
3573 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3574 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3575 __FUNCTION__, p_transaction->lbl);
3576 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3577 AVRC_CMD_STATUS, data_start, p_msg->len);
3579 status = BT_STATUS_SUCCESS;
3580 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3584 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3588 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3593 /***************************************************************************
3595 ** Function get_player_app_setting_val_text_cmd
3597 ** Description Get text description for app attribute values
3601 ***************************************************************************/
3602 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3604 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3605 rc_transaction_t *p_transaction = NULL;
3607 #if (AVRC_CTLR_INCLUDED == TRUE)
3608 tAVRC_COMMAND avrc_cmd = {0};
3609 BT_HDR *p_msg = NULL;
3610 bt_status_t tran_status;
3613 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3615 tran_status = get_transaction(&p_transaction);
3616 if (BT_STATUS_SUCCESS != tran_status)
3617 return BT_STATUS_FAIL;
3619 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3620 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3621 avrc_cmd.get_app_val_txt.num_val = num_vals;
3623 for (count = 0; count < num_vals; count++)
3625 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3627 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3628 if (status == AVRC_STS_NO_ERROR)
3630 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3631 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3632 __FUNCTION__, p_transaction->lbl);
3635 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3636 AVRC_CMD_STATUS, data_start, p_msg->len);
3637 status = BT_STATUS_SUCCESS;
3638 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3643 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3644 __FUNCTION__, status);
3648 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3653 /***************************************************************************
3655 ** Function register_notification_cmd
3657 ** Description Send Command to register for a Notification ID
3661 ***************************************************************************/
3662 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3665 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3666 #if (AVRC_CTLR_INCLUDED == TRUE)
3667 tAVRC_COMMAND avrc_cmd = {0};
3668 BT_HDR *p_msg = NULL;
3672 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3674 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3675 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3676 avrc_cmd.reg_notif.event_id = event_id;
3677 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3678 avrc_cmd.reg_notif.param = event_value;
3679 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3680 if (status == AVRC_STS_NO_ERROR)
3682 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3683 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3684 __FUNCTION__, label);
3687 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3688 data_start, p_msg->len);
3689 status = BT_STATUS_SUCCESS;
3694 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3695 __FUNCTION__, status);
3699 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3704 /***************************************************************************
3706 ** Function get_element_attribute_cmd
3708 ** Description Get Element Attribute for attributeIds
3712 ***************************************************************************/
3713 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3715 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3716 rc_transaction_t *p_transaction=NULL;
3718 #if (AVRC_CTLR_INCLUDED == TRUE)
3719 tAVRC_COMMAND avrc_cmd = {0};
3720 BT_HDR *p_msg = NULL;
3721 bt_status_t tran_status;
3724 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3725 __FUNCTION__, num_attribute, p_attr_ids[0]);
3727 tran_status = get_transaction(&p_transaction);
3728 if (BT_STATUS_SUCCESS != tran_status)
3729 return BT_STATUS_FAIL;
3731 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3732 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3733 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3734 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3735 for (count = 0; count < num_attribute; count++)
3737 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3740 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3741 if (status == AVRC_STS_NO_ERROR)
3743 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3744 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3745 __FUNCTION__, p_transaction->lbl);
3748 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3749 AVRC_CMD_STATUS, data_start, p_msg->len);
3750 status = BT_STATUS_SUCCESS;
3751 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3757 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3758 __FUNCTION__, status);
3762 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3767 /***************************************************************************
3769 ** Function get_play_status_cmd
3771 ** Description Get Element Attribute for attributeIds
3775 ***************************************************************************/
3776 static bt_status_t get_play_status_cmd(void)
3778 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3779 rc_transaction_t *p_transaction = NULL;
3780 #if (AVRC_CTLR_INCLUDED == TRUE)
3781 tAVRC_COMMAND avrc_cmd = {0};
3782 BT_HDR *p_msg = NULL;
3783 bt_status_t tran_status;
3786 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3787 tran_status = get_transaction(&p_transaction);
3788 if (BT_STATUS_SUCCESS != tran_status)
3789 return BT_STATUS_FAIL;
3791 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3792 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3793 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3794 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3795 if (status == AVRC_STS_NO_ERROR)
3797 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3798 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3799 __FUNCTION__, p_transaction->lbl);
3802 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3803 AVRC_CMD_STATUS, data_start, p_msg->len);
3804 status = BT_STATUS_SUCCESS;
3805 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3810 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3811 __FUNCTION__, status);
3815 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3821 /***************************************************************************
3823 ** Function set_volume_rsp
3825 ** Description Rsp for SetAbsoluteVolume Command
3829 ***************************************************************************/
3830 static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3832 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3833 #if (AVRC_CTLR_INCLUDED == TRUE)
3834 tAVRC_RESPONSE avrc_rsp;
3835 BT_HDR *p_msg = NULL;
3838 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3840 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3841 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3842 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3843 avrc_rsp.volume.volume = abs_vol;
3844 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3845 if (status == AVRC_STS_NO_ERROR)
3847 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3848 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3849 __FUNCTION__, btif_rc_cb.rc_vol_label);
3852 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3853 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3854 status = BT_STATUS_SUCCESS;
3859 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3860 __FUNCTION__, status);
3864 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3869 /***************************************************************************
3871 ** Function send_register_abs_vol_rsp
3873 ** Description Rsp for Notification of Absolute Volume
3877 ***************************************************************************/
3878 static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3879 uint8_t abs_vol, uint8_t label)
3881 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3882 tAVRC_RESPONSE avrc_rsp;
3883 BT_HDR *p_msg = NULL;
3884 #if (AVRC_CTLR_INCLUDED == TRUE)
3885 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
3888 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3889 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3890 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3891 avrc_rsp.reg_notif.param.volume = abs_vol;
3892 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
3894 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3895 if (status == AVRC_STS_NO_ERROR) {
3896 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3898 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3899 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3900 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3901 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3902 data_start, p_msg->len, 0);
3903 status = BT_STATUS_SUCCESS;
3905 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3911 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
3916 /***************************************************************************
3918 ** Function send_groupnavigation_cmd
3920 ** Description Send Pass-Through command
3924 ***************************************************************************/
3925 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3928 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3929 #if (AVRC_CTLR_INCLUDED == TRUE)
3930 rc_transaction_t *p_transaction=NULL;
3931 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3932 key_code, key_state);
3934 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3936 bt_status_t tran_status = get_transaction(&p_transaction);
3937 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
3938 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3939 UINT8* start = buffer;
3940 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3942 UINT8_TO_BE_STREAM(start, key_code);
3943 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3945 (tBTA_AV_STATE)key_state, buffer,
3946 AVRC_PASS_THRU_GROUP_LEN);
3947 status = BT_STATUS_SUCCESS;
3948 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3953 status = BT_STATUS_FAIL;
3954 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3959 status = BT_STATUS_FAIL;
3960 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3963 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3968 /***************************************************************************
3970 ** Function send_passthrough_cmd
3972 ** Description Send Pass-Through command
3976 ***************************************************************************/
3977 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3979 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3980 #if (AVRC_CTLR_INCLUDED == TRUE)
3982 rc_transaction_t *p_transaction=NULL;
3983 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3984 key_code, key_state);
3985 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3987 bt_status_t tran_status = get_transaction(&p_transaction);
3988 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
3990 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3991 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
3992 status = BT_STATUS_SUCCESS;
3993 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
3997 status = BT_STATUS_FAIL;
3998 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
4003 status = BT_STATUS_FAIL;
4004 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
4007 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
4012 static const btrc_interface_t bt_rc_interface = {
4013 sizeof(bt_rc_interface),
4015 get_play_status_rsp,
4016 NULL, /* list_player_app_attr_rsp */
4017 NULL, /* list_player_app_value_rsp */
4018 NULL, /* get_player_app_value_rsp */
4019 NULL, /* get_player_app_attr_text_rsp */
4020 NULL, /* get_player_app_value_text_rsp */
4021 get_element_attr_rsp,
4022 NULL, /* set_player_app_value_rsp */
4023 register_notification_rsp,
4028 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4029 sizeof(bt_rc_ctrl_interface),
4031 send_passthrough_cmd,
4032 send_groupnavigation_cmd,
4033 change_player_app_setting,
4035 volume_change_notification_rsp,
4039 /*******************************************************************************
4041 ** Function btif_rc_get_interface
4043 ** Description Get the AVRCP Target callback interface
4045 ** Returns btav_interface_t
4047 *******************************************************************************/
4048 const btrc_interface_t *btif_rc_get_interface(void)
4050 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4051 return &bt_rc_interface;
4054 /*******************************************************************************
4056 ** Function btif_rc_ctrl_get_interface
4058 ** Description Get the AVRCP Controller callback interface
4060 ** Returns btav_interface_t
4062 *******************************************************************************/
4063 const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4065 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4066 return &bt_rc_ctrl_interface;
4069 /*******************************************************************************
4070 ** Function initialize_transaction
4072 ** Description Initializes fields of the transaction structure
4075 *******************************************************************************/
4076 static void initialize_transaction(int lbl)
4078 pthread_mutex_lock(&device.lbllock);
4079 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4080 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4081 clear_cmd_timeout(lbl);
4083 device.transaction[lbl].lbl = lbl;
4084 device.transaction[lbl].in_use=FALSE;
4085 device.transaction[lbl].handle=0;
4087 pthread_mutex_unlock(&device.lbllock);
4090 /*******************************************************************************
4091 ** Function lbl_init
4093 ** Description Initializes label structures and mutexes.
4096 *******************************************************************************/
4099 memset(&device,0,sizeof(rc_device_t));
4100 pthread_mutexattr_t attr;
4101 pthread_mutexattr_init(&attr);
4102 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4103 pthread_mutex_init(&(device.lbllock), &attr);
4104 pthread_mutexattr_destroy(&attr);
4105 init_all_transactions();
4108 /*******************************************************************************
4110 ** Function init_all_transactions
4112 ** Description Initializes all transactions
4115 *******************************************************************************/
4116 void init_all_transactions()
4119 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4121 initialize_transaction(txn_indx);
4125 /*******************************************************************************
4127 ** Function get_transaction_by_lbl
4129 ** Description Will return a transaction based on the label. If not inuse
4130 ** will return an error.
4132 ** Returns bt_status_t
4133 *******************************************************************************/
4134 rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4136 rc_transaction_t *transaction = NULL;
4137 pthread_mutex_lock(&device.lbllock);
4139 /* Determine if this is a valid label */
4140 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4142 if (FALSE==device.transaction[lbl].in_use)
4148 transaction = &(device.transaction[lbl]);
4149 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
4153 pthread_mutex_unlock(&device.lbllock);
4157 /*******************************************************************************
4159 ** Function get_transaction
4161 ** Description Obtains the transaction details.
4163 ** Returns bt_status_t
4164 *******************************************************************************/
4166 bt_status_t get_transaction(rc_transaction_t **ptransaction)
4168 bt_status_t result = BT_STATUS_NOMEM;
4170 pthread_mutex_lock(&device.lbllock);
4172 // Check for unused transactions
4173 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4175 if (FALSE==device.transaction[i].in_use)
4177 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
4178 device.transaction[i].in_use = TRUE;
4179 *ptransaction = &(device.transaction[i]);
4180 result = BT_STATUS_SUCCESS;
4185 pthread_mutex_unlock(&device.lbllock);
4189 /*******************************************************************************
4191 ** Function release_transaction
4193 ** Description Will release a transaction for reuse
4195 ** Returns bt_status_t
4196 *******************************************************************************/
4197 void release_transaction(UINT8 lbl)
4199 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4201 /* If the transaction is in use... */
4202 if (transaction != NULL)
4204 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
4205 initialize_transaction(lbl);
4209 /*******************************************************************************
4211 ** Function lbl_destroy
4213 ** Description Cleanup of the mutex
4216 *******************************************************************************/
4219 pthread_mutex_destroy(&(device.lbllock));
4222 /*******************************************************************************
4223 ** Function sleep_ms
4225 ** Description Sleep the calling thread unconditionally for
4226 ** |timeout_ms| milliseconds.
4229 *******************************************************************************/
4230 static void sleep_ms(period_ms_t timeout_ms) {
4231 struct timespec delay;
4232 delay.tv_sec = timeout_ms / 1000;
4233 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4237 err = nanosleep(&delay, &delay);
4238 } while (err == -1 && errno == EINTR);
4241 static bool absolute_volume_disabled() {
4242 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
4243 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
4244 if (strncmp(volume_disabled, "true", 4) == 0) {
4245 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);