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>
38 * TODO(eisenbach): cutils/properties.h is only being used to pull-in runtime
39 * settings on Android. Remove this conditional include once we have a generic
40 * way to obtain system properties.
42 #if !defined(OS_GENERIC)
43 #include <cutils/properties.h>
44 #endif /* !defined(OS_GENERIC) */
46 #include "avrc_defs.h"
48 #include "bta_av_api.h"
50 #include "btif_common.h"
51 #include "btif_util.h"
52 #include "bt_common.h"
53 #include "device/include/interop.h"
55 #include "osi/include/list.h"
57 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
58 /*****************************************************************************
60 ******************************************************************************/
62 /* cod value for Headsets */
63 #define COD_AV_HEADSETS 0x0404
64 /* for AVRC 1.4 need to change this */
65 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
67 #define IDX_GET_PLAY_STATUS_RSP 0
68 #define IDX_LIST_APP_ATTR_RSP 1
69 #define IDX_LIST_APP_VALUE_RSP 2
70 #define IDX_GET_CURR_APP_VAL_RSP 3
71 #define IDX_SET_APP_VAL_RSP 4
72 #define IDX_GET_APP_ATTR_TXT_RSP 5
73 #define IDX_GET_APP_VAL_TXT_RSP 6
74 #define IDX_GET_ELEMENT_ATTR_RSP 7
75 #define MAX_VOLUME 128
77 #define MAX_TRANSACTIONS_PER_SESSION 16
78 #define MAX_CMD_QUEUE_LEN 8
79 #define PLAY_STATUS_PLAYING 1
81 #define CHECK_RC_CONNECTED \
82 BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
83 if (btif_rc_cb.rc_connected == FALSE) \
85 BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
86 return BT_STATUS_NOT_READY; \
89 #define FILL_PDU_QUEUE(index, ctype, label, pending) \
91 btif_rc_cb.rc_pdu_info[index].ctype = ctype; \
92 btif_rc_cb.rc_pdu_info[index].label = label; \
93 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
96 #define SEND_METAMSG_RSP(index, avrc_rsp) \
98 if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE) \
100 BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
101 return BT_STATUS_UNHANDLED; \
103 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label, \
104 btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp); \
105 btif_rc_cb.rc_pdu_info[index].ctype = 0; \
106 btif_rc_cb.rc_pdu_info[index].label = 0; \
107 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE; \
110 /*****************************************************************************
111 ** Local type definitions
112 ******************************************************************************/
116 } btif_rc_reg_notifications_t;
122 BOOLEAN is_rsp_pending;
123 } btif_rc_cmd_ctxt_t;
125 /* 2 second timeout to get interim response */
126 #define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000)
127 #define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000)
128 #define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000)
136 } btif_rc_nfn_reg_status_t;
141 btif_rc_nfn_reg_status_t status;
142 } btif_rc_supported_event_t;
144 #define BTIF_RC_STS_TIMEOUT 0xFE
148 } btif_rc_status_cmd_timer_t;
153 } btif_rc_control_cmd_timer_t;
157 btif_rc_status_cmd_timer_t rc_status_cmd;
158 btif_rc_control_cmd_timer_t rc_control_cmd;
160 } btif_rc_timer_context_t;
163 BOOLEAN query_started;
168 UINT8 ext_attr_index;
170 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE];
171 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE];
172 } btif_rc_player_app_settings_t;
174 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single struct */
176 BOOLEAN rc_connected;
178 tBTA_AV_FEAT rc_features;
180 UINT16 rc_pending_play;
181 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
182 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
183 unsigned int rc_volume;
184 uint8_t rc_vol_label;
185 list_t *rc_supported_event_list;
186 btif_rc_player_app_settings_t rc_app_settings;
187 alarm_t *rc_play_status_timer;
188 BOOLEAN rc_features_processed;
189 UINT64 rc_playing_uid;
190 BOOLEAN rc_procedure_complete;
197 btif_rc_timer_context_t txn_timer_context;
203 pthread_mutex_t lbllock;
204 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
209 #define MAX_UINPUT_PATHS 3
210 static const char* uinput_dev_path[] =
211 {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
212 static int uinput_fd = -1;
214 static int send_event (int fd, uint16_t type, uint16_t code, int32_t value);
215 static void send_key (int fd, uint16_t key, int pressed);
216 static int uinput_driver_check();
217 static int uinput_create(char *name);
218 static int init_uinput (void);
219 static void close_uinput (void);
220 static void sleep_ms(period_ms_t timeout_ms);
222 static const struct {
226 uint8_t release_quirk;
228 { "PLAY", AVRC_ID_PLAY, KEY_PLAYCD, 1 },
229 { "STOP", AVRC_ID_STOP, KEY_STOPCD, 0 },
230 { "PAUSE", AVRC_ID_PAUSE, KEY_PAUSECD, 1 },
231 { "FORWARD", AVRC_ID_FORWARD, KEY_NEXTSONG, 0 },
232 { "BACKWARD", AVRC_ID_BACKWARD, KEY_PREVIOUSSONG, 0 },
233 { "REWIND", AVRC_ID_REWIND, KEY_REWIND, 0 },
234 { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FAST_FORWARD, 0 },
238 static void send_reject_response (UINT8 rc_handle, UINT8 label,
239 UINT8 pdu, UINT8 status);
240 static UINT8 opcode_from_pdu(UINT8 pdu);
241 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
242 tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
243 static void register_volumechange(UINT8 label);
244 static void lbl_init();
245 static void lbl_destroy();
246 static void init_all_transactions();
247 static bt_status_t get_transaction(rc_transaction_t **ptransaction);
248 static void release_transaction(UINT8 label);
249 static rc_transaction_t* get_transaction_by_lbl(UINT8 label);
250 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
251 #if (AVRC_CTLR_INCLUDED == TRUE)
252 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg);
253 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
254 static void btif_rc_ctrl_upstreams_rsp_cmd(
255 UINT8 event, tAVRC_COMMAND *pavrc_cmd, UINT8 label);
256 static void btif_rc_ctrl_upstreams_rsp_evt(
257 UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8* p_buf, UINT16 buf_len, UINT8 rsp_type);
258 static void rc_ctrl_procedure_complete();
259 static void rc_stop_play_status_timer();
260 static void register_for_event_notification (btif_rc_supported_event_t *p_event);
261 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp);
262 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp);
263 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp);
264 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp);
265 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
266 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
267 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp);
268 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
269 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
270 static bt_status_t get_play_status_cmd(void);
271 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
272 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
273 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
274 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
275 static bt_status_t getcapabilities_cmd (uint8_t cap_id);
276 static bt_status_t list_player_app_setting_attrib_cmd(void);
277 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
278 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
280 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
281 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
282 static void rc_start_play_status_timer(void);
283 static bool absolute_volume_disabled(void);
285 /*****************************************************************************
287 ******************************************************************************/
288 static btif_rc_cb_t btif_rc_cb;
289 static btrc_callbacks_t *bt_rc_callbacks = NULL;
290 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
292 /*****************************************************************************
294 ******************************************************************************/
296 /*****************************************************************************
298 ******************************************************************************/
299 extern BOOLEAN btif_hf_call_terminated_recently();
300 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
302 extern fixed_queue_t *btu_general_alarm_queue;
304 /*****************************************************************************
306 ******************************************************************************/
308 /*****************************************************************************
309 ** Local uinput helper functions
310 ******************************************************************************/
311 int send_event (int fd, uint16_t type, uint16_t code, int32_t value)
313 struct uinput_event event;
314 BTIF_TRACE_DEBUG("%s type:%u code:%u value:%d", __FUNCTION__,
316 memset(&event, 0, sizeof(event));
321 return write(fd, &event, sizeof(event));
324 void send_key (int fd, uint16_t key, int pressed)
326 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
334 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
335 send_event(fd, EV_KEY, key, pressed);
336 send_event(fd, EV_SYN, SYN_REPORT, 0);
339 /************** uinput related functions **************/
340 int uinput_driver_check()
343 for (i=0; i < MAX_UINPUT_PATHS; i++)
345 if (access(uinput_dev_path[i], O_RDWR) == 0) {
349 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
353 int uinput_create(char *name)
355 struct uinput_dev dev;
358 for(x=0; x < MAX_UINPUT_PATHS; x++)
360 fd = open(uinput_dev_path[x], O_RDWR);
365 if (x == MAX_UINPUT_PATHS) {
366 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
369 memset(&dev, 0, sizeof(dev));
371 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
373 dev.id.bustype = BUS_BLUETOOTH;
374 dev.id.vendor = 0x0000;
375 dev.id.product = 0x0000;
376 dev.id.version = 0x0000;
378 if (write(fd, &dev, sizeof(dev)) < 0) {
379 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
384 ioctl(fd, UI_SET_EVBIT, EV_KEY);
385 ioctl(fd, UI_SET_EVBIT, EV_REL);
386 ioctl(fd, UI_SET_EVBIT, EV_SYN);
388 for (x = 0; key_map[x].name != NULL; x++)
389 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
391 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
392 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
399 int init_uinput (void)
401 char *name = "AVRCP";
403 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
404 uinput_fd = uinput_create(name);
406 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
407 __FUNCTION__, name, uinput_fd);
409 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
410 __FUNCTION__, name, uinput_fd);
415 void close_uinput (void)
417 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
419 ioctl(uinput_fd, UI_DEV_DESTROY);
426 #if (AVRC_CTLR_INCLUDED == TRUE)
427 void rc_cleanup_sent_cmd (void *p_data)
429 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
433 void handle_rc_ctrl_features(BD_ADDR bd_addr)
435 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
436 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
437 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
441 bdcpy(rc_addr.address,bd_addr);
443 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
444 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
446 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
448 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
449 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
450 (btif_rc_cb.rc_features_processed != TRUE))
452 rc_features |= BTRC_FEAT_METADATA;
453 /* Mark rc features processed to avoid repeating
454 * the AVRCP procedure every time on receiving this
457 btif_rc_cb.rc_features_processed = TRUE;
458 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
460 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
461 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
466 void handle_rc_features(BD_ADDR bd_addr)
468 if (bt_rc_callbacks != NULL)
470 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
472 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
474 if (interop_match(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
475 || absolute_volume_disabled())
476 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
478 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
480 rc_features |= BTRC_FEAT_BROWSE;
483 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
484 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
485 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
487 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
491 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
493 rc_features |= BTRC_FEAT_METADATA;
496 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
497 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
499 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
500 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
501 __FUNCTION__, btif_rc_cb.rc_vol_label);
502 // Register for volume change on connect
503 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
504 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
506 rc_transaction_t *p_transaction=NULL;
507 bt_status_t status = BT_STATUS_NOT_READY;
508 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
510 status=get_transaction(&p_transaction);
514 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
515 if (NULL!=p_transaction)
517 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
518 __FUNCTION__, btif_rc_cb.rc_vol_label);
522 status=get_transaction(&p_transaction);
525 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
527 btif_rc_cb.rc_vol_label=p_transaction->lbl;
528 register_volumechange(btif_rc_cb.rc_vol_label);
535 /***************************************************************************
536 * Function handle_rc_connect
538 * - Argument: tBTA_AV_RC_OPEN RC open data structure
540 * - Description: RC connection event handler
542 ***************************************************************************/
543 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
545 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
546 bt_status_t result = BT_STATUS_SUCCESS;
547 #if (AVRC_CTLR_INCLUDED == TRUE)
551 if (p_rc_open->status == BTA_AV_SUCCESS)
553 //check if already some RC is connected
554 if (btif_rc_cb.rc_connected)
556 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
557 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
558 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
559 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
561 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
562 BTA_AvCloseRc(p_rc_open->rc_handle);
566 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
567 btif_rc_cb.rc_features = p_rc_open->peer_features;
568 btif_rc_cb.rc_vol_label=MAX_LABEL;
569 btif_rc_cb.rc_volume=MAX_VOLUME;
571 btif_rc_cb.rc_connected = TRUE;
572 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
574 /* on locally initiated connection we will get remote features as part of connect */
575 if (btif_rc_cb.rc_features != 0)
576 handle_rc_features(btif_rc_cb.rc_addr);
579 result = uinput_driver_check();
580 if (result == BT_STATUS_SUCCESS)
587 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
590 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
591 #if (AVRC_CTLR_INCLUDED == TRUE)
592 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
593 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
594 if (bt_rc_ctrl_callbacks != NULL)
596 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
598 /* report connection state if remote device is AVRCP target */
599 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
600 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
601 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
603 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
609 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
610 __FUNCTION__, p_rc_open->status);
611 btif_rc_cb.rc_connected = FALSE;
615 /***************************************************************************
616 * Function handle_rc_disconnect
618 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
620 * - Description: RC disconnection event handler
622 ***************************************************************************/
623 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
625 #if (AVRC_CTLR_INCLUDED == TRUE)
627 tBTA_AV_FEAT features;
629 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
630 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
631 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
633 BTIF_TRACE_ERROR("Got disconnect of unknown device");
636 #if (AVRC_CTLR_INCLUDED == TRUE)
637 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
638 features = btif_rc_cb.rc_features;
639 /* Clean up AVRCP procedure flags */
640 memset(&btif_rc_cb.rc_app_settings, 0,
641 sizeof(btif_rc_player_app_settings_t));
642 btif_rc_cb.rc_features_processed = FALSE;
643 btif_rc_cb.rc_procedure_complete = FALSE;
644 rc_stop_play_status_timer();
645 /* Check and clear the notification event list */
646 if (btif_rc_cb.rc_supported_event_list != NULL)
648 list_clear(btif_rc_cb.rc_supported_event_list);
649 btif_rc_cb.rc_supported_event_list = NULL;
652 btif_rc_cb.rc_handle = 0;
653 btif_rc_cb.rc_connected = FALSE;
654 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
655 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
657 btif_rc_cb.rc_features = 0;
658 btif_rc_cb.rc_vol_label=MAX_LABEL;
659 btif_rc_cb.rc_volume=MAX_VOLUME;
660 init_all_transactions();
661 if (bt_rc_callbacks != NULL)
667 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
670 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
671 #if (AVRC_CTLR_INCLUDED == TRUE)
672 /* report connection state if device is AVRCP target */
673 if (bt_rc_ctrl_callbacks != NULL)
675 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
680 /***************************************************************************
681 * Function handle_rc_passthrough_cmd
683 * - Argument: tBTA_AV_RC rc_id remote control command ID
684 * tBTA_AV_STATE key_state status of key press
686 * - Description: Remote control command handler
688 ***************************************************************************/
689 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
694 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
696 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
699 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
700 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
702 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
704 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
705 btif_rc_cb.rc_pending_play = TRUE;
710 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
712 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
713 btif_rc_cb.rc_pending_play = FALSE;
716 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
717 return; // this command is not to be sent to UINPUT, only needed for PTS
720 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
722 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
726 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
734 /* If this is Play/Pause command (press or release) before processing, check the following
735 * a voice call has ended recently
736 * the remote device is not of type headset
737 * If the above conditions meet, drop the Play/Pause command
738 * This fix is to interop with certain carkits which sends an automatic PLAY or PAUSE
739 * commands right after call ends
741 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY || p_remote_cmd->rc_id == BTA_AV_RC_PAUSE)&&
742 (btif_hf_call_terminated_recently() == TRUE) &&
743 (check_cod( (const bt_bdaddr_t*)&(btif_rc_cb.rc_addr), COD_AV_HEADSETS) != TRUE))
745 BTIF_TRACE_DEBUG("%s:Dropping the play/Pause command received right after call end cmd:%d",
746 __FUNCTION__,p_remote_cmd->rc_id);
750 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
751 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
755 for (i = 0; key_map[i].name != NULL; i++) {
756 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
757 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
759 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
760 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
761 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
762 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
763 * The fix is to generate a release right after the press and drown the 'actual'
766 if ((key_map[i].release_quirk == 1) && (pressed == 0))
768 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
769 __FUNCTION__, key_map[i].name);
772 send_key(uinput_fd, key_map[i].mapped_id, pressed);
773 if ((key_map[i].release_quirk == 1) && (pressed == 1))
776 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
777 __FUNCTION__, key_map[i].name);
778 send_key(uinput_fd, key_map[i].mapped_id, 0);
784 if (key_map[i].name == NULL)
785 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
786 p_remote_cmd->rc_id, status);
789 /***************************************************************************
790 * Function handle_rc_passthrough_rsp
792 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
794 * - Description: Remote control passthrough response handler
796 ***************************************************************************/
797 void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
799 #if (AVRC_CTLR_INCLUDED == TRUE)
801 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
804 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
815 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
817 release_transaction(p_remote_rsp->label);
818 if (bt_rc_ctrl_callbacks != NULL) {
819 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
824 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
827 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
831 /***************************************************************************
832 * Function handle_rc_vendorunique_rsp
834 * - Argument: tBTA_AV_REMOTE_RSP command response
836 * - Description: Remote control vendor unique response handler
838 ***************************************************************************/
839 void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
841 #if (AVRC_CTLR_INCLUDED == TRUE)
844 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
847 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
858 if (p_remote_rsp->len > 0)
860 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
861 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
862 osi_free_and_reset((void **)&p_remote_rsp->p_data);
864 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
866 release_transaction(p_remote_rsp->label);
867 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
871 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
874 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
878 void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
880 tAVRC_RESPONSE avrc_rsp = {0};
881 avrc_rsp.rsp.pdu = pavrc_command->pdu;
882 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
883 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
885 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
886 avrc_rsp.reg_notif.param.uid_counter = 0;
888 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
889 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
893 /***************************************************************************
894 * Function handle_rc_metamsg_cmd
896 * - Argument: tBTA_AV_VENDOR Structure containing the received
899 * - Description: Remote control metamsg command handler (AVRCP 1.3)
901 ***************************************************************************/
902 void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
904 /* Parse the metamsg command and pass it on to BTL-IFS */
905 UINT8 scratch_buf[512] = {0};
906 tAVRC_COMMAND avrc_command = {0};
909 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
911 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
913 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
916 if (pmeta_msg->len < 3)
918 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
923 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
925 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
927 rc_transaction_t *transaction=NULL;
928 transaction=get_transaction_by_lbl(pmeta_msg->label);
929 if (NULL!=transaction)
931 handle_rc_metamsg_rsp(pmeta_msg);
935 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
936 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
942 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
943 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
949 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
950 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
951 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
953 if (status != AVRC_STS_NO_ERROR)
956 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
957 __FUNCTION__, status);
958 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
962 /* if RegisterNotification, add it to our registered queue */
964 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
966 UINT8 event_id = avrc_command.reg_notif.event_id;
967 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
968 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
969 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
970 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
972 if (event_id == AVRC_EVT_UIDS_CHANGE)
974 handle_uid_changed_notification(pmeta_msg, &avrc_command);
980 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
981 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
983 /* Since handle_rc_metamsg_cmd() itself is called from
984 *btif context, no context switching is required. Invoke
985 * btif_rc_upstreams_evt directly from here. */
986 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
991 /***************************************************************************
993 ** Function btif_rc_handler
995 ** Description RC event handler
997 ***************************************************************************/
998 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
1000 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
1003 case BTA_AV_RC_OPEN_EVT:
1005 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
1006 handle_rc_connect( &(p_data->rc_open) );
1009 case BTA_AV_RC_CLOSE_EVT:
1011 handle_rc_disconnect( &(p_data->rc_close) );
1014 case BTA_AV_REMOTE_CMD_EVT:
1016 if (bt_rc_callbacks != NULL)
1018 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1019 __FUNCTION__, p_data->remote_cmd.rc_id,
1020 p_data->remote_cmd.key_state);
1021 /** In race conditions just after 2nd AVRCP is connected
1022 * remote might send pass through commands, so check for
1023 * Rc handle before processing pass through commands
1025 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1027 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1031 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1036 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1041 #if (AVRC_CTLR_INCLUDED == TRUE)
1042 case BTA_AV_REMOTE_RSP_EVT:
1044 BTIF_TRACE_DEBUG("%s RSP: rc_id:0x%x key_state:%d",
1045 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1046 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1048 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1052 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1058 case BTA_AV_RC_FEAT_EVT:
1060 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
1061 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
1062 handle_rc_features(p_data->rc_feat.peer_addr);
1063 #if (AVRC_CTLR_INCLUDED == TRUE)
1064 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1066 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1072 case BTA_AV_META_MSG_EVT:
1074 if (bt_rc_callbacks != NULL)
1076 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1078 p_data->meta_msg.code,
1079 p_data->meta_msg.label);
1080 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1082 p_data->meta_msg.company_id,
1083 p_data->meta_msg.len,
1084 p_data->meta_msg.rc_handle);
1085 /* handle the metamsg command */
1086 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1087 /* Free the Memory allocated for tAVRC_MSG */
1089 #if (AVRC_CTLR_INCLUDED == TRUE)
1090 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1092 /* This is case of Sink + CT + TG(for abs vol)) */
1093 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1095 p_data->meta_msg.code,
1096 p_data->meta_msg.label);
1097 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1099 p_data->meta_msg.company_id,
1100 p_data->meta_msg.len,
1101 p_data->meta_msg.rc_handle);
1102 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1103 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1105 /* Its a response */
1106 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1108 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1111 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1118 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1124 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
1128 /***************************************************************************
1130 ** Function btif_rc_get_connected_peer
1132 ** Description Fetches the connected headset's BD_ADDR if any
1134 ***************************************************************************/
1135 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1137 if (btif_rc_cb.rc_connected == TRUE) {
1138 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1144 /***************************************************************************
1146 ** Function btif_rc_get_connected_peer_handle
1148 ** Description Fetches the connected headset's handle if any
1150 ***************************************************************************/
1151 UINT8 btif_rc_get_connected_peer_handle(void)
1153 return btif_rc_cb.rc_handle;
1156 /***************************************************************************
1158 ** Function btif_rc_check_handle_pending_play
1160 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1162 ***************************************************************************/
1164 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
1165 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1169 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
1170 if (btif_rc_cb.rc_pending_play)
1174 tBTA_AV_REMOTE_CMD remote_cmd;
1175 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
1177 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1178 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1179 remote_cmd.rc_id = AVRC_ID_PLAY;
1180 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1181 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1183 /* delay sending to app, else there is a timing issue in the framework,
1184 ** which causes the audio to be on th device's speaker. Delay between
1188 /* send to app - both PRESSED & RELEASED */
1189 remote_cmd.key_state = AVRC_STATE_PRESS;
1190 handle_rc_passthrough_cmd( &remote_cmd );
1194 remote_cmd.key_state = AVRC_STATE_RELEASE;
1195 handle_rc_passthrough_cmd( &remote_cmd );
1197 btif_rc_cb.rc_pending_play = FALSE;
1201 /* Generic reject response */
1202 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1204 UINT8 ctype = AVRC_RSP_REJ;
1205 tAVRC_RESPONSE avrc_rsp;
1206 BT_HDR *p_msg = NULL;
1207 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1209 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1210 avrc_rsp.rsp.pdu = pdu;
1211 avrc_rsp.rsp.status = status;
1213 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1215 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
1216 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1217 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1221 /***************************************************************************
1222 * Function send_metamsg_rsp
1225 * rc_handle RC handle corresponding to the connected RC
1226 * label Label of the RC response
1227 * code Response type
1228 * pmetamsg_resp Vendor response
1230 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1232 ***************************************************************************/
1233 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1234 tAVRC_RESPONSE *pmetamsg_resp)
1240 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
1244 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
1245 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1247 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1249 ctype = AVRC_RSP_REJ;
1253 if ( code < AVRC_RSP_NOT_IMPL)
1255 if (code == AVRC_CMD_NOTIF)
1257 ctype = AVRC_RSP_INTERIM;
1259 else if (code == AVRC_CMD_STATUS)
1261 ctype = AVRC_RSP_IMPL_STBL;
1265 ctype = AVRC_RSP_ACCEPT;
1273 /* if response is for register_notification, make sure the rc has
1274 actually registered for this */
1275 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
1277 BOOLEAN bSent = FALSE;
1278 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1279 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1281 /* de-register this notification for a CHANGED response */
1282 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
1283 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
1284 btif_rc_cb.rc_handle, event_id, bNotify);
1287 BT_HDR *p_msg = NULL;
1290 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1291 pmetamsg_resp, &p_msg)) )
1293 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
1294 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1296 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1301 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
1302 __FUNCTION__, status);
1309 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
1310 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1315 /* All other commands go here */
1317 BT_HDR *p_msg = NULL;
1320 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1322 if (status == AVRC_STS_NO_ERROR)
1324 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1328 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1329 __FUNCTION__, status);
1334 static UINT8 opcode_from_pdu(UINT8 pdu)
1340 case AVRC_PDU_NEXT_GROUP:
1341 case AVRC_PDU_PREV_GROUP: /* pass thru */
1342 opcode = AVRC_OP_PASS_THRU;
1345 default: /* vendor */
1346 opcode = AVRC_OP_VENDOR;
1353 /*******************************************************************************
1355 ** Function btif_rc_upstreams_evt
1357 ** Description Executes AVRC UPSTREAMS events in btif context.
1361 *******************************************************************************/
1362 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1364 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1365 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1369 case AVRC_PDU_GET_PLAY_STATUS:
1371 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1372 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1375 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1376 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1377 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1378 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1379 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1380 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1382 /* TODO: Add support for Application Settings */
1383 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
1386 case AVRC_PDU_GET_ELEMENT_ATTR:
1388 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1390 memset(&element_attrs, 0, sizeof(element_attrs));
1391 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1393 /* CT requests for all attributes */
1395 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1396 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
1398 element_attrs[attr_cnt] = attr_cnt + 1;
1401 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1403 /* 0xff indicates, no attributes requested - reject */
1404 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1405 AVRC_STS_BAD_PARAM);
1410 int attr_cnt, filled_attr_count;
1413 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1414 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1415 * Fill only valid entries.
1417 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1418 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1420 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1421 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1423 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1425 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1427 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1430 if (filled_attr_count == num_attr)
1432 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1438 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1439 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1442 case AVRC_PDU_REGISTER_NOTIFICATION:
1444 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1445 pavrc_cmd->reg_notif.param == 0)
1447 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
1449 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1450 /* de-register this notification for a rejected response */
1451 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1454 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1455 pavrc_cmd->reg_notif.param);
1458 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1460 tAVRC_RESPONSE avrc_rsp;
1461 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
1462 if (btif_rc_cb.rc_connected == TRUE)
1464 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1465 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1466 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1467 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1468 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1474 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1475 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1482 #if (AVRC_CTLR_INCLUDED == TRUE)
1483 /*******************************************************************************
1485 ** Function btif_rc_ctrl_upstreams_rsp_cmd
1487 ** Description Executes AVRC UPSTREAMS response events in btif context.
1491 *******************************************************************************/
1492 static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1495 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1496 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1497 bt_bdaddr_t rc_addr;
1498 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1499 #if (AVRC_CTLR_INCLUDED == TRUE)
1502 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1503 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1504 pavrc_cmd->volume.volume, label);
1506 case AVRC_PDU_REGISTER_NOTIFICATION:
1507 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1509 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1518 /*******************************************************************************
1520 ** Function btif_rc_upstreams_rsp_evt
1522 ** Description Executes AVRC UPSTREAMS response events in btif context.
1526 *******************************************************************************/
1527 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1529 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1530 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1532 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1535 case AVRC_PDU_REGISTER_NOTIFICATION:
1537 if (AVRC_RSP_CHANGED==ctype)
1538 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1539 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1543 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1545 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1546 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1547 if (AVRC_RSP_ACCEPT==ctype)
1548 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1549 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1559 /************************************************************************************
1560 ** AVRCP API Functions
1561 ************************************************************************************/
1563 /*******************************************************************************
1567 ** Description Initializes the AVRC interface
1569 ** Returns bt_status_t
1571 *******************************************************************************/
1572 static bt_status_t init(btrc_callbacks_t* callbacks )
1574 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1575 bt_status_t result = BT_STATUS_SUCCESS;
1577 if (bt_rc_callbacks)
1578 return BT_STATUS_DONE;
1580 bt_rc_callbacks = callbacks;
1581 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1582 btif_rc_cb.rc_vol_label=MAX_LABEL;
1583 btif_rc_cb.rc_volume=MAX_VOLUME;
1589 /*******************************************************************************
1591 ** Function init_ctrl
1593 ** Description Initializes the AVRC interface
1595 ** Returns bt_status_t
1597 *******************************************************************************/
1598 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1600 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1601 bt_status_t result = BT_STATUS_SUCCESS;
1603 if (bt_rc_ctrl_callbacks)
1604 return BT_STATUS_DONE;
1606 bt_rc_ctrl_callbacks = callbacks;
1607 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1608 btif_rc_cb.rc_vol_label=MAX_LABEL;
1609 btif_rc_cb.rc_volume=MAX_VOLUME;
1615 static void rc_ctrl_procedure_complete ()
1617 if (btif_rc_cb.rc_procedure_complete == TRUE)
1621 btif_rc_cb.rc_procedure_complete = TRUE;
1622 UINT32 attr_list[] = {
1623 AVRC_MEDIA_ATTR_ID_TITLE,
1624 AVRC_MEDIA_ATTR_ID_ARTIST,
1625 AVRC_MEDIA_ATTR_ID_ALBUM,
1626 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1627 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1628 AVRC_MEDIA_ATTR_ID_GENRE,
1629 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1631 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1634 /***************************************************************************
1636 ** Function get_play_status_rsp
1638 ** Description Returns the current play status.
1639 ** This method is called in response to
1640 ** GetPlayStatus request.
1642 ** Returns bt_status_t
1644 ***************************************************************************/
1645 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1648 tAVRC_RESPONSE avrc_rsp;
1650 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1651 avrc_rsp.get_play_status.song_len = song_len;
1652 avrc_rsp.get_play_status.song_pos = song_pos;
1653 avrc_rsp.get_play_status.play_status = play_status;
1655 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1656 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1657 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1658 /* Send the response */
1659 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1660 return BT_STATUS_SUCCESS;
1663 /***************************************************************************
1665 ** Function get_element_attr_rsp
1667 ** Description Returns the current songs' element attributes
1670 ** Returns bt_status_t
1672 ***************************************************************************/
1673 static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1675 tAVRC_RESPONSE avrc_rsp;
1677 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1679 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1683 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1687 for (i=0; i<num_attr; i++) {
1688 element_attrs[i].attr_id = p_attrs[i].attr_id;
1689 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1690 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1691 element_attrs[i].name.p_str = p_attrs[i].text;
1692 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
1693 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1694 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1695 element_attrs[i].name.p_str);
1697 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1699 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1700 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1701 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1702 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1703 /* Send the response */
1704 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1705 return BT_STATUS_SUCCESS;
1708 /***************************************************************************
1710 ** Function register_notification_rsp
1712 ** Description Response to the register notification request.
1715 ** Returns bt_status_t
1717 ***************************************************************************/
1718 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1719 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1721 tAVRC_RESPONSE avrc_rsp;
1723 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1724 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1726 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
1727 return BT_STATUS_NOT_READY;
1729 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1730 avrc_rsp.reg_notif.event_id = event_id;
1734 case BTRC_EVT_PLAY_STATUS_CHANGED:
1735 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1736 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1737 btif_av_clear_remote_suspend_flag();
1739 case BTRC_EVT_TRACK_CHANGE:
1740 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1742 case BTRC_EVT_PLAY_POS_CHANGED:
1743 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1746 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1747 return BT_STATUS_UNHANDLED;
1750 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1751 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1752 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1754 /* Send the response. */
1755 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1756 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1757 return BT_STATUS_SUCCESS;
1760 /***************************************************************************
1762 ** Function set_volume
1764 ** Description Send current volume setting to remote side.
1765 ** Support limited to SetAbsoluteVolume
1766 ** This can be enhanced to support Relative Volume (AVRCP 1.0).
1767 ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1768 ** as opposed to absolute volume level
1769 ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1771 ** Returns bt_status_t
1773 ***************************************************************************/
1774 static bt_status_t set_volume(uint8_t volume)
1776 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1778 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1779 rc_transaction_t *p_transaction=NULL;
1781 if (btif_rc_cb.rc_volume==volume)
1783 status=BT_STATUS_DONE;
1784 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
1788 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1789 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1791 tAVRC_COMMAND avrc_cmd = {0};
1792 BT_HDR *p_msg = NULL;
1794 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
1795 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1796 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1797 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1798 avrc_cmd.volume.volume = volume;
1800 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1802 bt_status_t tran_status=get_transaction(&p_transaction);
1803 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
1805 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
1806 __FUNCTION__,p_transaction->lbl);
1807 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1808 status = BT_STATUS_SUCCESS;
1813 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
1814 __FUNCTION__, tran_status);
1815 status = BT_STATUS_FAIL;
1820 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
1821 __FUNCTION__, status);
1822 status = BT_STATUS_FAIL;
1826 status=BT_STATUS_NOT_READY;
1830 /***************************************************************************
1832 ** Function register_volumechange
1834 ** Description Register for volume change notification from remote side.
1838 ***************************************************************************/
1840 static void register_volumechange (UINT8 lbl)
1842 tAVRC_COMMAND avrc_cmd = {0};
1843 BT_HDR *p_msg = NULL;
1844 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
1845 rc_transaction_t *p_transaction=NULL;
1847 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
1849 avrc_cmd.cmd.opcode=0x00;
1850 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1851 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1852 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1853 avrc_cmd.reg_notif.param = 0;
1855 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
1856 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1857 p_transaction = get_transaction_by_lbl(lbl);
1858 if (p_transaction != NULL) {
1859 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1860 AVRC_CMD_NOTIF, p_msg);
1861 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1864 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1868 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
1872 /***************************************************************************
1874 ** Function handle_rc_metamsg_rsp
1876 ** Description Handle RC metamessage response
1880 ***************************************************************************/
1881 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1883 tAVRC_RESPONSE avrc_response = {0};
1884 UINT8 scratch_buf[512] = {0};
1885 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1887 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
1888 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1889 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1891 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
1892 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
1893 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1894 status, pmeta_msg->label);
1896 if (status != AVRC_STS_NO_ERROR)
1898 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1899 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1900 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1902 btif_rc_cb.rc_vol_label=MAX_LABEL;
1903 release_transaction(btif_rc_cb.rc_vol_label);
1905 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1907 release_transaction(pmeta_msg->label);
1911 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1912 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1913 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1915 // Just discard the message, if the device sends back with an incorrect label
1916 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
1917 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1923 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
1924 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1928 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1929 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1930 && AVRC_RSP_CHANGED==pmeta_msg->code)
1932 /* re-register for volume change notification */
1933 // Do not re-register for rejected case, as it might get into endless loop
1934 register_volumechange(btif_rc_cb.rc_vol_label);
1936 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1938 /* free up the label here */
1939 release_transaction(pmeta_msg->label);
1942 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
1943 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1944 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1948 #if (AVRC_CTLR_INCLUDED == TRUE)
1949 /***************************************************************************
1951 ** Function iterate_supported_event_list_for_interim_rsp
1953 ** Description iterator callback function to match the event and handle
1955 ** Returns true to continue iterating, false to stop
1957 ***************************************************************************/
1958 bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1961 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1963 p_event_id = (UINT8*)cb_data;
1965 if (p_event->event_id == *p_event_id)
1967 p_event->status = eINTERIM;
1973 /***************************************************************************
1975 ** Function iterate_supported_event_list_for_timeout
1977 ** Description Iterator callback function for timeout handling.
1978 ** As part of the failure handling, it releases the
1979 ** transaction label and removes the event from list,
1980 ** this event will not be requested again during
1981 ** the lifetime of the connection.
1982 ** Returns false to stop iterating, true to continue
1984 ***************************************************************************/
1985 bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1988 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1990 label = (*(UINT8*)cb_data) & 0xFF;
1992 if (p_event->label == label)
1994 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
2000 /***************************************************************************
2002 ** Function rc_notification_interim_timout
2004 ** Description Interim response timeout handler.
2005 ** Runs the iterator to check and clear the timed out event.
2006 ** Proceeds to register for the unregistered events.
2009 ***************************************************************************/
2010 static void rc_notification_interim_timout (UINT8 label)
2014 list_foreach(btif_rc_cb.rc_supported_event_list,
2015 iterate_supported_event_list_for_timeout, &label);
2016 /* Timeout happened for interim response for the registered event,
2017 * check if there are any pending for registration
2019 node = list_begin(btif_rc_cb.rc_supported_event_list);
2020 while (node != NULL)
2022 btif_rc_supported_event_t *p_event;
2024 p_event = (btif_rc_supported_event_t *)list_node(node);
2025 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2027 register_for_event_notification(p_event);
2030 node = list_next (node);
2032 /* Todo. Need to initiate application settings query if this
2033 * is the last event registration.
2037 /***************************************************************************
2039 ** Function btif_rc_status_cmd_timeout_handler
2041 ** Description RC status command timeout handler (Runs in BTIF context).
2044 ***************************************************************************/
2045 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2048 btif_rc_timer_context_t *p_context;
2049 tAVRC_RESPONSE avrc_response = {0};
2050 tBTA_AV_META_MSG meta_msg;
2052 p_context = (btif_rc_timer_context_t *)data;
2053 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2054 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2056 switch (p_context->rc_status_cmd.pdu_id) {
2057 case AVRC_PDU_REGISTER_NOTIFICATION:
2058 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2061 case AVRC_PDU_GET_CAPABILITIES:
2062 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2063 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2066 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2067 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2068 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2071 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2072 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2073 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2076 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2077 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2078 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2081 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2082 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2083 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2086 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2087 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2088 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2091 case AVRC_PDU_GET_ELEMENT_ATTR:
2092 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2093 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2096 case AVRC_PDU_GET_PLAY_STATUS:
2097 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2098 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2101 release_transaction(p_context->rc_status_cmd.label);
2104 /***************************************************************************
2106 ** Function btif_rc_status_cmd_timer_timeout
2108 ** Description RC status command timeout callback.
2109 ** This is called from BTU context and switches to BTIF
2110 ** context to handle the timeout events
2113 ***************************************************************************/
2114 static void btif_rc_status_cmd_timer_timeout(void *data)
2116 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2118 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2119 (char *)p_data, sizeof(btif_rc_timer_context_t),
2123 /***************************************************************************
2125 ** Function btif_rc_control_cmd_timeout_handler
2127 ** Description RC control command timeout handler (Runs in BTIF context).
2130 ***************************************************************************/
2131 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2134 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2135 tAVRC_RESPONSE avrc_response = {0};
2136 tBTA_AV_META_MSG meta_msg;
2138 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2139 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2141 switch (p_context->rc_control_cmd.pdu_id) {
2142 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2143 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2144 handle_set_app_attr_val_response(&meta_msg,
2145 &avrc_response.set_app_val);
2148 release_transaction(p_context->rc_control_cmd.label);
2151 /***************************************************************************
2153 ** Function btif_rc_control_cmd_timer_timeout
2155 ** Description RC control command timeout callback.
2156 ** This is called from BTU context and switches to BTIF
2157 ** context to handle the timeout events
2160 ***************************************************************************/
2161 static void btif_rc_control_cmd_timer_timeout(void *data)
2163 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2165 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2166 (char *)p_data, sizeof(btif_rc_timer_context_t),
2170 /***************************************************************************
2172 ** Function btif_rc_play_status_timeout_handler
2174 ** Description RC play status timeout handler (Runs in BTIF context).
2177 ***************************************************************************/
2178 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2179 UNUSED_ATTR char *p_data)
2181 get_play_status_cmd();
2182 rc_start_play_status_timer();
2185 /***************************************************************************
2187 ** Function btif_rc_play_status_timer_timeout
2189 ** Description RC play status timeout callback.
2190 ** This is called from BTU context and switches to BTIF
2191 ** context to handle the timeout events
2194 ***************************************************************************/
2195 static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2197 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
2200 /***************************************************************************
2202 ** Function rc_start_play_status_timer
2204 ** Description Helper function to start the timer to fetch play status.
2207 ***************************************************************************/
2208 static void rc_start_play_status_timer(void)
2210 /* Start the Play status timer only if it is not started */
2211 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2212 if (btif_rc_cb.rc_play_status_timer == NULL) {
2213 btif_rc_cb.rc_play_status_timer =
2214 alarm_new("btif_rc.rc_play_status_timer");
2216 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2217 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2218 btif_rc_play_status_timer_timeout, NULL,
2219 btu_general_alarm_queue);
2223 /***************************************************************************
2225 ** Function rc_stop_play_status_timer
2227 ** Description Helper function to stop the play status timer.
2230 ***************************************************************************/
2231 void rc_stop_play_status_timer()
2233 if (btif_rc_cb.rc_play_status_timer != NULL)
2234 alarm_cancel(btif_rc_cb.rc_play_status_timer);
2237 /***************************************************************************
2239 ** Function register_for_event_notification
2241 ** Description Helper function registering notification events
2242 ** sets an interim response timeout to handle if the remote
2243 ** does not respond.
2246 ***************************************************************************/
2247 static void register_for_event_notification(btif_rc_supported_event_t *p_event)
2250 rc_transaction_t *p_transaction;
2252 status = get_transaction(&p_transaction);
2253 if (status == BT_STATUS_SUCCESS)
2255 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
2257 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2258 if (status != BT_STATUS_SUCCESS)
2260 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2261 __FUNCTION__, status);
2262 release_transaction (p_transaction->lbl);
2265 p_event->label = p_transaction->lbl;
2266 p_event->status = eREGISTERED;
2267 p_context->rc_status_cmd.label = p_transaction->lbl;
2268 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2270 alarm_free(p_transaction->txn_timer);
2271 p_transaction->txn_timer =
2272 alarm_new("btif_rc.status_command_txn_timer");
2273 alarm_set_on_queue(p_transaction->txn_timer,
2274 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2275 btif_rc_status_cmd_timer_timeout, p_context,
2276 btu_general_alarm_queue);
2280 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2281 __FUNCTION__, status);
2285 static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2287 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2288 p_context->rc_status_cmd.label = p_txn->lbl;
2289 p_context->rc_status_cmd.pdu_id = pdu_id;
2291 alarm_free(p_txn->txn_timer);
2292 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2293 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2294 btif_rc_status_cmd_timer_timeout, p_context,
2295 btu_general_alarm_queue);
2298 static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2300 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2301 p_context->rc_control_cmd.label = p_txn->lbl;
2302 p_context->rc_control_cmd.pdu_id = pdu_id;
2304 alarm_free(p_txn->txn_timer);
2305 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2306 alarm_set_on_queue(p_txn->txn_timer,
2307 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2308 btif_rc_control_cmd_timer_timeout, p_context,
2309 btu_general_alarm_queue);
2312 /***************************************************************************
2314 ** Function handle_get_capability_response
2316 ** Description Handles the get_cap_response to populate company id info
2317 ** and query the supported events.
2318 ** Initiates Notification registration for events supported
2321 ***************************************************************************/
2322 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2326 /* Todo: Do we need to retry on command timeout */
2327 if (p_rsp->status != AVRC_STS_NO_ERROR)
2329 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2330 __FUNCTION__, p_rsp->status);
2334 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2336 btif_rc_supported_event_t *p_event;
2338 /* Todo: Check if list can be active when we hit here */
2339 btif_rc_cb.rc_supported_event_list = list_new(osi_free);
2340 for (xx = 0; xx < p_rsp->count; xx++)
2342 /* Skip registering for Play position change notification */
2343 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2344 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2345 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2347 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
2348 p_event->event_id = p_rsp->param.event_id[xx];
2349 p_event->status = eNOT_REGISTERED;
2350 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2353 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2354 if (p_event != NULL)
2356 register_for_event_notification(p_event);
2359 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2361 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2362 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2363 for (xx = 0; xx < p_rsp->count; xx++)
2365 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2370 bool rc_is_track_id_valid (tAVRC_UID uid)
2372 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2374 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2384 /***************************************************************************
2386 ** Function handle_notification_response
2388 ** Description Main handler for notification responses to registered events
2389 ** 1. Register for unregistered event(in interim response path)
2390 ** 2. After registering for all supported events, start
2391 ** retrieving application settings and values
2392 ** 3. Reregister for events on getting changed response
2393 ** 4. Run play status timer for getting position when the
2394 ** status changes to playing
2395 ** 5. Get the Media details when the track change happens
2396 ** or track change interim response is received with
2398 ** 6. HAL callback for play status change and application
2402 ***************************************************************************/
2403 static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2405 bt_bdaddr_t rc_addr;
2406 UINT32 attr_list[] = {
2407 AVRC_MEDIA_ATTR_ID_TITLE,
2408 AVRC_MEDIA_ATTR_ID_ARTIST,
2409 AVRC_MEDIA_ATTR_ID_ALBUM,
2410 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2411 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2412 AVRC_MEDIA_ATTR_ID_GENRE,
2413 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2417 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2419 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2421 btif_rc_supported_event_t *p_event;
2424 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2425 switch (p_rsp->event_id)
2427 case AVRC_EVT_PLAY_STATUS_CHANGE:
2428 /* Start timer to get play status periodically
2429 * if the play state is playing.
2431 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2433 rc_start_play_status_timer();
2435 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2436 &rc_addr, p_rsp->param.play_status);
2439 case AVRC_EVT_TRACK_CHANGE:
2440 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2446 UINT8 *p_data = p_rsp->param.track;
2447 /* Update the UID for current track
2448 * Attributes will be fetched after the AVRCP procedure
2450 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2454 case AVRC_EVT_APP_SETTING_CHANGE:
2457 case AVRC_EVT_NOW_PLAYING_CHANGE:
2460 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2463 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2466 case AVRC_EVT_UIDS_CHANGE:
2469 case AVRC_EVT_TRACK_REACHED_END:
2470 case AVRC_EVT_TRACK_REACHED_START:
2471 case AVRC_EVT_PLAY_POS_CHANGED:
2472 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2473 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2475 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2479 list_foreach(btif_rc_cb.rc_supported_event_list,
2480 iterate_supported_event_list_for_interim_rsp,
2483 node = list_begin(btif_rc_cb.rc_supported_event_list);
2484 while (node != NULL)
2486 p_event = (btif_rc_supported_event_t *)list_node(node);
2487 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2489 register_for_event_notification(p_event);
2492 node = list_next (node);
2495 /* Registered for all events, we can request application settings */
2496 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2498 /* we need to do this only if remote TG supports
2499 * player application settings
2501 btif_rc_cb.rc_app_settings.query_started = TRUE;
2502 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2504 list_player_app_setting_attrib_cmd();
2508 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2509 rc_ctrl_procedure_complete();
2513 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2515 btif_rc_supported_event_t *p_event;
2518 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2521 node = list_begin(btif_rc_cb.rc_supported_event_list);
2522 while (node != NULL)
2524 p_event = (btif_rc_supported_event_t *)list_node(node);
2525 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2527 p_event->status = eNOT_REGISTERED;
2528 register_for_event_notification(p_event);
2531 node = list_next (node);
2534 switch (p_rsp->event_id)
2536 case AVRC_EVT_PLAY_STATUS_CHANGE:
2537 /* Start timer to get play status periodically
2538 * if the play state is playing.
2540 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2542 rc_start_play_status_timer();
2546 rc_stop_play_status_timer();
2548 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2549 &rc_addr, p_rsp->param.play_status);
2552 case AVRC_EVT_TRACK_CHANGE:
2553 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2557 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2560 case AVRC_EVT_APP_SETTING_CHANGE:
2562 btrc_player_settings_t app_settings;
2565 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2566 for (xx = 0; xx < app_settings.num_attr; xx++)
2568 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2569 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2571 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2572 &rc_addr, &app_settings);
2576 case AVRC_EVT_NOW_PLAYING_CHANGE:
2579 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2582 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2585 case AVRC_EVT_UIDS_CHANGE:
2588 case AVRC_EVT_TRACK_REACHED_END:
2589 case AVRC_EVT_TRACK_REACHED_START:
2590 case AVRC_EVT_PLAY_POS_CHANGED:
2591 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2592 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2594 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2595 __FUNCTION__, p_rsp->event_id);
2601 /***************************************************************************
2603 ** Function handle_app_attr_response
2605 ** Description handles the the application attributes response and
2606 ** initiates procedure to fetch the attribute values
2609 ***************************************************************************/
2610 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2614 if (p_rsp->status != AVRC_STS_NO_ERROR)
2616 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2617 __FUNCTION__, p_rsp->status);
2618 rc_ctrl_procedure_complete();
2622 for (xx = 0; xx < p_rsp->num_attr; xx++)
2626 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2628 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2629 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2630 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2634 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2635 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2636 btif_rc_cb.rc_app_settings.num_attrs++;
2639 btif_rc_cb.rc_app_settings.attr_index = 0;
2640 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2641 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2642 if (p_rsp->num_attr)
2644 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2648 BTIF_TRACE_ERROR("%s No Player application settings found",
2653 /***************************************************************************
2655 ** Function handle_app_val_response
2657 ** Description handles the the attributes value response and if extended
2658 ** menu is available, it initiates query for the attribute
2659 ** text. If not, it initiates procedure to get the current
2660 ** attribute values and calls the HAL callback for provding
2661 ** application settings information.
2664 ***************************************************************************/
2665 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2667 UINT8 xx, attr_index;
2668 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2669 btif_rc_player_app_settings_t *p_app_settings;
2670 bt_bdaddr_t rc_addr;
2672 /* Todo: Do we need to retry on command timeout */
2673 if (p_rsp->status != AVRC_STS_NO_ERROR)
2675 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2676 __FUNCTION__, p_rsp->status);
2680 p_app_settings = &btif_rc_cb.rc_app_settings;
2681 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2683 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2685 attr_index = p_app_settings->attr_index;
2686 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2687 for (xx = 0; xx < p_rsp->num_val; xx++)
2689 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2692 p_app_settings->attr_index++;
2693 if (attr_index < p_app_settings->num_attrs)
2695 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2697 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2700 p_app_settings->ext_attr_index = 0;
2701 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2705 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2707 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2709 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2710 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2711 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2714 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2716 attr_index = p_app_settings->ext_attr_index;
2717 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2718 for (xx = 0; xx < p_rsp->num_val; xx++)
2720 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2723 p_app_settings->ext_attr_index++;
2724 if (attr_index < p_app_settings->num_ext_attrs)
2726 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2730 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2733 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2735 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2737 get_player_app_setting_attr_text_cmd(attr, xx);
2742 /***************************************************************************
2744 ** Function handle_app_cur_val_response
2746 ** Description handles the the get attributes value response.
2750 ***************************************************************************/
2751 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2753 btrc_player_settings_t app_settings;
2754 bt_bdaddr_t rc_addr;
2757 /* Todo: Do we need to retry on command timeout */
2758 if (p_rsp->status != AVRC_STS_NO_ERROR)
2760 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2761 __FUNCTION__, p_rsp->status);
2765 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2767 app_settings.num_attr = p_rsp->num_val;
2768 for (xx = 0; xx < app_settings.num_attr; xx++)
2770 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2771 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2773 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2774 &rc_addr, &app_settings);
2775 /* Application settings are fetched only once for initial values
2776 * initiate anything that follows after RC procedure.
2777 * Defer it if browsing is supported till players query
2779 rc_ctrl_procedure_complete ();
2780 osi_free_and_reset((void **)&p_rsp->p_vals);
2783 /***************************************************************************
2785 ** Function handle_app_attr_txt_response
2787 ** Description handles the the get attributes text response, if fails
2788 ** calls HAL callback with just normal settings and initiates
2789 ** query for current settings else initiates query for value text
2792 ***************************************************************************/
2793 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2796 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2797 btif_rc_player_app_settings_t *p_app_settings;
2798 bt_bdaddr_t rc_addr;
2800 p_app_settings = &btif_rc_cb.rc_app_settings;
2801 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2803 /* Todo: Do we need to retry on command timeout */
2804 if (p_rsp->status != AVRC_STS_NO_ERROR)
2806 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2808 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2809 __FUNCTION__, p_rsp->status);
2810 /* Not able to fetch Text for extended Menu, skip the process
2811 * and cleanup used memory. Proceed to get the current settings
2812 * for standard attributes.
2814 p_app_settings->num_ext_attrs = 0;
2815 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2816 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2817 p_app_settings->ext_attr_index = 0;
2819 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2821 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2823 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2824 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2826 get_player_app_setting_cmd (xx, attrs);
2830 for (xx = 0; xx < p_rsp->num_attr; xx++)
2833 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2835 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2837 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2838 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2839 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2845 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2847 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2849 get_player_app_setting_value_text_cmd(vals, xx);
2853 /***************************************************************************
2855 ** Function handle_app_attr_val_txt_response
2857 ** Description handles the the get attributes value text response, if fails
2858 ** calls HAL callback with just normal settings and initiates
2859 ** query for current settings
2862 ***************************************************************************/
2863 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2865 UINT8 xx, attr_index;
2866 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2867 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2868 btif_rc_player_app_settings_t *p_app_settings;
2869 bt_bdaddr_t rc_addr;
2871 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2872 p_app_settings = &btif_rc_cb.rc_app_settings;
2874 /* Todo: Do we need to retry on command timeout */
2875 if (p_rsp->status != AVRC_STS_NO_ERROR)
2877 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2879 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2880 __FUNCTION__, p_rsp->status);
2882 /* Not able to fetch Text for extended Menu, skip the process
2883 * and cleanup used memory. Proceed to get the current settings
2884 * for standard attributes.
2886 p_app_settings->num_ext_attrs = 0;
2887 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2890 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2892 for (x = 0; x < p_ext_attr->num_val; x++)
2893 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2894 p_ext_attr->num_val = 0;
2895 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2897 p_app_settings->ext_attr_index = 0;
2899 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2901 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2903 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2904 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2906 get_player_app_setting_cmd (xx, attrs);
2910 for (xx = 0; xx < p_rsp->num_attr; xx++)
2913 btrc_player_app_ext_attr_t *p_ext_attr;
2914 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2915 for (x = 0; x < p_rsp->num_attr; x++)
2917 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2919 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2920 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2921 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2926 p_app_settings->ext_val_index++;
2928 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2930 attr_index = p_app_settings->ext_val_index;
2931 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2933 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2935 get_player_app_setting_value_text_cmd(vals, xx);
2941 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2943 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2945 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2947 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2949 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2950 p_app_settings->num_attrs, &p_app_settings->attrs,
2951 p_app_settings->num_ext_attrs, &p_app_settings->ext_attrs);
2952 get_player_app_setting_cmd (xx + x, attrs);
2954 /* Free the application settings information after sending to
2957 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2960 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2962 for (x = 0; x < p_ext_attr->num_val; x++)
2963 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2964 p_ext_attr->num_val = 0;
2965 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2967 p_app_settings->num_attrs = 0;
2971 /***************************************************************************
2973 ** Function handle_set_app_attr_val_response
2975 ** Description handles the the set attributes value response, if fails
2976 ** calls HAL callback to indicate the failure
2979 ***************************************************************************/
2980 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2982 uint8_t accepted = 0;
2983 bt_bdaddr_t rc_addr;
2985 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2987 /* For timeout pmeta_msg will be NULL, else we need to
2988 * check if this is accepted by TG
2990 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2994 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2997 /***************************************************************************
2999 ** Function handle_get_elem_attr_response
3001 ** Description handles the the element attributes response, calls
3002 ** HAL callback to update track change information.
3005 ***************************************************************************/
3006 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
3008 btrc_element_attr_val_t *p_attr;
3009 bt_bdaddr_t rc_addr;
3012 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3014 if (p_rsp->status == AVRC_STS_NO_ERROR)
3016 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
3017 p_attr = (btrc_element_attr_val_t *)osi_malloc(buf_size);
3018 memset(p_attr, 0, buf_size);
3019 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3020 p_attr[xx].attr_id = p_rsp->p_attrs[xx].attr_id;
3021 /* Todo. Legth limit check to include null */
3022 if (p_rsp->p_attrs[xx].name.str_len &&
3023 p_rsp->p_attrs[xx].name.p_str) {
3024 memcpy(p_attr[xx].text, p_rsp->p_attrs[xx].name.p_str,
3025 p_rsp->p_attrs[xx].name.str_len);
3026 osi_free_and_reset((void **)&p_rsp->p_attrs[xx].name.p_str);
3029 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3030 &rc_addr, p_rsp->num_attr, p_attr);
3033 else if (p_rsp->status == BTIF_RC_STS_TIMEOUT)
3035 /* Retry for timeout case, this covers error handling
3036 * for continuation failure also.
3038 UINT32 attr_list[] = {
3039 AVRC_MEDIA_ATTR_ID_TITLE,
3040 AVRC_MEDIA_ATTR_ID_ARTIST,
3041 AVRC_MEDIA_ATTR_ID_ALBUM,
3042 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3043 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3044 AVRC_MEDIA_ATTR_ID_GENRE,
3045 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3047 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
3051 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
3052 __FUNCTION__, p_rsp->status);
3056 /***************************************************************************
3058 ** Function handle_get_playstatus_response
3060 ** Description handles the the play status response, calls
3061 ** HAL callback to update play position.
3064 ***************************************************************************/
3065 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3067 bt_bdaddr_t rc_addr;
3069 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3071 if (p_rsp->status == AVRC_STS_NO_ERROR)
3073 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3074 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3078 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3079 __FUNCTION__, p_rsp->status);
3083 /***************************************************************************
3085 ** Function clear_cmd_timeout
3087 ** Description helper function to stop the command timeout timer
3090 ***************************************************************************/
3091 static void clear_cmd_timeout (UINT8 label)
3093 rc_transaction_t *p_txn;
3095 p_txn = get_transaction_by_lbl (label);
3098 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3102 if (p_txn->txn_timer != NULL)
3103 alarm_cancel(p_txn->txn_timer);
3106 /***************************************************************************
3108 ** Function handle_avk_rc_metamsg_rsp
3110 ** Description Handle RC metamessage response
3114 ***************************************************************************/
3115 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3117 tAVRC_RESPONSE avrc_response = {0};
3118 UINT8 scratch_buf[512] = {0};// this variable is unused
3122 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3123 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3125 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3126 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3127 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3129 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3130 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3131 __FUNCTION__, status, avrc_response.pdu,
3132 pmeta_msg->p_msg->vendor.hdr.ctype);
3134 switch (avrc_response.pdu)
3136 case AVRC_PDU_REGISTER_NOTIFICATION:
3137 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3138 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3140 /* Don't free the transaction Id */
3141 clear_cmd_timeout (pmeta_msg->label);
3146 case AVRC_PDU_GET_CAPABILITIES:
3147 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3150 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3151 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3154 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3155 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3158 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3159 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3162 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3163 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3166 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3167 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3170 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3171 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3174 case AVRC_PDU_GET_ELEMENT_ATTR:
3175 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3178 case AVRC_PDU_GET_PLAY_STATUS:
3179 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3182 release_transaction(pmeta_msg->label);
3186 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3187 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3192 /***************************************************************************
3194 ** Function handle_avk_rc_metamsg_cmd
3196 ** Description Handle RC metamessage response
3200 ***************************************************************************/
3201 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3203 tAVRC_COMMAND avrc_cmd = {0};
3204 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3205 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3206 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3207 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3208 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3210 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3211 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3212 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3214 if (status != AVRC_STS_NO_ERROR)
3217 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3218 __FUNCTION__, status);
3219 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3223 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3225 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3226 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3227 __FUNCTION__, dump_rc_notification_event_id(event_id));
3229 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3231 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3233 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3238 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3239 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3245 /***************************************************************************
3249 ** Description Closes the AVRC interface
3253 ***************************************************************************/
3254 static void cleanup()
3256 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3258 if (bt_rc_callbacks)
3260 bt_rc_callbacks = NULL;
3262 alarm_free(btif_rc_cb.rc_play_status_timer);
3263 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3265 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3268 /***************************************************************************
3270 ** Function cleanup_ctrl
3272 ** Description Closes the AVRC Controller interface
3276 ***************************************************************************/
3277 static void cleanup_ctrl()
3279 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3281 if (bt_rc_ctrl_callbacks)
3283 bt_rc_ctrl_callbacks = NULL;
3285 alarm_free(btif_rc_cb.rc_play_status_timer);
3286 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3288 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3291 /***************************************************************************
3293 ** Function getcapabilities_cmd
3295 ** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3299 ***************************************************************************/
3300 static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3302 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3303 rc_transaction_t *p_transaction = NULL;
3304 #if (AVRC_CTLR_INCLUDED == TRUE)
3305 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3307 bt_status_t tran_status=get_transaction(&p_transaction);
3308 if (BT_STATUS_SUCCESS != tran_status)
3309 return BT_STATUS_FAIL;
3311 tAVRC_COMMAND avrc_cmd = {0};
3312 BT_HDR *p_msg = NULL;
3313 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3314 avrc_cmd.get_caps.capability_id = cap_id;
3315 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3316 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3317 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3318 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3320 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3321 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3322 __FUNCTION__,p_transaction->lbl);
3323 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3324 data_start, p_msg->len);
3325 status = BT_STATUS_SUCCESS;
3326 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3330 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3331 __FUNCTION__, status);
3335 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3340 /***************************************************************************
3342 ** Function list_player_app_setting_attrib_cmd
3344 ** Description Get supported List Player Attributes
3348 ***************************************************************************/
3349 static bt_status_t list_player_app_setting_attrib_cmd(void)
3351 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3352 rc_transaction_t *p_transaction = NULL;
3353 #if (AVRC_CTLR_INCLUDED == TRUE)
3354 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3356 bt_status_t tran_status=get_transaction(&p_transaction);
3357 if (BT_STATUS_SUCCESS != tran_status)
3358 return BT_STATUS_FAIL;
3360 tAVRC_COMMAND avrc_cmd = {0};
3361 BT_HDR *p_msg = NULL;
3362 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3363 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3364 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3365 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3366 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3368 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3369 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3370 __FUNCTION__,p_transaction->lbl);
3371 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3372 data_start, p_msg->len);
3373 status = BT_STATUS_SUCCESS;
3374 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3379 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3380 __FUNCTION__, status);
3384 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3389 /***************************************************************************
3391 ** Function list_player_app_setting_value_cmd
3393 ** Description Get values of supported Player Attributes
3397 ***************************************************************************/
3398 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3400 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3401 rc_transaction_t *p_transaction=NULL;
3402 #if (AVRC_CTLR_INCLUDED == TRUE)
3403 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3405 bt_status_t tran_status=get_transaction(&p_transaction);
3406 if (BT_STATUS_SUCCESS != tran_status)
3407 return BT_STATUS_FAIL;
3409 tAVRC_COMMAND avrc_cmd = {0};
3410 BT_HDR *p_msg = NULL;
3411 avrc_cmd.list_app_values.attr_id = attrib_id;
3412 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3413 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3414 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3415 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3416 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3418 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3419 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3420 __FUNCTION__,p_transaction->lbl);
3421 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3422 data_start, p_msg->len);
3423 status = BT_STATUS_SUCCESS;
3424 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3428 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3432 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3437 /***************************************************************************
3439 ** Function get_player_app_setting_cmd
3441 ** Description Get current values of Player Attributes
3445 ***************************************************************************/
3446 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3448 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3449 rc_transaction_t *p_transaction = NULL;
3451 #if (AVRC_CTLR_INCLUDED == TRUE)
3452 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3454 bt_status_t tran_status=get_transaction(&p_transaction);
3455 if (BT_STATUS_SUCCESS != tran_status)
3456 return BT_STATUS_FAIL;
3458 tAVRC_COMMAND avrc_cmd = {0};
3459 BT_HDR *p_msg = NULL;
3460 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3461 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3462 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3463 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3465 for (count = 0; count < num_attrib; count++)
3467 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3469 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3470 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3472 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3473 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3474 __FUNCTION__,p_transaction->lbl);
3475 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3476 data_start, p_msg->len);
3477 status = BT_STATUS_SUCCESS;
3478 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3482 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3483 __FUNCTION__, status);
3487 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3492 /***************************************************************************
3494 ** Function change_player_app_setting
3496 ** Description Set current values of Player Attributes
3500 ***************************************************************************/
3501 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)
3503 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3504 rc_transaction_t *p_transaction = NULL;
3506 #if (AVRC_CTLR_INCLUDED == TRUE)
3507 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3509 bt_status_t tran_status=get_transaction(&p_transaction);
3510 if (BT_STATUS_SUCCESS != tran_status)
3511 return BT_STATUS_FAIL;
3513 tAVRC_COMMAND avrc_cmd = {0};
3514 BT_HDR *p_msg = NULL;
3515 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3516 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3517 avrc_cmd.set_app_val.num_val = num_attrib;
3518 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3519 avrc_cmd.set_app_val.p_vals =
3520 (tAVRC_APP_SETTING *)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
3521 for (count = 0; count < num_attrib; count++)
3523 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3524 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3526 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3527 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3529 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3530 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3531 __FUNCTION__,p_transaction->lbl);
3532 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3533 data_start, p_msg->len);
3534 status = BT_STATUS_SUCCESS;
3535 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3539 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3540 __FUNCTION__, status);
3543 osi_free_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
3545 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3550 /***************************************************************************
3552 ** Function get_player_app_setting_attr_text_cmd
3554 ** Description Get text description for app attribute
3558 ***************************************************************************/
3559 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3561 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3562 rc_transaction_t *p_transaction = NULL;
3564 #if (AVRC_CTLR_INCLUDED == TRUE)
3565 tAVRC_COMMAND avrc_cmd = {0};
3566 BT_HDR *p_msg = NULL;
3567 bt_status_t tran_status;
3570 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3572 tran_status = get_transaction(&p_transaction);
3573 if (BT_STATUS_SUCCESS != tran_status)
3574 return BT_STATUS_FAIL;
3576 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3577 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3578 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3580 for (count = 0; count < num_attrs; count++)
3582 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3584 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3585 if (status == AVRC_STS_NO_ERROR)
3587 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3588 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3589 __FUNCTION__, p_transaction->lbl);
3590 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3591 AVRC_CMD_STATUS, data_start, p_msg->len);
3593 status = BT_STATUS_SUCCESS;
3594 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3598 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3602 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3607 /***************************************************************************
3609 ** Function get_player_app_setting_val_text_cmd
3611 ** Description Get text description for app attribute values
3615 ***************************************************************************/
3616 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3618 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3619 rc_transaction_t *p_transaction = NULL;
3621 #if (AVRC_CTLR_INCLUDED == TRUE)
3622 tAVRC_COMMAND avrc_cmd = {0};
3623 BT_HDR *p_msg = NULL;
3624 bt_status_t tran_status;
3627 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3629 tran_status = get_transaction(&p_transaction);
3630 if (BT_STATUS_SUCCESS != tran_status)
3631 return BT_STATUS_FAIL;
3633 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3634 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3635 avrc_cmd.get_app_val_txt.num_val = num_vals;
3637 for (count = 0; count < num_vals; count++)
3639 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3641 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3642 if (status == AVRC_STS_NO_ERROR)
3644 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3645 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3646 __FUNCTION__, p_transaction->lbl);
3649 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3650 AVRC_CMD_STATUS, data_start, p_msg->len);
3651 status = BT_STATUS_SUCCESS;
3652 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3657 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3658 __FUNCTION__, status);
3662 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3667 /***************************************************************************
3669 ** Function register_notification_cmd
3671 ** Description Send Command to register for a Notification ID
3675 ***************************************************************************/
3676 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3679 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3680 #if (AVRC_CTLR_INCLUDED == TRUE)
3681 tAVRC_COMMAND avrc_cmd = {0};
3682 BT_HDR *p_msg = NULL;
3686 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3688 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3689 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3690 avrc_cmd.reg_notif.event_id = event_id;
3691 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3692 avrc_cmd.reg_notif.param = event_value;
3693 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3694 if (status == AVRC_STS_NO_ERROR)
3696 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3697 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3698 __FUNCTION__, label);
3701 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3702 data_start, p_msg->len);
3703 status = BT_STATUS_SUCCESS;
3708 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3709 __FUNCTION__, status);
3713 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3718 /***************************************************************************
3720 ** Function get_element_attribute_cmd
3722 ** Description Get Element Attribute for attributeIds
3726 ***************************************************************************/
3727 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3729 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3730 rc_transaction_t *p_transaction=NULL;
3732 #if (AVRC_CTLR_INCLUDED == TRUE)
3733 tAVRC_COMMAND avrc_cmd = {0};
3734 BT_HDR *p_msg = NULL;
3735 bt_status_t tran_status;
3738 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3739 __FUNCTION__, num_attribute, p_attr_ids[0]);
3741 tran_status = get_transaction(&p_transaction);
3742 if (BT_STATUS_SUCCESS != tran_status)
3743 return BT_STATUS_FAIL;
3745 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3746 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3747 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3748 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3749 for (count = 0; count < num_attribute; count++)
3751 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3754 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3755 if (status == AVRC_STS_NO_ERROR)
3757 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3758 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3759 __FUNCTION__, p_transaction->lbl);
3762 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3763 AVRC_CMD_STATUS, data_start, p_msg->len);
3764 status = BT_STATUS_SUCCESS;
3765 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3771 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3772 __FUNCTION__, status);
3776 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3781 /***************************************************************************
3783 ** Function get_play_status_cmd
3785 ** Description Get Element Attribute for attributeIds
3789 ***************************************************************************/
3790 static bt_status_t get_play_status_cmd(void)
3792 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3793 rc_transaction_t *p_transaction = NULL;
3794 #if (AVRC_CTLR_INCLUDED == TRUE)
3795 tAVRC_COMMAND avrc_cmd = {0};
3796 BT_HDR *p_msg = NULL;
3797 bt_status_t tran_status;
3800 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3801 tran_status = get_transaction(&p_transaction);
3802 if (BT_STATUS_SUCCESS != tran_status)
3803 return BT_STATUS_FAIL;
3805 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3806 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3807 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3808 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3809 if (status == AVRC_STS_NO_ERROR)
3811 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3812 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3813 __FUNCTION__, p_transaction->lbl);
3816 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3817 AVRC_CMD_STATUS, data_start, p_msg->len);
3818 status = BT_STATUS_SUCCESS;
3819 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3824 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3825 __FUNCTION__, status);
3829 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3835 /***************************************************************************
3837 ** Function set_volume_rsp
3839 ** Description Rsp for SetAbsoluteVolume Command
3843 ***************************************************************************/
3844 static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3846 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3847 #if (AVRC_CTLR_INCLUDED == TRUE)
3848 tAVRC_RESPONSE avrc_rsp;
3849 BT_HDR *p_msg = NULL;
3852 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3854 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3855 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3856 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3857 avrc_rsp.volume.volume = abs_vol;
3858 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3859 if (status == AVRC_STS_NO_ERROR)
3861 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3862 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3863 __FUNCTION__, btif_rc_cb.rc_vol_label);
3866 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3867 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3868 status = BT_STATUS_SUCCESS;
3873 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3874 __FUNCTION__, status);
3878 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3883 /***************************************************************************
3885 ** Function send_register_abs_vol_rsp
3887 ** Description Rsp for Notification of Absolute Volume
3891 ***************************************************************************/
3892 static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3893 uint8_t abs_vol, uint8_t label)
3895 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3896 tAVRC_RESPONSE avrc_rsp;
3897 BT_HDR *p_msg = NULL;
3898 #if (AVRC_CTLR_INCLUDED == TRUE)
3899 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
3902 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3903 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3904 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3905 avrc_rsp.reg_notif.param.volume = abs_vol;
3906 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
3908 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3909 if (status == AVRC_STS_NO_ERROR) {
3910 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3912 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3913 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3914 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3915 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3916 data_start, p_msg->len, 0);
3917 status = BT_STATUS_SUCCESS;
3919 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3925 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
3930 /***************************************************************************
3932 ** Function send_groupnavigation_cmd
3934 ** Description Send Pass-Through command
3938 ***************************************************************************/
3939 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3942 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3943 #if (AVRC_CTLR_INCLUDED == TRUE)
3944 rc_transaction_t *p_transaction=NULL;
3945 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3946 key_code, key_state);
3948 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3950 bt_status_t tran_status = get_transaction(&p_transaction);
3951 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
3952 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3953 UINT8* start = buffer;
3954 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3956 UINT8_TO_BE_STREAM(start, key_code);
3957 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3959 (tBTA_AV_STATE)key_state, buffer,
3960 AVRC_PASS_THRU_GROUP_LEN);
3961 status = BT_STATUS_SUCCESS;
3962 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3967 status = BT_STATUS_FAIL;
3968 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3973 status = BT_STATUS_FAIL;
3974 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3977 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3982 /***************************************************************************
3984 ** Function send_passthrough_cmd
3986 ** Description Send Pass-Through command
3990 ***************************************************************************/
3991 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3993 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3994 #if (AVRC_CTLR_INCLUDED == TRUE)
3996 rc_transaction_t *p_transaction=NULL;
3997 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3998 key_code, key_state);
3999 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
4001 bt_status_t tran_status = get_transaction(&p_transaction);
4002 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
4004 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
4005 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
4006 status = BT_STATUS_SUCCESS;
4007 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
4011 status = BT_STATUS_FAIL;
4012 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
4017 status = BT_STATUS_FAIL;
4018 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
4021 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
4026 static const btrc_interface_t bt_rc_interface = {
4027 sizeof(bt_rc_interface),
4029 get_play_status_rsp,
4030 NULL, /* list_player_app_attr_rsp */
4031 NULL, /* list_player_app_value_rsp */
4032 NULL, /* get_player_app_value_rsp */
4033 NULL, /* get_player_app_attr_text_rsp */
4034 NULL, /* get_player_app_value_text_rsp */
4035 get_element_attr_rsp,
4036 NULL, /* set_player_app_value_rsp */
4037 register_notification_rsp,
4042 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4043 sizeof(bt_rc_ctrl_interface),
4045 send_passthrough_cmd,
4046 send_groupnavigation_cmd,
4047 change_player_app_setting,
4049 volume_change_notification_rsp,
4053 /*******************************************************************************
4055 ** Function btif_rc_get_interface
4057 ** Description Get the AVRCP Target callback interface
4059 ** Returns btav_interface_t
4061 *******************************************************************************/
4062 const btrc_interface_t *btif_rc_get_interface(void)
4064 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4065 return &bt_rc_interface;
4068 /*******************************************************************************
4070 ** Function btif_rc_ctrl_get_interface
4072 ** Description Get the AVRCP Controller callback interface
4074 ** Returns btav_interface_t
4076 *******************************************************************************/
4077 const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4079 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4080 return &bt_rc_ctrl_interface;
4083 /*******************************************************************************
4084 ** Function initialize_transaction
4086 ** Description Initializes fields of the transaction structure
4089 *******************************************************************************/
4090 static void initialize_transaction(int lbl)
4092 pthread_mutex_lock(&device.lbllock);
4093 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4094 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4095 clear_cmd_timeout(lbl);
4097 device.transaction[lbl].lbl = lbl;
4098 device.transaction[lbl].in_use=FALSE;
4099 device.transaction[lbl].handle=0;
4101 pthread_mutex_unlock(&device.lbllock);
4104 /*******************************************************************************
4105 ** Function lbl_init
4107 ** Description Initializes label structures and mutexes.
4110 *******************************************************************************/
4113 memset(&device,0,sizeof(rc_device_t));
4114 pthread_mutexattr_t attr;
4115 pthread_mutexattr_init(&attr);
4116 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4117 pthread_mutex_init(&(device.lbllock), &attr);
4118 pthread_mutexattr_destroy(&attr);
4119 init_all_transactions();
4122 /*******************************************************************************
4124 ** Function init_all_transactions
4126 ** Description Initializes all transactions
4129 *******************************************************************************/
4130 void init_all_transactions()
4133 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4135 initialize_transaction(txn_indx);
4139 /*******************************************************************************
4141 ** Function get_transaction_by_lbl
4143 ** Description Will return a transaction based on the label. If not inuse
4144 ** will return an error.
4146 ** Returns bt_status_t
4147 *******************************************************************************/
4148 rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4150 rc_transaction_t *transaction = NULL;
4151 pthread_mutex_lock(&device.lbllock);
4153 /* Determine if this is a valid label */
4154 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4156 if (FALSE==device.transaction[lbl].in_use)
4162 transaction = &(device.transaction[lbl]);
4163 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
4167 pthread_mutex_unlock(&device.lbllock);
4171 /*******************************************************************************
4173 ** Function get_transaction
4175 ** Description Obtains the transaction details.
4177 ** Returns bt_status_t
4178 *******************************************************************************/
4180 bt_status_t get_transaction(rc_transaction_t **ptransaction)
4182 bt_status_t result = BT_STATUS_NOMEM;
4184 pthread_mutex_lock(&device.lbllock);
4186 // Check for unused transactions
4187 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4189 if (FALSE==device.transaction[i].in_use)
4191 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
4192 device.transaction[i].in_use = TRUE;
4193 *ptransaction = &(device.transaction[i]);
4194 result = BT_STATUS_SUCCESS;
4199 pthread_mutex_unlock(&device.lbllock);
4203 /*******************************************************************************
4205 ** Function release_transaction
4207 ** Description Will release a transaction for reuse
4209 ** Returns bt_status_t
4210 *******************************************************************************/
4211 void release_transaction(UINT8 lbl)
4213 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4215 /* If the transaction is in use... */
4216 if (transaction != NULL)
4218 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
4219 initialize_transaction(lbl);
4223 /*******************************************************************************
4225 ** Function lbl_destroy
4227 ** Description Cleanup of the mutex
4230 *******************************************************************************/
4233 pthread_mutex_destroy(&(device.lbllock));
4236 /*******************************************************************************
4237 ** Function sleep_ms
4239 ** Description Sleep the calling thread unconditionally for
4240 ** |timeout_ms| milliseconds.
4243 *******************************************************************************/
4244 static void sleep_ms(period_ms_t timeout_ms) {
4245 struct timespec delay;
4246 delay.tv_sec = timeout_ms / 1000;
4247 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4251 err = nanosleep(&delay, &delay);
4252 } while (err == -1 && errno == EINTR);
4255 static bool absolute_volume_disabled() {
4256 #if !defined(OS_GENERIC)
4257 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
4258 property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
4259 if (strncmp(volume_disabled, "true", 4) == 0) {
4260 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);
4263 #endif /* !defined(OS_GENERIC) */