2 * Copyright (C) 2015 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /*****************************************************************************
21 * Description: Bluetooth AVRC implementation
23 *****************************************************************************/
25 #define LOG_TAG "bt_btif_avrc"
34 #include <hardware/bluetooth.h>
35 #include <hardware/bt_rc.h>
37 #include "avrc_defs.h"
39 #include "bta_av_api.h"
41 #include "btif_common.h"
42 #include "btif_util.h"
43 #include "bt_common.h"
44 #include "device/include/interop.h"
46 #include "osi/include/list.h"
48 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
49 /*****************************************************************************
51 ******************************************************************************/
53 /* cod value for Headsets */
54 #define COD_AV_HEADSETS 0x0404
55 /* for AVRC 1.4 need to change this */
56 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
58 #define IDX_GET_PLAY_STATUS_RSP 0
59 #define IDX_LIST_APP_ATTR_RSP 1
60 #define IDX_LIST_APP_VALUE_RSP 2
61 #define IDX_GET_CURR_APP_VAL_RSP 3
62 #define IDX_SET_APP_VAL_RSP 4
63 #define IDX_GET_APP_ATTR_TXT_RSP 5
64 #define IDX_GET_APP_VAL_TXT_RSP 6
65 #define IDX_GET_ELEMENT_ATTR_RSP 7
66 #define MAX_VOLUME 128
68 #define MAX_TRANSACTIONS_PER_SESSION 16
69 #define MAX_CMD_QUEUE_LEN 8
70 #define PLAY_STATUS_PLAYING 1
72 #define CHECK_RC_CONNECTED \
73 BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
74 if (btif_rc_cb.rc_connected == FALSE) \
76 BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
77 return BT_STATUS_NOT_READY; \
80 #define FILL_PDU_QUEUE(index, ctype, label, pending) \
82 btif_rc_cb.rc_pdu_info[index].ctype = ctype; \
83 btif_rc_cb.rc_pdu_info[index].label = label; \
84 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
87 #define SEND_METAMSG_RSP(index, avrc_rsp) \
89 if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE) \
91 BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
92 return BT_STATUS_UNHANDLED; \
94 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label, \
95 btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp); \
96 btif_rc_cb.rc_pdu_info[index].ctype = 0; \
97 btif_rc_cb.rc_pdu_info[index].label = 0; \
98 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE; \
101 /*****************************************************************************
102 ** Local type definitions
103 ******************************************************************************/
107 } btif_rc_reg_notifications_t;
113 BOOLEAN is_rsp_pending;
114 } btif_rc_cmd_ctxt_t;
116 /* 2 second timeout to get interim response */
117 #define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000)
118 #define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000)
119 #define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000)
127 } btif_rc_nfn_reg_status_t;
132 btif_rc_nfn_reg_status_t status;
133 } btif_rc_supported_event_t;
135 #define BTIF_RC_STS_TIMEOUT 0xFE
139 } btif_rc_status_cmd_timer_t;
144 } btif_rc_control_cmd_timer_t;
148 btif_rc_status_cmd_timer_t rc_status_cmd;
149 btif_rc_control_cmd_timer_t rc_control_cmd;
151 } btif_rc_timer_context_t;
154 BOOLEAN query_started;
159 UINT8 ext_attr_index;
161 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE];
162 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE];
163 } btif_rc_player_app_settings_t;
165 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single struct */
167 BOOLEAN rc_connected;
169 tBTA_AV_FEAT rc_features;
171 UINT16 rc_pending_play;
172 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
173 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
174 unsigned int rc_volume;
175 uint8_t rc_vol_label;
176 list_t *rc_supported_event_list;
177 btif_rc_player_app_settings_t rc_app_settings;
178 alarm_t *rc_play_status_timer;
179 BOOLEAN rc_features_processed;
180 UINT64 rc_playing_uid;
181 BOOLEAN rc_procedure_complete;
188 btif_rc_timer_context_t txn_timer_context;
194 pthread_mutex_t lbllock;
195 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
200 #define MAX_UINPUT_PATHS 3
201 static const char* uinput_dev_path[] =
202 {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
203 static int uinput_fd = -1;
205 static int send_event (int fd, uint16_t type, uint16_t code, int32_t value);
206 static void send_key (int fd, uint16_t key, int pressed);
207 static int uinput_driver_check();
208 static int uinput_create(char *name);
209 static int init_uinput (void);
210 static void close_uinput (void);
211 static void sleep_ms(period_ms_t timeout_ms);
213 static const struct {
217 uint8_t release_quirk;
219 { "PLAY", AVRC_ID_PLAY, KEY_PLAYCD, 1 },
220 { "STOP", AVRC_ID_STOP, KEY_STOPCD, 0 },
221 { "PAUSE", AVRC_ID_PAUSE, KEY_PAUSECD, 1 },
222 { "FORWARD", AVRC_ID_FORWARD, KEY_NEXTSONG, 0 },
223 { "BACKWARD", AVRC_ID_BACKWARD, KEY_PREVIOUSSONG, 0 },
224 { "REWIND", AVRC_ID_REWIND, KEY_REWIND, 0 },
225 { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FAST_FORWARD, 0 },
229 static void send_reject_response (UINT8 rc_handle, UINT8 label,
230 UINT8 pdu, UINT8 status);
231 static UINT8 opcode_from_pdu(UINT8 pdu);
232 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
233 tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
234 static void register_volumechange(UINT8 label);
235 static void lbl_init();
236 static void lbl_destroy();
237 static void init_all_transactions();
238 static bt_status_t get_transaction(rc_transaction_t **ptransaction);
239 static void release_transaction(UINT8 label);
240 static rc_transaction_t* get_transaction_by_lbl(UINT8 label);
241 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
242 #if (AVRC_CTLR_INCLUDED == TRUE)
243 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg);
244 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
245 static void btif_rc_ctrl_upstreams_rsp_cmd(
246 UINT8 event, tAVRC_COMMAND *pavrc_cmd, UINT8 label);
247 static void btif_rc_ctrl_upstreams_rsp_evt(
248 UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8* p_buf, UINT16 buf_len, UINT8 rsp_type);
249 static void rc_ctrl_procedure_complete();
250 static void rc_stop_play_status_timer();
251 static void register_for_event_notification (btif_rc_supported_event_t *p_event);
252 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp);
253 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp);
254 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp);
255 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp);
256 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
257 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
258 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp);
259 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
260 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
261 static bt_status_t get_play_status_cmd(void);
262 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
263 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
264 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
265 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
266 static bt_status_t getcapabilities_cmd (uint8_t cap_id);
267 static bt_status_t list_player_app_setting_attrib_cmd(void);
268 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
269 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
271 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
272 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
273 static void rc_start_play_status_timer(void);
275 /*****************************************************************************
277 ******************************************************************************/
278 static btif_rc_cb_t btif_rc_cb;
279 static btrc_callbacks_t *bt_rc_callbacks = NULL;
280 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
282 /*****************************************************************************
284 ******************************************************************************/
286 /*****************************************************************************
288 ******************************************************************************/
289 extern BOOLEAN btif_hf_call_terminated_recently();
290 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
292 extern fixed_queue_t *btu_general_alarm_queue;
294 /*****************************************************************************
296 ******************************************************************************/
298 /*****************************************************************************
299 ** Local uinput helper functions
300 ******************************************************************************/
301 int send_event (int fd, uint16_t type, uint16_t code, int32_t value)
303 struct uinput_event event;
304 BTIF_TRACE_DEBUG("%s type:%u code:%u value:%d", __FUNCTION__,
306 memset(&event, 0, sizeof(event));
311 return write(fd, &event, sizeof(event));
314 void send_key (int fd, uint16_t key, int pressed)
316 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
324 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
325 send_event(fd, EV_KEY, key, pressed);
326 send_event(fd, EV_SYN, SYN_REPORT, 0);
329 /************** uinput related functions **************/
330 int uinput_driver_check()
333 for (i=0; i < MAX_UINPUT_PATHS; i++)
335 if (access(uinput_dev_path[i], O_RDWR) == 0) {
339 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
343 int uinput_create(char *name)
345 struct uinput_dev dev;
348 for(x=0; x < MAX_UINPUT_PATHS; x++)
350 fd = open(uinput_dev_path[x], O_RDWR);
355 if (x == MAX_UINPUT_PATHS) {
356 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
359 memset(&dev, 0, sizeof(dev));
361 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
363 dev.id.bustype = BUS_BLUETOOTH;
364 dev.id.vendor = 0x0000;
365 dev.id.product = 0x0000;
366 dev.id.version = 0x0000;
368 if (write(fd, &dev, sizeof(dev)) < 0) {
369 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
374 ioctl(fd, UI_SET_EVBIT, EV_KEY);
375 ioctl(fd, UI_SET_EVBIT, EV_REL);
376 ioctl(fd, UI_SET_EVBIT, EV_SYN);
378 for (x = 0; key_map[x].name != NULL; x++)
379 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
381 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
382 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
389 int init_uinput (void)
391 char *name = "AVRCP";
393 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
394 uinput_fd = uinput_create(name);
396 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
397 __FUNCTION__, name, uinput_fd);
399 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
400 __FUNCTION__, name, uinput_fd);
405 void close_uinput (void)
407 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
409 ioctl(uinput_fd, UI_DEV_DESTROY);
416 #if (AVRC_CTLR_INCLUDED == TRUE)
417 void rc_cleanup_sent_cmd (void *p_data)
419 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
423 void handle_rc_ctrl_features(BD_ADDR bd_addr)
425 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
426 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
427 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
431 bdcpy(rc_addr.address,bd_addr);
433 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
434 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
436 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
438 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
439 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
440 (btif_rc_cb.rc_features_processed != TRUE))
442 rc_features |= BTRC_FEAT_METADATA;
443 /* Mark rc features processed to avoid repeating
444 * the AVRCP procedure every time on receiving this
447 btif_rc_cb.rc_features_processed = TRUE;
448 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
450 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
451 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
456 void handle_rc_features(BD_ADDR bd_addr)
458 if (bt_rc_callbacks != NULL)
460 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
462 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
464 if (interop_match(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr))
465 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
467 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
469 rc_features |= BTRC_FEAT_BROWSE;
472 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
473 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
474 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
476 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
480 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
482 rc_features |= BTRC_FEAT_METADATA;
485 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
486 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
488 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
489 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
490 __FUNCTION__, btif_rc_cb.rc_vol_label);
491 // Register for volume change on connect
492 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
493 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
495 rc_transaction_t *p_transaction=NULL;
496 bt_status_t status = BT_STATUS_NOT_READY;
497 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
499 status=get_transaction(&p_transaction);
503 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
504 if (NULL!=p_transaction)
506 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
507 __FUNCTION__, btif_rc_cb.rc_vol_label);
511 status=get_transaction(&p_transaction);
514 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
516 btif_rc_cb.rc_vol_label=p_transaction->lbl;
517 register_volumechange(btif_rc_cb.rc_vol_label);
524 /***************************************************************************
525 * Function handle_rc_connect
527 * - Argument: tBTA_AV_RC_OPEN RC open data structure
529 * - Description: RC connection event handler
531 ***************************************************************************/
532 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
534 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
535 bt_status_t result = BT_STATUS_SUCCESS;
536 #if (AVRC_CTLR_INCLUDED == TRUE)
540 if (p_rc_open->status == BTA_AV_SUCCESS)
542 //check if already some RC is connected
543 if (btif_rc_cb.rc_connected)
545 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
546 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
547 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
548 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
550 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
551 BTA_AvCloseRc(p_rc_open->rc_handle);
555 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
556 btif_rc_cb.rc_features = p_rc_open->peer_features;
557 btif_rc_cb.rc_vol_label=MAX_LABEL;
558 btif_rc_cb.rc_volume=MAX_VOLUME;
560 btif_rc_cb.rc_connected = TRUE;
561 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
563 /* on locally initiated connection we will get remote features as part of connect */
564 if (btif_rc_cb.rc_features != 0)
565 handle_rc_features(btif_rc_cb.rc_addr);
568 result = uinput_driver_check();
569 if (result == BT_STATUS_SUCCESS)
576 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
579 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
580 #if (AVRC_CTLR_INCLUDED == TRUE)
581 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
582 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
583 if (bt_rc_ctrl_callbacks != NULL)
585 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
587 /* report connection state if remote device is AVRCP target */
588 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
589 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
590 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
592 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
598 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
599 __FUNCTION__, p_rc_open->status);
600 btif_rc_cb.rc_connected = FALSE;
604 /***************************************************************************
605 * Function handle_rc_disconnect
607 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
609 * - Description: RC disconnection event handler
611 ***************************************************************************/
612 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
614 #if (AVRC_CTLR_INCLUDED == TRUE)
616 tBTA_AV_FEAT features;
618 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
619 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
620 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
622 BTIF_TRACE_ERROR("Got disconnect of unknown device");
625 #if (AVRC_CTLR_INCLUDED == TRUE)
626 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
627 features = btif_rc_cb.rc_features;
628 /* Clean up AVRCP procedure flags */
629 memset(&btif_rc_cb.rc_app_settings, 0,
630 sizeof(btif_rc_player_app_settings_t));
631 btif_rc_cb.rc_features_processed = FALSE;
632 btif_rc_cb.rc_procedure_complete = FALSE;
633 rc_stop_play_status_timer();
634 /* Check and clear the notification event list */
635 if (btif_rc_cb.rc_supported_event_list != NULL)
637 list_clear(btif_rc_cb.rc_supported_event_list);
638 btif_rc_cb.rc_supported_event_list = NULL;
641 btif_rc_cb.rc_handle = 0;
642 btif_rc_cb.rc_connected = FALSE;
643 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
644 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
646 btif_rc_cb.rc_features = 0;
647 btif_rc_cb.rc_vol_label=MAX_LABEL;
648 btif_rc_cb.rc_volume=MAX_VOLUME;
649 init_all_transactions();
650 if (bt_rc_callbacks != NULL)
656 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
659 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
660 #if (AVRC_CTLR_INCLUDED == TRUE)
661 /* report connection state if device is AVRCP target */
662 if (bt_rc_ctrl_callbacks != NULL)
664 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
669 /***************************************************************************
670 * Function handle_rc_passthrough_cmd
672 * - Argument: tBTA_AV_RC rc_id remote control command ID
673 * tBTA_AV_STATE key_state status of key press
675 * - Description: Remote control command handler
677 ***************************************************************************/
678 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
683 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
685 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
688 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
689 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
691 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
693 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
694 btif_rc_cb.rc_pending_play = TRUE;
699 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
701 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
702 btif_rc_cb.rc_pending_play = FALSE;
705 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
706 return; // this command is not to be sent to UINPUT, only needed for PTS
709 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
711 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
715 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
723 /* If this is Play/Pause command (press or release) before processing, check the following
724 * a voice call has ended recently
725 * the remote device is not of type headset
726 * If the above conditions meet, drop the Play/Pause command
727 * This fix is to interop with certain carkits which sends an automatic PLAY or PAUSE
728 * commands right after call ends
730 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY || p_remote_cmd->rc_id == BTA_AV_RC_PAUSE)&&
731 (btif_hf_call_terminated_recently() == TRUE) &&
732 (check_cod( (const bt_bdaddr_t*)&(btif_rc_cb.rc_addr), COD_AV_HEADSETS) != TRUE))
734 BTIF_TRACE_DEBUG("%s:Dropping the play/Pause command received right after call end cmd:%d",
735 __FUNCTION__,p_remote_cmd->rc_id);
739 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
740 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
744 for (i = 0; key_map[i].name != NULL; i++) {
745 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
746 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
748 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
749 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
750 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
751 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
752 * The fix is to generate a release right after the press and drown the 'actual'
755 if ((key_map[i].release_quirk == 1) && (pressed == 0))
757 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
758 __FUNCTION__, key_map[i].name);
761 send_key(uinput_fd, key_map[i].mapped_id, pressed);
762 if ((key_map[i].release_quirk == 1) && (pressed == 1))
765 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
766 __FUNCTION__, key_map[i].name);
767 send_key(uinput_fd, key_map[i].mapped_id, 0);
773 if (key_map[i].name == NULL)
774 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
775 p_remote_cmd->rc_id, status);
778 /***************************************************************************
779 * Function handle_rc_passthrough_rsp
781 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
783 * - Description: Remote control passthrough response handler
785 ***************************************************************************/
786 void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
788 #if (AVRC_CTLR_INCLUDED == TRUE)
790 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
793 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
804 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
806 release_transaction(p_remote_rsp->label);
807 if (bt_rc_ctrl_callbacks != NULL) {
808 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
813 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
816 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
820 /***************************************************************************
821 * Function handle_rc_vendorunique_rsp
823 * - Argument: tBTA_AV_REMOTE_RSP command response
825 * - Description: Remote control vendor unique response handler
827 ***************************************************************************/
828 void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
830 #if (AVRC_CTLR_INCLUDED == TRUE)
833 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
836 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
847 if (p_remote_rsp->len > 0)
849 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
850 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
851 osi_freebuf_and_reset((void **)&p_remote_rsp->p_data);
853 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
855 release_transaction(p_remote_rsp->label);
856 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
860 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
863 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
867 void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
869 tAVRC_RESPONSE avrc_rsp = {0};
870 avrc_rsp.rsp.pdu = pavrc_command->pdu;
871 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
872 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
874 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
875 avrc_rsp.reg_notif.param.uid_counter = 0;
877 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
878 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
882 /***************************************************************************
883 * Function handle_rc_metamsg_cmd
885 * - Argument: tBTA_AV_VENDOR Structure containing the received
888 * - Description: Remote control metamsg command handler (AVRCP 1.3)
890 ***************************************************************************/
891 void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
893 /* Parse the metamsg command and pass it on to BTL-IFS */
894 UINT8 scratch_buf[512] = {0};
895 tAVRC_COMMAND avrc_command = {0};
898 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
900 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
902 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
905 if (pmeta_msg->len < 3)
907 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
912 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
914 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
916 rc_transaction_t *transaction=NULL;
917 transaction=get_transaction_by_lbl(pmeta_msg->label);
918 if (NULL!=transaction)
920 handle_rc_metamsg_rsp(pmeta_msg);
924 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
925 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
931 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
932 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
938 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
939 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
940 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
942 if (status != AVRC_STS_NO_ERROR)
945 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
946 __FUNCTION__, status);
947 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
951 /* if RegisterNotification, add it to our registered queue */
953 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
955 UINT8 event_id = avrc_command.reg_notif.event_id;
956 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
957 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
958 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
959 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
961 if (event_id == AVRC_EVT_UIDS_CHANGE)
963 handle_uid_changed_notification(pmeta_msg, &avrc_command);
969 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
970 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
972 /* Since handle_rc_metamsg_cmd() itself is called from
973 *btif context, no context switching is required. Invoke
974 * btif_rc_upstreams_evt directly from here. */
975 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
980 /***************************************************************************
982 ** Function btif_rc_handler
984 ** Description RC event handler
986 ***************************************************************************/
987 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
989 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
992 case BTA_AV_RC_OPEN_EVT:
994 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
995 handle_rc_connect( &(p_data->rc_open) );
998 case BTA_AV_RC_CLOSE_EVT:
1000 handle_rc_disconnect( &(p_data->rc_close) );
1003 case BTA_AV_REMOTE_CMD_EVT:
1005 if (bt_rc_callbacks != NULL)
1007 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1008 __FUNCTION__, p_data->remote_cmd.rc_id,
1009 p_data->remote_cmd.key_state);
1010 /** In race conditions just after 2nd AVRCP is connected
1011 * remote might send pass through commands, so check for
1012 * Rc handle before processing pass through commands
1014 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1016 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1020 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1025 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1030 #if (AVRC_CTLR_INCLUDED == TRUE)
1031 case BTA_AV_REMOTE_RSP_EVT:
1033 BTIF_TRACE_DEBUG("%s %s RSP: rc_id:0x%x key_state:%d",
1034 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1035 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1037 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1041 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1047 case BTA_AV_RC_FEAT_EVT:
1049 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
1050 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
1051 handle_rc_features(p_data->rc_feat.peer_addr);
1052 #if (AVRC_CTLR_INCLUDED == TRUE)
1053 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1055 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1061 case BTA_AV_META_MSG_EVT:
1063 if (bt_rc_callbacks != NULL)
1065 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1067 p_data->meta_msg.code,
1068 p_data->meta_msg.label);
1069 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1071 p_data->meta_msg.company_id,
1072 p_data->meta_msg.len,
1073 p_data->meta_msg.rc_handle);
1074 /* handle the metamsg command */
1075 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1076 /* Free the Memory allocated for tAVRC_MSG */
1078 #if (AVRC_CTLR_INCLUDED == TRUE)
1079 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1081 /* This is case of Sink + CT + TG(for abs vol)) */
1082 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1084 p_data->meta_msg.code,
1085 p_data->meta_msg.label);
1086 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1088 p_data->meta_msg.company_id,
1089 p_data->meta_msg.len,
1090 p_data->meta_msg.rc_handle);
1091 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1092 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1094 /* Its a response */
1095 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1097 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1100 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1107 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1113 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
1117 /***************************************************************************
1119 ** Function btif_rc_get_connected_peer
1121 ** Description Fetches the connected headset's BD_ADDR if any
1123 ***************************************************************************/
1124 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1126 if (btif_rc_cb.rc_connected == TRUE) {
1127 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1133 /***************************************************************************
1135 ** Function btif_rc_get_connected_peer_handle
1137 ** Description Fetches the connected headset's handle if any
1139 ***************************************************************************/
1140 UINT8 btif_rc_get_connected_peer_handle(void)
1142 return btif_rc_cb.rc_handle;
1145 /***************************************************************************
1147 ** Function btif_rc_check_handle_pending_play
1149 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1151 ***************************************************************************/
1153 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
1154 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1158 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
1159 if (btif_rc_cb.rc_pending_play)
1163 tBTA_AV_REMOTE_CMD remote_cmd;
1164 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
1166 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1167 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1168 remote_cmd.rc_id = AVRC_ID_PLAY;
1169 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1170 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1172 /* delay sending to app, else there is a timing issue in the framework,
1173 ** which causes the audio to be on th device's speaker. Delay between
1177 /* send to app - both PRESSED & RELEASED */
1178 remote_cmd.key_state = AVRC_STATE_PRESS;
1179 handle_rc_passthrough_cmd( &remote_cmd );
1183 remote_cmd.key_state = AVRC_STATE_RELEASE;
1184 handle_rc_passthrough_cmd( &remote_cmd );
1186 btif_rc_cb.rc_pending_play = FALSE;
1190 /* Generic reject response */
1191 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1193 UINT8 ctype = AVRC_RSP_REJ;
1194 tAVRC_RESPONSE avrc_rsp;
1195 BT_HDR *p_msg = NULL;
1196 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1198 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1199 avrc_rsp.rsp.pdu = pdu;
1200 avrc_rsp.rsp.status = status;
1202 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1204 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
1205 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1206 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1210 /***************************************************************************
1211 * Function send_metamsg_rsp
1214 * rc_handle RC handle corresponding to the connected RC
1215 * label Label of the RC response
1216 * code Response type
1217 * pmetamsg_resp Vendor response
1219 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1221 ***************************************************************************/
1222 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1223 tAVRC_RESPONSE *pmetamsg_resp)
1229 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
1233 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
1234 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1236 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1238 ctype = AVRC_RSP_REJ;
1242 if ( code < AVRC_RSP_NOT_IMPL)
1244 if (code == AVRC_CMD_NOTIF)
1246 ctype = AVRC_RSP_INTERIM;
1248 else if (code == AVRC_CMD_STATUS)
1250 ctype = AVRC_RSP_IMPL_STBL;
1254 ctype = AVRC_RSP_ACCEPT;
1262 /* if response is for register_notification, make sure the rc has
1263 actually registered for this */
1264 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
1266 BOOLEAN bSent = FALSE;
1267 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1268 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1270 /* de-register this notification for a CHANGED response */
1271 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
1272 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
1273 btif_rc_cb.rc_handle, event_id, bNotify);
1276 BT_HDR *p_msg = NULL;
1279 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1280 pmetamsg_resp, &p_msg)) )
1282 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
1283 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1285 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1290 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
1291 __FUNCTION__, status);
1298 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
1299 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1304 /* All other commands go here */
1306 BT_HDR *p_msg = NULL;
1309 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1311 if (status == AVRC_STS_NO_ERROR)
1313 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1317 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1318 __FUNCTION__, status);
1323 static UINT8 opcode_from_pdu(UINT8 pdu)
1329 case AVRC_PDU_NEXT_GROUP:
1330 case AVRC_PDU_PREV_GROUP: /* pass thru */
1331 opcode = AVRC_OP_PASS_THRU;
1334 default: /* vendor */
1335 opcode = AVRC_OP_VENDOR;
1342 /*******************************************************************************
1344 ** Function btif_rc_upstreams_evt
1346 ** Description Executes AVRC UPSTREAMS events in btif context.
1350 *******************************************************************************/
1351 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1353 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1354 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1358 case AVRC_PDU_GET_PLAY_STATUS:
1360 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1361 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1364 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1365 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1366 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1367 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1368 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1369 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1371 /* TODO: Add support for Application Settings */
1372 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
1375 case AVRC_PDU_GET_ELEMENT_ATTR:
1377 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1379 memset(&element_attrs, 0, sizeof(element_attrs));
1380 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1382 /* CT requests for all attributes */
1384 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1385 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
1387 element_attrs[attr_cnt] = attr_cnt + 1;
1390 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1392 /* 0xff indicates, no attributes requested - reject */
1393 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1394 AVRC_STS_BAD_PARAM);
1399 int attr_cnt, filled_attr_count;
1402 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1403 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1404 * Fill only valid entries.
1406 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1407 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1409 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1410 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1412 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1414 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1416 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1419 if (filled_attr_count == num_attr)
1421 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1427 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1428 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1431 case AVRC_PDU_REGISTER_NOTIFICATION:
1433 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1434 pavrc_cmd->reg_notif.param == 0)
1436 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
1438 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1439 /* de-register this notification for a rejected response */
1440 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1443 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1444 pavrc_cmd->reg_notif.param);
1447 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1449 tAVRC_RESPONSE avrc_rsp;
1450 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
1451 if (btif_rc_cb.rc_connected == TRUE)
1453 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1454 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1455 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1456 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1457 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1463 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1464 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1471 #if (AVRC_CTLR_INCLUDED == TRUE)
1472 /*******************************************************************************
1474 ** Function btif_rc_ctrl_upstreams_rsp_cmd
1476 ** Description Executes AVRC UPSTREAMS response events in btif context.
1480 *******************************************************************************/
1481 static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1484 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1485 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1486 bt_bdaddr_t rc_addr;
1487 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1488 #if (AVRC_CTLR_INCLUDED == TRUE)
1491 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1492 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1493 pavrc_cmd->volume.volume, label);
1495 case AVRC_PDU_REGISTER_NOTIFICATION:
1496 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1498 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1507 /*******************************************************************************
1509 ** Function btif_rc_upstreams_rsp_evt
1511 ** Description Executes AVRC UPSTREAMS response events in btif context.
1515 *******************************************************************************/
1516 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1518 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1519 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1521 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1524 case AVRC_PDU_REGISTER_NOTIFICATION:
1526 if (AVRC_RSP_CHANGED==ctype)
1527 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1528 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1532 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1534 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1535 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1536 if (AVRC_RSP_ACCEPT==ctype)
1537 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1538 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1548 /************************************************************************************
1549 ** AVRCP API Functions
1550 ************************************************************************************/
1552 /*******************************************************************************
1556 ** Description Initializes the AVRC interface
1558 ** Returns bt_status_t
1560 *******************************************************************************/
1561 static bt_status_t init(btrc_callbacks_t* callbacks )
1563 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1564 bt_status_t result = BT_STATUS_SUCCESS;
1566 if (bt_rc_callbacks)
1567 return BT_STATUS_DONE;
1569 bt_rc_callbacks = callbacks;
1570 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1571 btif_rc_cb.rc_vol_label=MAX_LABEL;
1572 btif_rc_cb.rc_volume=MAX_VOLUME;
1578 /*******************************************************************************
1580 ** Function init_ctrl
1582 ** Description Initializes the AVRC interface
1584 ** Returns bt_status_t
1586 *******************************************************************************/
1587 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1589 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1590 bt_status_t result = BT_STATUS_SUCCESS;
1592 if (bt_rc_ctrl_callbacks)
1593 return BT_STATUS_DONE;
1595 bt_rc_ctrl_callbacks = callbacks;
1596 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1597 btif_rc_cb.rc_vol_label=MAX_LABEL;
1598 btif_rc_cb.rc_volume=MAX_VOLUME;
1604 static void rc_ctrl_procedure_complete ()
1606 if (btif_rc_cb.rc_procedure_complete == TRUE)
1610 btif_rc_cb.rc_procedure_complete = TRUE;
1611 UINT32 attr_list[] = {
1612 AVRC_MEDIA_ATTR_ID_TITLE,
1613 AVRC_MEDIA_ATTR_ID_ARTIST,
1614 AVRC_MEDIA_ATTR_ID_ALBUM,
1615 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1616 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1617 AVRC_MEDIA_ATTR_ID_GENRE,
1618 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1620 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1623 /***************************************************************************
1625 ** Function get_play_status_rsp
1627 ** Description Returns the current play status.
1628 ** This method is called in response to
1629 ** GetPlayStatus request.
1631 ** Returns bt_status_t
1633 ***************************************************************************/
1634 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1637 tAVRC_RESPONSE avrc_rsp;
1639 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1640 avrc_rsp.get_play_status.song_len = song_len;
1641 avrc_rsp.get_play_status.song_pos = song_pos;
1642 avrc_rsp.get_play_status.play_status = play_status;
1644 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1645 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1646 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1647 /* Send the response */
1648 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1649 return BT_STATUS_SUCCESS;
1652 /***************************************************************************
1654 ** Function get_element_attr_rsp
1656 ** Description Returns the current songs' element attributes
1659 ** Returns bt_status_t
1661 ***************************************************************************/
1662 static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1664 tAVRC_RESPONSE avrc_rsp;
1666 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1668 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1672 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1676 for (i=0; i<num_attr; i++) {
1677 element_attrs[i].attr_id = p_attrs[i].attr_id;
1678 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1679 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1680 element_attrs[i].name.p_str = p_attrs[i].text;
1681 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
1682 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1683 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1684 element_attrs[i].name.p_str);
1686 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1688 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1689 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1690 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1691 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1692 /* Send the response */
1693 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1694 return BT_STATUS_SUCCESS;
1697 /***************************************************************************
1699 ** Function register_notification_rsp
1701 ** Description Response to the register notification request.
1704 ** Returns bt_status_t
1706 ***************************************************************************/
1707 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1708 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1710 tAVRC_RESPONSE avrc_rsp;
1712 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1713 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1715 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
1716 return BT_STATUS_NOT_READY;
1718 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1719 avrc_rsp.reg_notif.event_id = event_id;
1723 case BTRC_EVT_PLAY_STATUS_CHANGED:
1724 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1725 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1726 btif_av_clear_remote_suspend_flag();
1728 case BTRC_EVT_TRACK_CHANGE:
1729 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1731 case BTRC_EVT_PLAY_POS_CHANGED:
1732 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1735 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1736 return BT_STATUS_UNHANDLED;
1739 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1740 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1741 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1743 /* Send the response. */
1744 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1745 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1746 return BT_STATUS_SUCCESS;
1749 /***************************************************************************
1751 ** Function set_volume
1753 ** Description Send current volume setting to remote side.
1754 ** Support limited to SetAbsoluteVolume
1755 ** This can be enhanced to support Relative Volume (AVRCP 1.0).
1756 ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1757 ** as opposed to absolute volume level
1758 ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1760 ** Returns bt_status_t
1762 ***************************************************************************/
1763 static bt_status_t set_volume(uint8_t volume)
1765 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1767 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1768 rc_transaction_t *p_transaction=NULL;
1770 if (btif_rc_cb.rc_volume==volume)
1772 status=BT_STATUS_DONE;
1773 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
1777 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1778 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1780 tAVRC_COMMAND avrc_cmd = {0};
1781 BT_HDR *p_msg = NULL;
1783 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
1784 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1785 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1786 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1787 avrc_cmd.volume.volume = volume;
1789 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1791 bt_status_t tran_status=get_transaction(&p_transaction);
1792 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
1794 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
1795 __FUNCTION__,p_transaction->lbl);
1796 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1797 status = BT_STATUS_SUCCESS;
1802 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
1803 __FUNCTION__, tran_status);
1804 status = BT_STATUS_FAIL;
1809 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
1810 __FUNCTION__, status);
1811 status = BT_STATUS_FAIL;
1815 status=BT_STATUS_NOT_READY;
1819 /***************************************************************************
1821 ** Function register_volumechange
1823 ** Description Register for volume change notification from remote side.
1827 ***************************************************************************/
1829 static void register_volumechange (UINT8 lbl)
1831 tAVRC_COMMAND avrc_cmd = {0};
1832 BT_HDR *p_msg = NULL;
1833 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
1834 rc_transaction_t *p_transaction=NULL;
1836 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
1838 avrc_cmd.cmd.opcode=0x00;
1839 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1840 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1841 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1842 avrc_cmd.reg_notif.param = 0;
1844 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
1845 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1846 p_transaction = get_transaction_by_lbl(lbl);
1847 if (p_transaction != NULL) {
1848 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1849 AVRC_CMD_NOTIF, p_msg);
1850 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1853 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1857 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
1861 /***************************************************************************
1863 ** Function handle_rc_metamsg_rsp
1865 ** Description Handle RC metamessage response
1869 ***************************************************************************/
1870 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1872 tAVRC_RESPONSE avrc_response = {0};
1873 UINT8 scratch_buf[512] = {0};
1874 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1876 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
1877 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1878 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1880 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
1881 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
1882 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1883 status, pmeta_msg->label);
1885 if (status != AVRC_STS_NO_ERROR)
1887 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1888 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1889 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1891 btif_rc_cb.rc_vol_label=MAX_LABEL;
1892 release_transaction(btif_rc_cb.rc_vol_label);
1894 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1896 release_transaction(pmeta_msg->label);
1900 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1901 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1902 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1904 // Just discard the message, if the device sends back with an incorrect label
1905 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
1906 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1912 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
1913 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1917 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1918 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1919 && AVRC_RSP_CHANGED==pmeta_msg->code)
1921 /* re-register for volume change notification */
1922 // Do not re-register for rejected case, as it might get into endless loop
1923 register_volumechange(btif_rc_cb.rc_vol_label);
1925 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1927 /* free up the label here */
1928 release_transaction(pmeta_msg->label);
1931 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
1932 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1933 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1937 #if (AVRC_CTLR_INCLUDED == TRUE)
1938 /***************************************************************************
1940 ** Function iterate_supported_event_list_for_interim_rsp
1942 ** Description iterator callback function to match the event and handle
1944 ** Returns true to continue iterating, false to stop
1946 ***************************************************************************/
1947 bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1950 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1952 p_event_id = (UINT8*)cb_data;
1954 if (p_event->event_id == *p_event_id)
1956 p_event->status = eINTERIM;
1962 /***************************************************************************
1964 ** Function iterate_supported_event_list_for_timeout
1966 ** Description Iterator callback function for timeout handling.
1967 ** As part of the failure handling, it releases the
1968 ** transaction label and removes the event from list,
1969 ** this event will not be requested again during
1970 ** the lifetime of the connection.
1971 ** Returns false to stop iterating, true to continue
1973 ***************************************************************************/
1974 bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1977 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1979 label = (*(UINT8*)cb_data) & 0xFF;
1981 if (p_event->label == label)
1983 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
1989 /***************************************************************************
1991 ** Function rc_notification_interim_timout
1993 ** Description Interim response timeout handler.
1994 ** Runs the iterator to check and clear the timed out event.
1995 ** Proceeds to register for the unregistered events.
1998 ***************************************************************************/
1999 static void rc_notification_interim_timout (UINT8 label)
2003 list_foreach(btif_rc_cb.rc_supported_event_list,
2004 iterate_supported_event_list_for_timeout, &label);
2005 /* Timeout happened for interim response for the registered event,
2006 * check if there are any pending for registration
2008 node = list_begin(btif_rc_cb.rc_supported_event_list);
2009 while (node != NULL)
2011 btif_rc_supported_event_t *p_event;
2013 p_event = (btif_rc_supported_event_t *)list_node(node);
2014 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2016 register_for_event_notification(p_event);
2019 node = list_next (node);
2021 /* Todo. Need to initiate application settings query if this
2022 * is the last event registration.
2026 /***************************************************************************
2028 ** Function btif_rc_status_cmd_timeout_handler
2030 ** Description RC status command timeout handler (Runs in BTIF context).
2033 ***************************************************************************/
2034 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2037 btif_rc_timer_context_t *p_context;
2038 tAVRC_RESPONSE avrc_response = {0};
2039 tBTA_AV_META_MSG meta_msg;
2041 p_context = (btif_rc_timer_context_t *)data;
2042 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2043 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2045 switch (p_context->rc_status_cmd.pdu_id) {
2046 case AVRC_PDU_REGISTER_NOTIFICATION:
2047 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2050 case AVRC_PDU_GET_CAPABILITIES:
2051 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2052 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2055 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2056 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2057 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2060 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2061 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2062 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2065 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2066 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2067 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2070 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2071 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2072 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2075 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2076 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2077 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2080 case AVRC_PDU_GET_ELEMENT_ATTR:
2081 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2082 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2085 case AVRC_PDU_GET_PLAY_STATUS:
2086 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2087 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2090 release_transaction(p_context->rc_status_cmd.label);
2093 /***************************************************************************
2095 ** Function btif_rc_status_cmd_timer_timeout
2097 ** Description RC status command timeout callback.
2098 ** This is called from BTU context and switches to BTIF
2099 ** context to handle the timeout events
2102 ***************************************************************************/
2103 static void btif_rc_status_cmd_timer_timeout(void *data)
2105 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2107 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2108 (char *)p_data, sizeof(btif_rc_timer_context_t),
2112 /***************************************************************************
2114 ** Function btif_rc_control_cmd_timeout_handler
2116 ** Description RC control command timeout handler (Runs in BTIF context).
2119 ***************************************************************************/
2120 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2123 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2124 tAVRC_RESPONSE avrc_response = {0};
2125 tBTA_AV_META_MSG meta_msg;
2127 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2128 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2130 switch (p_context->rc_control_cmd.pdu_id) {
2131 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2132 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2133 handle_set_app_attr_val_response(&meta_msg,
2134 &avrc_response.set_app_val);
2137 release_transaction(p_context->rc_control_cmd.label);
2140 /***************************************************************************
2142 ** Function btif_rc_control_cmd_timer_timeout
2144 ** Description RC control command timeout callback.
2145 ** This is called from BTU context and switches to BTIF
2146 ** context to handle the timeout events
2149 ***************************************************************************/
2150 static void btif_rc_control_cmd_timer_timeout(void *data)
2152 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2154 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2155 (char *)p_data, sizeof(btif_rc_timer_context_t),
2159 /***************************************************************************
2161 ** Function btif_rc_play_status_timeout_handler
2163 ** Description RC play status timeout handler (Runs in BTIF context).
2166 ***************************************************************************/
2167 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2168 UNUSED_ATTR char *p_data)
2170 get_play_status_cmd();
2171 rc_start_play_status_timer();
2174 /***************************************************************************
2176 ** Function btif_rc_play_status_timer_timeout
2178 ** Description RC play status timeout callback.
2179 ** This is called from BTU context and switches to BTIF
2180 ** context to handle the timeout events
2183 ***************************************************************************/
2184 static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2186 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
2189 /***************************************************************************
2191 ** Function rc_start_play_status_timer
2193 ** Description Helper function to start the timer to fetch play status.
2196 ***************************************************************************/
2197 static void rc_start_play_status_timer(void)
2199 /* Start the Play status timer only if it is not started */
2200 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2201 if (btif_rc_cb.rc_play_status_timer == NULL) {
2202 btif_rc_cb.rc_play_status_timer =
2203 alarm_new("btif_rc.rc_play_status_timer");
2205 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2206 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2207 btif_rc_play_status_timer_timeout, NULL,
2208 btu_general_alarm_queue);
2212 /***************************************************************************
2214 ** Function rc_stop_play_status_timer
2216 ** Description Helper function to stop the play status timer.
2219 ***************************************************************************/
2220 void rc_stop_play_status_timer()
2222 if (btif_rc_cb.rc_play_status_timer != NULL)
2223 alarm_cancel(btif_rc_cb.rc_play_status_timer);
2226 /***************************************************************************
2228 ** Function register_for_event_notification
2230 ** Description Helper function registering notification events
2231 ** sets an interim response timeout to handle if the remote
2232 ** does not respond.
2235 ***************************************************************************/
2236 static void register_for_event_notification(btif_rc_supported_event_t *p_event)
2239 rc_transaction_t *p_transaction;
2241 status = get_transaction(&p_transaction);
2242 if (status == BT_STATUS_SUCCESS)
2244 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
2246 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2247 if (status != BT_STATUS_SUCCESS)
2249 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2250 __FUNCTION__, status);
2251 release_transaction (p_transaction->lbl);
2254 p_event->label = p_transaction->lbl;
2255 p_event->status = eREGISTERED;
2256 p_context->rc_status_cmd.label = p_transaction->lbl;
2257 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2259 alarm_free(p_transaction->txn_timer);
2260 p_transaction->txn_timer =
2261 alarm_new("btif_rc.status_command_txn_timer");
2262 alarm_set_on_queue(p_transaction->txn_timer,
2263 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2264 btif_rc_status_cmd_timer_timeout, p_context,
2265 btu_general_alarm_queue);
2269 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2270 __FUNCTION__, status);
2274 static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2276 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2277 p_context->rc_status_cmd.label = p_txn->lbl;
2278 p_context->rc_status_cmd.pdu_id = pdu_id;
2280 alarm_free(p_txn->txn_timer);
2281 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2282 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2283 btif_rc_status_cmd_timer_timeout, p_context,
2284 btu_general_alarm_queue);
2287 static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2289 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2290 p_context->rc_control_cmd.label = p_txn->lbl;
2291 p_context->rc_control_cmd.pdu_id = pdu_id;
2293 alarm_free(p_txn->txn_timer);
2294 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2295 alarm_set_on_queue(p_txn->txn_timer,
2296 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2297 btif_rc_control_cmd_timer_timeout, p_context,
2298 btu_general_alarm_queue);
2301 /***************************************************************************
2303 ** Function handle_get_capability_response
2305 ** Description Handles the get_cap_response to populate company id info
2306 ** and query the supported events.
2307 ** Initiates Notification registration for events supported
2310 ***************************************************************************/
2311 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2315 /* Todo: Do we need to retry on command timeout */
2316 if (p_rsp->status != AVRC_STS_NO_ERROR)
2318 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2319 __FUNCTION__, p_rsp->status);
2323 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2325 btif_rc_supported_event_t *p_event;
2327 /* Todo: Check if list can be active when we hit here */
2328 btif_rc_cb.rc_supported_event_list = list_new(osi_freebuf);
2329 for (xx = 0; xx < p_rsp->count; xx++)
2331 /* Skip registering for Play position change notification */
2332 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2333 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2334 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2336 p_event = (btif_rc_supported_event_t *)osi_getbuf(sizeof(btif_rc_supported_event_t));
2337 p_event->event_id = p_rsp->param.event_id[xx];
2338 p_event->status = eNOT_REGISTERED;
2339 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2342 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2343 if (p_event != NULL)
2345 register_for_event_notification(p_event);
2348 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2350 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2351 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2352 for (xx = 0; xx < p_rsp->count; xx++)
2354 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2359 bool rc_is_track_id_valid (tAVRC_UID uid)
2361 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2363 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2373 /***************************************************************************
2375 ** Function handle_notification_response
2377 ** Description Main handler for notification responses to registered events
2378 ** 1. Register for unregistered event(in interim response path)
2379 ** 2. After registering for all supported events, start
2380 ** retrieving application settings and values
2381 ** 3. Reregister for events on getting changed response
2382 ** 4. Run play status timer for getting position when the
2383 ** status changes to playing
2384 ** 5. Get the Media details when the track change happens
2385 ** or track change interim response is received with
2387 ** 6. HAL callback for play status change and application
2391 ***************************************************************************/
2392 static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2394 bt_bdaddr_t rc_addr;
2395 UINT32 attr_list[] = {
2396 AVRC_MEDIA_ATTR_ID_TITLE,
2397 AVRC_MEDIA_ATTR_ID_ARTIST,
2398 AVRC_MEDIA_ATTR_ID_ALBUM,
2399 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2400 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2401 AVRC_MEDIA_ATTR_ID_GENRE,
2402 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2406 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2408 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2410 btif_rc_supported_event_t *p_event;
2413 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2414 switch (p_rsp->event_id)
2416 case AVRC_EVT_PLAY_STATUS_CHANGE:
2417 /* Start timer to get play status periodically
2418 * if the play state is playing.
2420 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2422 rc_start_play_status_timer();
2424 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2425 &rc_addr, p_rsp->param.play_status);
2428 case AVRC_EVT_TRACK_CHANGE:
2429 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2435 UINT8 *p_data = p_rsp->param.track;
2436 /* Update the UID for current track
2437 * Attributes will be fetched after the AVRCP procedure
2439 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2443 case AVRC_EVT_APP_SETTING_CHANGE:
2446 case AVRC_EVT_NOW_PLAYING_CHANGE:
2449 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2452 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2455 case AVRC_EVT_UIDS_CHANGE:
2458 case AVRC_EVT_TRACK_REACHED_END:
2459 case AVRC_EVT_TRACK_REACHED_START:
2460 case AVRC_EVT_PLAY_POS_CHANGED:
2461 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2462 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2464 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2468 list_foreach(btif_rc_cb.rc_supported_event_list,
2469 iterate_supported_event_list_for_interim_rsp,
2472 node = list_begin(btif_rc_cb.rc_supported_event_list);
2473 while (node != NULL)
2475 p_event = (btif_rc_supported_event_t *)list_node(node);
2476 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2478 register_for_event_notification(p_event);
2481 node = list_next (node);
2484 /* Registered for all events, we can request application settings */
2485 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2487 /* we need to do this only if remote TG supports
2488 * player application settings
2490 btif_rc_cb.rc_app_settings.query_started = TRUE;
2491 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2493 list_player_app_setting_attrib_cmd();
2497 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2498 rc_ctrl_procedure_complete();
2502 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2504 btif_rc_supported_event_t *p_event;
2507 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2510 node = list_begin(btif_rc_cb.rc_supported_event_list);
2511 while (node != NULL)
2513 p_event = (btif_rc_supported_event_t *)list_node(node);
2514 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2516 p_event->status = eNOT_REGISTERED;
2517 register_for_event_notification(p_event);
2520 node = list_next (node);
2523 switch (p_rsp->event_id)
2525 case AVRC_EVT_PLAY_STATUS_CHANGE:
2526 /* Start timer to get play status periodically
2527 * if the play state is playing.
2529 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2531 rc_start_play_status_timer();
2535 rc_stop_play_status_timer();
2537 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2538 &rc_addr, p_rsp->param.play_status);
2541 case AVRC_EVT_TRACK_CHANGE:
2542 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2546 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2549 case AVRC_EVT_APP_SETTING_CHANGE:
2551 btrc_player_settings_t app_settings;
2554 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2555 for (xx = 0; xx < app_settings.num_attr; xx++)
2557 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2558 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2560 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2561 &rc_addr, &app_settings);
2565 case AVRC_EVT_NOW_PLAYING_CHANGE:
2568 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2571 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2574 case AVRC_EVT_UIDS_CHANGE:
2577 case AVRC_EVT_TRACK_REACHED_END:
2578 case AVRC_EVT_TRACK_REACHED_START:
2579 case AVRC_EVT_PLAY_POS_CHANGED:
2580 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2581 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2583 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2584 __FUNCTION__, p_rsp->event_id);
2590 /***************************************************************************
2592 ** Function handle_app_attr_response
2594 ** Description handles the the application attributes response and
2595 ** initiates procedure to fetch the attribute values
2598 ***************************************************************************/
2599 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2603 if (p_rsp->status != AVRC_STS_NO_ERROR)
2605 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2606 __FUNCTION__, p_rsp->status);
2607 rc_ctrl_procedure_complete();
2611 for (xx = 0; xx < p_rsp->num_attr; xx++)
2615 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2617 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2618 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2619 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2623 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2624 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2625 btif_rc_cb.rc_app_settings.num_attrs++;
2628 btif_rc_cb.rc_app_settings.attr_index = 0;
2629 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2630 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2631 if (p_rsp->num_attr)
2633 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2637 BTIF_TRACE_ERROR("%s No Player application settings found",
2642 /***************************************************************************
2644 ** Function handle_app_val_response
2646 ** Description handles the the attributes value response and if extended
2647 ** menu is available, it initiates query for the attribute
2648 ** text. If not, it initiates procedure to get the current
2649 ** attribute values and calls the HAL callback for provding
2650 ** application settings information.
2653 ***************************************************************************/
2654 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2656 UINT8 xx, attr_index;
2657 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2658 btif_rc_player_app_settings_t *p_app_settings;
2659 bt_bdaddr_t rc_addr;
2661 /* Todo: Do we need to retry on command timeout */
2662 if (p_rsp->status != AVRC_STS_NO_ERROR)
2664 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2665 __FUNCTION__, p_rsp->status);
2669 p_app_settings = &btif_rc_cb.rc_app_settings;
2670 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2672 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2674 attr_index = p_app_settings->attr_index;
2675 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2676 for (xx = 0; xx < p_rsp->num_val; xx++)
2678 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2681 p_app_settings->attr_index++;
2682 if (attr_index < p_app_settings->num_attrs)
2684 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2686 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2689 p_app_settings->ext_attr_index = 0;
2690 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2694 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2696 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2698 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2699 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2700 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2703 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2705 attr_index = p_app_settings->ext_attr_index;
2706 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2707 for (xx = 0; xx < p_rsp->num_val; xx++)
2709 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2712 p_app_settings->ext_attr_index++;
2713 if (attr_index < p_app_settings->num_ext_attrs)
2715 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2719 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2722 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2724 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2726 get_player_app_setting_attr_text_cmd(attr, xx);
2731 /***************************************************************************
2733 ** Function handle_app_cur_val_response
2735 ** Description handles the the get attributes value response.
2739 ***************************************************************************/
2740 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2742 btrc_player_settings_t app_settings;
2743 bt_bdaddr_t rc_addr;
2746 /* Todo: Do we need to retry on command timeout */
2747 if (p_rsp->status != AVRC_STS_NO_ERROR)
2749 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2750 __FUNCTION__, p_rsp->status);
2754 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2756 app_settings.num_attr = p_rsp->num_val;
2757 for (xx = 0; xx < app_settings.num_attr; xx++)
2759 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2760 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2762 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2763 &rc_addr, &app_settings);
2764 /* Application settings are fetched only once for initial values
2765 * initiate anything that follows after RC procedure.
2766 * Defer it if browsing is supported till players query
2768 rc_ctrl_procedure_complete ();
2769 osi_freebuf_and_reset((void **)&p_rsp->p_vals);
2772 /***************************************************************************
2774 ** Function handle_app_attr_txt_response
2776 ** Description handles the the get attributes text response, if fails
2777 ** calls HAL callback with just normal settings and initiates
2778 ** query for current settings else initiates query for value text
2781 ***************************************************************************/
2782 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2785 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2786 btif_rc_player_app_settings_t *p_app_settings;
2787 bt_bdaddr_t rc_addr;
2789 p_app_settings = &btif_rc_cb.rc_app_settings;
2790 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2792 /* Todo: Do we need to retry on command timeout */
2793 if (p_rsp->status != AVRC_STS_NO_ERROR)
2795 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2797 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2798 __FUNCTION__, p_rsp->status);
2799 /* Not able to fetch Text for extended Menu, skip the process
2800 * and cleanup used memory. Proceed to get the current settings
2801 * for standard attributes.
2803 p_app_settings->num_ext_attrs = 0;
2804 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2805 osi_freebuf_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2806 p_app_settings->ext_attr_index = 0;
2808 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2810 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2812 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2813 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2815 get_player_app_setting_cmd (xx, attrs);
2819 for (xx = 0; xx < p_rsp->num_attr; xx++)
2822 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2824 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2826 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2827 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2828 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2834 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2836 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2838 get_player_app_setting_value_text_cmd(vals, xx);
2842 /***************************************************************************
2844 ** Function handle_app_attr_val_txt_response
2846 ** Description handles the the get attributes value text response, if fails
2847 ** calls HAL callback with just normal settings and initiates
2848 ** query for current settings
2851 ***************************************************************************/
2852 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2854 UINT8 xx, attr_index;
2855 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2856 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2857 btif_rc_player_app_settings_t *p_app_settings;
2858 bt_bdaddr_t rc_addr;
2860 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2861 p_app_settings = &btif_rc_cb.rc_app_settings;
2863 /* Todo: Do we need to retry on command timeout */
2864 if (p_rsp->status != AVRC_STS_NO_ERROR)
2866 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2868 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2869 __FUNCTION__, p_rsp->status);
2871 /* Not able to fetch Text for extended Menu, skip the process
2872 * and cleanup used memory. Proceed to get the current settings
2873 * for standard attributes.
2875 p_app_settings->num_ext_attrs = 0;
2876 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2879 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2881 for (x = 0; x < p_ext_attr->num_val; x++)
2882 osi_freebuf_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2883 p_ext_attr->num_val = 0;
2884 osi_freebuf_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2886 p_app_settings->ext_attr_index = 0;
2888 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2890 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2892 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2893 p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
2895 get_player_app_setting_cmd (xx, attrs);
2899 for (xx = 0; xx < p_rsp->num_attr; xx++)
2902 btrc_player_app_ext_attr_t *p_ext_attr;
2903 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2904 for (x = 0; x < p_rsp->num_attr; x++)
2906 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2908 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2909 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2910 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2915 p_app_settings->ext_val_index++;
2917 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2919 attr_index = p_app_settings->ext_val_index;
2920 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2922 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2924 get_player_app_setting_value_text_cmd(vals, xx);
2930 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2932 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2934 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2936 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2938 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2939 p_app_settings->num_attrs, &p_app_settings->attrs,
2940 p_app_settings->num_ext_attrs, &p_app_settings->ext_attrs);
2941 get_player_app_setting_cmd (xx + x, attrs);
2943 /* Free the application settings information after sending to
2946 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2949 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2951 for (x = 0; x < p_ext_attr->num_val; x++)
2952 osi_freebuf_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2953 p_ext_attr->num_val = 0;
2954 osi_freebuf_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2956 p_app_settings->num_attrs = 0;
2960 /***************************************************************************
2962 ** Function handle_set_app_attr_val_response
2964 ** Description handles the the set attributes value response, if fails
2965 ** calls HAL callback to indicate the failure
2968 ***************************************************************************/
2969 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2971 uint8_t accepted = 0;
2972 bt_bdaddr_t rc_addr;
2974 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2976 /* For timeout pmeta_msg will be NULL, else we need to
2977 * check if this is accepted by TG
2979 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2983 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2986 /***************************************************************************
2988 ** Function handle_get_elem_attr_response
2990 ** Description handles the the element attributes response, calls
2991 ** HAL callback to update track change information.
2994 ***************************************************************************/
2995 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
2997 btrc_element_attr_val_t *p_attr;
2998 bt_bdaddr_t rc_addr;
3001 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3003 if (p_rsp->status == AVRC_STS_NO_ERROR)
3005 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
3006 p_attr = (btrc_element_attr_val_t *)osi_getbuf(buf_size);
3007 memset(p_attr, 0, buf_size);
3008 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3009 p_attr[xx].attr_id = p_rsp->p_attrs[xx].attr_id;
3010 /* Todo. Legth limit check to include null */
3011 if (p_rsp->p_attrs[xx].name.str_len &&
3012 p_rsp->p_attrs[xx].name.p_str) {
3013 memcpy(p_attr[xx].text, p_rsp->p_attrs[xx].name.p_str,
3014 p_rsp->p_attrs[xx].name.str_len);
3015 osi_freebuf_and_reset((void **)&p_rsp->p_attrs[xx].name.p_str);
3018 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3019 &rc_addr, p_rsp->num_attr, p_attr);
3020 osi_freebuf(p_attr);
3022 else if (p_rsp->status == BTIF_RC_STS_TIMEOUT)
3024 /* Retry for timeout case, this covers error handling
3025 * for continuation failure also.
3027 UINT32 attr_list[] = {
3028 AVRC_MEDIA_ATTR_ID_TITLE,
3029 AVRC_MEDIA_ATTR_ID_ARTIST,
3030 AVRC_MEDIA_ATTR_ID_ALBUM,
3031 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3032 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3033 AVRC_MEDIA_ATTR_ID_GENRE,
3034 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3036 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
3040 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
3041 __FUNCTION__, p_rsp->status);
3045 /***************************************************************************
3047 ** Function handle_get_playstatus_response
3049 ** Description handles the the play status response, calls
3050 ** HAL callback to update play position.
3053 ***************************************************************************/
3054 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3056 bt_bdaddr_t rc_addr;
3058 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3060 if (p_rsp->status == AVRC_STS_NO_ERROR)
3062 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3063 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3067 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3068 __FUNCTION__, p_rsp->status);
3072 /***************************************************************************
3074 ** Function clear_cmd_timeout
3076 ** Description helper function to stop the command timeout timer
3079 ***************************************************************************/
3080 static void clear_cmd_timeout (UINT8 label)
3082 rc_transaction_t *p_txn;
3084 p_txn = get_transaction_by_lbl (label);
3087 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3091 if (p_txn->txn_timer != NULL)
3092 alarm_cancel(p_txn->txn_timer);
3095 /***************************************************************************
3097 ** Function handle_avk_rc_metamsg_rsp
3099 ** Description Handle RC metamessage response
3103 ***************************************************************************/
3104 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3106 tAVRC_RESPONSE avrc_response = {0};
3107 UINT8 scratch_buf[512] = {0};// this variable is unused
3111 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3112 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3114 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3115 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3116 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3118 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3119 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3120 __FUNCTION__, status, avrc_response.pdu,
3121 pmeta_msg->p_msg->vendor.hdr.ctype);
3123 switch (avrc_response.pdu)
3125 case AVRC_PDU_REGISTER_NOTIFICATION:
3126 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3127 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3129 /* Don't free the transaction Id */
3130 clear_cmd_timeout (pmeta_msg->label);
3135 case AVRC_PDU_GET_CAPABILITIES:
3136 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3139 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3140 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3143 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3144 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3147 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3148 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3151 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3152 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3155 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3156 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3159 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3160 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3163 case AVRC_PDU_GET_ELEMENT_ATTR:
3164 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3167 case AVRC_PDU_GET_PLAY_STATUS:
3168 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3171 release_transaction(pmeta_msg->label);
3175 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3176 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3181 /***************************************************************************
3183 ** Function handle_avk_rc_metamsg_cmd
3185 ** Description Handle RC metamessage response
3189 ***************************************************************************/
3190 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3192 tAVRC_COMMAND avrc_cmd = {0};
3193 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3194 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3195 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3196 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3197 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3199 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3200 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3201 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3203 if (status != AVRC_STS_NO_ERROR)
3206 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3207 __FUNCTION__, status);
3208 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3212 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3214 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3215 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3216 __FUNCTION__, dump_rc_notification_event_id(event_id));
3218 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3220 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3222 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3227 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3228 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3234 /***************************************************************************
3238 ** Description Closes the AVRC interface
3242 ***************************************************************************/
3243 static void cleanup()
3245 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3247 if (bt_rc_callbacks)
3249 bt_rc_callbacks = NULL;
3251 alarm_free(btif_rc_cb.rc_play_status_timer);
3252 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3254 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3257 /***************************************************************************
3259 ** Function cleanup_ctrl
3261 ** Description Closes the AVRC Controller interface
3265 ***************************************************************************/
3266 static void cleanup_ctrl()
3268 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3270 if (bt_rc_ctrl_callbacks)
3272 bt_rc_ctrl_callbacks = NULL;
3274 alarm_free(btif_rc_cb.rc_play_status_timer);
3275 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3277 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3280 /***************************************************************************
3282 ** Function getcapabilities_cmd
3284 ** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3288 ***************************************************************************/
3289 static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3291 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3292 rc_transaction_t *p_transaction = NULL;
3293 #if (AVRC_CTLR_INCLUDED == TRUE)
3294 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3296 bt_status_t tran_status=get_transaction(&p_transaction);
3297 if (BT_STATUS_SUCCESS != tran_status)
3298 return BT_STATUS_FAIL;
3300 tAVRC_COMMAND avrc_cmd = {0};
3301 BT_HDR *p_msg = NULL;
3302 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3303 avrc_cmd.get_caps.capability_id = cap_id;
3304 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3305 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3306 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3307 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3309 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3310 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3311 __FUNCTION__,p_transaction->lbl);
3312 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3313 data_start, p_msg->len);
3314 status = BT_STATUS_SUCCESS;
3315 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3319 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3320 __FUNCTION__, status);
3324 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3329 /***************************************************************************
3331 ** Function list_player_app_setting_attrib_cmd
3333 ** Description Get supported List Player Attributes
3337 ***************************************************************************/
3338 static bt_status_t list_player_app_setting_attrib_cmd(void)
3340 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3341 rc_transaction_t *p_transaction = NULL;
3342 #if (AVRC_CTLR_INCLUDED == TRUE)
3343 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3345 bt_status_t tran_status=get_transaction(&p_transaction);
3346 if (BT_STATUS_SUCCESS != tran_status)
3347 return BT_STATUS_FAIL;
3349 tAVRC_COMMAND avrc_cmd = {0};
3350 BT_HDR *p_msg = NULL;
3351 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3352 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3353 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3354 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3355 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3357 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3358 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3359 __FUNCTION__,p_transaction->lbl);
3360 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3361 data_start, p_msg->len);
3362 status = BT_STATUS_SUCCESS;
3363 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3368 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3369 __FUNCTION__, status);
3373 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3378 /***************************************************************************
3380 ** Function list_player_app_setting_value_cmd
3382 ** Description Get values of supported Player Attributes
3386 ***************************************************************************/
3387 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3389 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3390 rc_transaction_t *p_transaction=NULL;
3391 #if (AVRC_CTLR_INCLUDED == TRUE)
3392 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3394 bt_status_t tran_status=get_transaction(&p_transaction);
3395 if (BT_STATUS_SUCCESS != tran_status)
3396 return BT_STATUS_FAIL;
3398 tAVRC_COMMAND avrc_cmd = {0};
3399 BT_HDR *p_msg = NULL;
3400 avrc_cmd.list_app_values.attr_id = attrib_id;
3401 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3402 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3403 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3404 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3405 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3407 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3408 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3409 __FUNCTION__,p_transaction->lbl);
3410 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3411 data_start, p_msg->len);
3412 status = BT_STATUS_SUCCESS;
3413 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3417 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3421 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3426 /***************************************************************************
3428 ** Function get_player_app_setting_cmd
3430 ** Description Get current values of Player Attributes
3434 ***************************************************************************/
3435 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3437 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3438 rc_transaction_t *p_transaction = NULL;
3440 #if (AVRC_CTLR_INCLUDED == TRUE)
3441 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3443 bt_status_t tran_status=get_transaction(&p_transaction);
3444 if (BT_STATUS_SUCCESS != tran_status)
3445 return BT_STATUS_FAIL;
3447 tAVRC_COMMAND avrc_cmd = {0};
3448 BT_HDR *p_msg = NULL;
3449 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3450 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3451 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3452 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3454 for (count = 0; count < num_attrib; count++)
3456 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3458 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3459 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3461 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3462 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3463 __FUNCTION__,p_transaction->lbl);
3464 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3465 data_start, p_msg->len);
3466 status = BT_STATUS_SUCCESS;
3467 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3471 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3472 __FUNCTION__, status);
3476 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3481 /***************************************************************************
3483 ** Function change_player_app_setting
3485 ** Description Set current values of Player Attributes
3489 ***************************************************************************/
3490 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)
3492 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3493 rc_transaction_t *p_transaction = NULL;
3495 #if (AVRC_CTLR_INCLUDED == TRUE)
3496 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3498 bt_status_t tran_status=get_transaction(&p_transaction);
3499 if (BT_STATUS_SUCCESS != tran_status)
3500 return BT_STATUS_FAIL;
3502 tAVRC_COMMAND avrc_cmd = {0};
3503 BT_HDR *p_msg = NULL;
3504 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3505 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3506 avrc_cmd.set_app_val.num_val = num_attrib;
3507 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3508 avrc_cmd.set_app_val.p_vals =
3509 (tAVRC_APP_SETTING *)osi_getbuf(sizeof(tAVRC_APP_SETTING) * num_attrib);
3510 for (count = 0; count < num_attrib; count++)
3512 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3513 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3515 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3516 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3518 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3519 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3520 __FUNCTION__,p_transaction->lbl);
3521 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3522 data_start, p_msg->len);
3523 status = BT_STATUS_SUCCESS;
3524 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3528 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3529 __FUNCTION__, status);
3532 osi_freebuf_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
3534 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3539 /***************************************************************************
3541 ** Function get_player_app_setting_attr_text_cmd
3543 ** Description Get text description for app attribute
3547 ***************************************************************************/
3548 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3550 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3551 rc_transaction_t *p_transaction = NULL;
3553 #if (AVRC_CTLR_INCLUDED == TRUE)
3554 tAVRC_COMMAND avrc_cmd = {0};
3555 BT_HDR *p_msg = NULL;
3556 bt_status_t tran_status;
3559 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3561 tran_status = get_transaction(&p_transaction);
3562 if (BT_STATUS_SUCCESS != tran_status)
3563 return BT_STATUS_FAIL;
3565 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3566 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3567 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3569 for (count = 0; count < num_attrs; count++)
3571 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3573 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3574 if (status == AVRC_STS_NO_ERROR)
3576 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3577 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3578 __FUNCTION__, p_transaction->lbl);
3579 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3580 AVRC_CMD_STATUS, data_start, p_msg->len);
3582 status = BT_STATUS_SUCCESS;
3583 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3587 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3591 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3596 /***************************************************************************
3598 ** Function get_player_app_setting_val_text_cmd
3600 ** Description Get text description for app attribute values
3604 ***************************************************************************/
3605 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3607 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3608 rc_transaction_t *p_transaction = NULL;
3610 #if (AVRC_CTLR_INCLUDED == TRUE)
3611 tAVRC_COMMAND avrc_cmd = {0};
3612 BT_HDR *p_msg = NULL;
3613 bt_status_t tran_status;
3616 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3618 tran_status = get_transaction(&p_transaction);
3619 if (BT_STATUS_SUCCESS != tran_status)
3620 return BT_STATUS_FAIL;
3622 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3623 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3624 avrc_cmd.get_app_val_txt.num_val = num_vals;
3626 for (count = 0; count < num_vals; count++)
3628 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3630 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3631 if (status == AVRC_STS_NO_ERROR)
3633 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3634 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3635 __FUNCTION__, p_transaction->lbl);
3638 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3639 AVRC_CMD_STATUS, data_start, p_msg->len);
3640 status = BT_STATUS_SUCCESS;
3641 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3646 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3647 __FUNCTION__, status);
3651 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3656 /***************************************************************************
3658 ** Function register_notification_cmd
3660 ** Description Send Command to register for a Notification ID
3664 ***************************************************************************/
3665 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3668 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3669 #if (AVRC_CTLR_INCLUDED == TRUE)
3670 tAVRC_COMMAND avrc_cmd = {0};
3671 BT_HDR *p_msg = NULL;
3675 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3677 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3678 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3679 avrc_cmd.reg_notif.event_id = event_id;
3680 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3681 avrc_cmd.reg_notif.param = event_value;
3682 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3683 if (status == AVRC_STS_NO_ERROR)
3685 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3686 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3687 __FUNCTION__, label);
3690 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3691 data_start, p_msg->len);
3692 status = BT_STATUS_SUCCESS;
3697 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3698 __FUNCTION__, status);
3702 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3707 /***************************************************************************
3709 ** Function get_element_attribute_cmd
3711 ** Description Get Element Attribute for attributeIds
3715 ***************************************************************************/
3716 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3718 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3719 rc_transaction_t *p_transaction=NULL;
3721 #if (AVRC_CTLR_INCLUDED == TRUE)
3722 tAVRC_COMMAND avrc_cmd = {0};
3723 BT_HDR *p_msg = NULL;
3724 bt_status_t tran_status;
3727 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3728 __FUNCTION__, num_attribute, p_attr_ids[0]);
3730 tran_status = get_transaction(&p_transaction);
3731 if (BT_STATUS_SUCCESS != tran_status)
3732 return BT_STATUS_FAIL;
3734 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3735 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3736 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3737 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3738 for (count = 0; count < num_attribute; count++)
3740 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3743 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3744 if (status == AVRC_STS_NO_ERROR)
3746 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3747 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3748 __FUNCTION__, p_transaction->lbl);
3751 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3752 AVRC_CMD_STATUS, data_start, p_msg->len);
3753 status = BT_STATUS_SUCCESS;
3754 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3760 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3761 __FUNCTION__, status);
3765 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3770 /***************************************************************************
3772 ** Function get_play_status_cmd
3774 ** Description Get Element Attribute for attributeIds
3778 ***************************************************************************/
3779 static bt_status_t get_play_status_cmd(void)
3781 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3782 rc_transaction_t *p_transaction = NULL;
3783 #if (AVRC_CTLR_INCLUDED == TRUE)
3784 tAVRC_COMMAND avrc_cmd = {0};
3785 BT_HDR *p_msg = NULL;
3786 bt_status_t tran_status;
3789 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3790 tran_status = get_transaction(&p_transaction);
3791 if (BT_STATUS_SUCCESS != tran_status)
3792 return BT_STATUS_FAIL;
3794 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3795 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3796 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3797 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3798 if (status == AVRC_STS_NO_ERROR)
3800 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3801 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3802 __FUNCTION__, p_transaction->lbl);
3805 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3806 AVRC_CMD_STATUS, data_start, p_msg->len);
3807 status = BT_STATUS_SUCCESS;
3808 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3813 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3814 __FUNCTION__, status);
3818 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3824 /***************************************************************************
3826 ** Function set_volume_rsp
3828 ** Description Rsp for SetAbsoluteVolume Command
3832 ***************************************************************************/
3833 static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3835 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3836 #if (AVRC_CTLR_INCLUDED == TRUE)
3837 tAVRC_RESPONSE avrc_rsp;
3838 BT_HDR *p_msg = NULL;
3841 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3843 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3844 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3845 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3846 avrc_rsp.volume.volume = abs_vol;
3847 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3848 if (status == AVRC_STS_NO_ERROR)
3850 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3851 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3852 __FUNCTION__, btif_rc_cb.rc_vol_label);
3855 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3856 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3857 status = BT_STATUS_SUCCESS;
3862 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3863 __FUNCTION__, status);
3867 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3872 /***************************************************************************
3874 ** Function send_register_abs_vol_rsp
3876 ** Description Rsp for Notification of Absolute Volume
3880 ***************************************************************************/
3881 static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3882 uint8_t abs_vol, uint8_t label)
3884 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3885 tAVRC_RESPONSE avrc_rsp;
3886 BT_HDR *p_msg = NULL;
3887 #if (AVRC_CTLR_INCLUDED == TRUE)
3888 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
3891 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3892 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3893 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3894 avrc_rsp.reg_notif.param.volume = abs_vol;
3895 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
3897 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3898 if (status == AVRC_STS_NO_ERROR) {
3899 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3901 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3902 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3903 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3904 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3905 data_start, p_msg->len, 0);
3906 status = BT_STATUS_SUCCESS;
3908 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3914 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
3919 /***************************************************************************
3921 ** Function send_groupnavigation_cmd
3923 ** Description Send Pass-Through command
3927 ***************************************************************************/
3928 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3931 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3932 #if (AVRC_CTLR_INCLUDED == TRUE)
3933 rc_transaction_t *p_transaction=NULL;
3934 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3935 key_code, key_state);
3937 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3939 bt_status_t tran_status = get_transaction(&p_transaction);
3940 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
3941 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3942 UINT8* start = buffer;
3943 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3945 UINT8_TO_BE_STREAM(start, key_code);
3946 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3948 (tBTA_AV_STATE)key_state, buffer,
3949 AVRC_PASS_THRU_GROUP_LEN);
3950 status = BT_STATUS_SUCCESS;
3951 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3956 status = BT_STATUS_FAIL;
3957 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3962 status = BT_STATUS_FAIL;
3963 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3966 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3971 /***************************************************************************
3973 ** Function send_passthrough_cmd
3975 ** Description Send Pass-Through command
3979 ***************************************************************************/
3980 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3982 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3983 #if (AVRC_CTLR_INCLUDED == TRUE)
3985 rc_transaction_t *p_transaction=NULL;
3986 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3987 key_code, key_state);
3988 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3990 bt_status_t tran_status = get_transaction(&p_transaction);
3991 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
3993 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3994 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
3995 status = BT_STATUS_SUCCESS;
3996 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
4000 status = BT_STATUS_FAIL;
4001 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
4006 status = BT_STATUS_FAIL;
4007 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
4010 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
4015 static const btrc_interface_t bt_rc_interface = {
4016 sizeof(bt_rc_interface),
4018 get_play_status_rsp,
4019 NULL, /* list_player_app_attr_rsp */
4020 NULL, /* list_player_app_value_rsp */
4021 NULL, /* get_player_app_value_rsp */
4022 NULL, /* get_player_app_attr_text_rsp */
4023 NULL, /* get_player_app_value_text_rsp */
4024 get_element_attr_rsp,
4025 NULL, /* set_player_app_value_rsp */
4026 register_notification_rsp,
4031 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4032 sizeof(bt_rc_ctrl_interface),
4034 send_passthrough_cmd,
4035 send_groupnavigation_cmd,
4036 change_player_app_setting,
4038 volume_change_notification_rsp,
4042 /*******************************************************************************
4044 ** Function btif_rc_get_interface
4046 ** Description Get the AVRCP Target callback interface
4048 ** Returns btav_interface_t
4050 *******************************************************************************/
4051 const btrc_interface_t *btif_rc_get_interface(void)
4053 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4054 return &bt_rc_interface;
4057 /*******************************************************************************
4059 ** Function btif_rc_ctrl_get_interface
4061 ** Description Get the AVRCP Controller callback interface
4063 ** Returns btav_interface_t
4065 *******************************************************************************/
4066 const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4068 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4069 return &bt_rc_ctrl_interface;
4072 /*******************************************************************************
4073 ** Function initialize_transaction
4075 ** Description Initializes fields of the transaction structure
4078 *******************************************************************************/
4079 static void initialize_transaction(int lbl)
4081 pthread_mutex_lock(&device.lbllock);
4082 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4083 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4084 clear_cmd_timeout(lbl);
4086 device.transaction[lbl].lbl = lbl;
4087 device.transaction[lbl].in_use=FALSE;
4088 device.transaction[lbl].handle=0;
4090 pthread_mutex_unlock(&device.lbllock);
4093 /*******************************************************************************
4094 ** Function lbl_init
4096 ** Description Initializes label structures and mutexes.
4099 *******************************************************************************/
4102 memset(&device,0,sizeof(rc_device_t));
4103 pthread_mutexattr_t attr;
4104 pthread_mutexattr_init(&attr);
4105 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4106 pthread_mutex_init(&(device.lbllock), &attr);
4107 pthread_mutexattr_destroy(&attr);
4108 init_all_transactions();
4111 /*******************************************************************************
4113 ** Function init_all_transactions
4115 ** Description Initializes all transactions
4118 *******************************************************************************/
4119 void init_all_transactions()
4122 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4124 initialize_transaction(txn_indx);
4128 /*******************************************************************************
4130 ** Function get_transaction_by_lbl
4132 ** Description Will return a transaction based on the label. If not inuse
4133 ** will return an error.
4135 ** Returns bt_status_t
4136 *******************************************************************************/
4137 rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4139 rc_transaction_t *transaction = NULL;
4140 pthread_mutex_lock(&device.lbllock);
4142 /* Determine if this is a valid label */
4143 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4145 if (FALSE==device.transaction[lbl].in_use)
4151 transaction = &(device.transaction[lbl]);
4152 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
4156 pthread_mutex_unlock(&device.lbllock);
4160 /*******************************************************************************
4162 ** Function get_transaction
4164 ** Description Obtains the transaction details.
4166 ** Returns bt_status_t
4167 *******************************************************************************/
4169 bt_status_t get_transaction(rc_transaction_t **ptransaction)
4171 bt_status_t result = BT_STATUS_NOMEM;
4173 pthread_mutex_lock(&device.lbllock);
4175 // Check for unused transactions
4176 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4178 if (FALSE==device.transaction[i].in_use)
4180 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
4181 device.transaction[i].in_use = TRUE;
4182 *ptransaction = &(device.transaction[i]);
4183 result = BT_STATUS_SUCCESS;
4188 pthread_mutex_unlock(&device.lbllock);
4192 /*******************************************************************************
4194 ** Function release_transaction
4196 ** Description Will release a transaction for reuse
4198 ** Returns bt_status_t
4199 *******************************************************************************/
4200 void release_transaction(UINT8 lbl)
4202 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4204 /* If the transaction is in use... */
4205 if (transaction != NULL)
4207 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
4208 initialize_transaction(lbl);
4212 /*******************************************************************************
4214 ** Function lbl_destroy
4216 ** Description Cleanup of the mutex
4219 *******************************************************************************/
4222 pthread_mutex_destroy(&(device.lbllock));
4225 /*******************************************************************************
4226 ** Function sleep_ms
4228 ** Description Sleep the calling thread unconditionally for
4229 ** |timeout_ms| milliseconds.
4232 *******************************************************************************/
4233 static void sleep_ms(period_ms_t timeout_ms) {
4234 struct timespec delay;
4235 delay.tv_sec = timeout_ms / 1000;
4236 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4240 err = nanosleep(&delay, &delay);
4241 } while (err == -1 && errno == EINTR);