pmeta_msg->label);
}
+#if (AVRC_CTLR_INCLUDED == TRUE)
/***************************************************************************
**
-** Function cleanup
-**
-** Description Closes the AVRC interface
+** Function iterate_supported_event_list_for_interim_rsp
**
-** Returns void
+** Description iterator callback function to match the event and handle
+** timer cleanup
- ** Returns true if matches with the event, flase otherwise
++** Returns true to continue iterating, false to stop
**
***************************************************************************/
-static void cleanup()
+bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
{
- BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
- close_uinput();
- if (bt_rc_callbacks)
+ UINT8 *p_event_id;
+ btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
+
+ p_event_id = (UINT8*)cb_data;
+
+ if (p_event->event_id == *p_event_id)
{
- bt_rc_callbacks = NULL;
+ p_event->status = eINTERIM;
- return true;
++ return false;
}
- return false;
- memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
- lbl_destroy();
- BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
++ return true;
}
/***************************************************************************
**
-** Function cleanup_ctrl
-**
-** Description Closes the AVRC Controller interface
+** Function iterate_supported_event_list_for_timeout
**
-** Returns void
+** Description Iterator callback function for timeout handling.
+** As part of the failure handling, it releases the
+** transaction label and removes the event from list,
+** this event will not be requested again during
+** the lifetime of the connection.
- ** Returns true if matches with the event, flase otherwise
++** Returns false to stop iterating, true to continue
**
***************************************************************************/
-static void cleanup_ctrl()
+bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
{
- BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
+ UINT8 label;
- UINT32 cb_value;
+ btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
- cb_value = (UINT32)cb_data;
-
- label = cb_value & 0xFF;
- if (bt_rc_ctrl_callbacks)
++ label = (*(UINT8*)cb_data) & 0xFF;
+
+ if (p_event->label == label)
{
- bt_rc_ctrl_callbacks = NULL;
+ list_remove(btif_rc_cb.rc_supported_event_list, p_event);
- return true;
++ return false;
}
- return false;
- memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
- lbl_destroy();
- BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
++ return true;
}
-static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
+/***************************************************************************
+**
+** Function rc_notification_interim_timout
+**
+** Description Interim response timeout handler.
+** Runs the iterator to check and clear the timed out event.
+** Proceeds to register for the unregistered events.
+** Returns None
+**
+***************************************************************************/
+static void rc_notification_interim_timout (UINT8 label)
{
- tAVRC_STS status = BT_STATUS_UNSUPPORTED;
-#if (AVRC_CTLR_INCLUDED == TRUE)
- CHECK_RC_CONNECTED
- rc_transaction_t *p_transaction=NULL;
- BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
- key_code, key_state);
- if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+ list_node_t *node;
- UINT32 cb_data;
+
- cb_data = label;
- list_foreach_ext(btif_rc_cb.rc_supported_event_list,
- iterate_supported_event_list_for_timeout, (void*)cb_data);
++ list_foreach(btif_rc_cb.rc_supported_event_list,
++ iterate_supported_event_list_for_timeout, &label);
+ /* Timeout happened for interim response for the registered event,
+ * check if there are any pending for registration
+ */
+ node = list_begin(btif_rc_cb.rc_supported_event_list);
+ while (node != NULL)
{
- bt_status_t tran_status = get_transaction(&p_transaction);
- if(BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
- {
- BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
- (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
- status = BT_STATUS_SUCCESS;
- BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
- }
- else
+ btif_rc_supported_event_t *p_event;
+
+ p_event = (btif_rc_supported_event_t *)list_node(node);
+ if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
{
- status = BT_STATUS_FAIL;
- BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
+ register_for_event_notification(p_event);
+ break;
}
+ node = list_next (node);
}
- else
- {
- status = BT_STATUS_FAIL;
- BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
- }
-#else
- BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
-#endif
- return status;
+ /* Todo. Need to initiate application settings query if this
+ * is the last event registration.
+ */
}
-static const btrc_interface_t bt_rc_interface = {
- sizeof(bt_rc_interface),
- init,
- get_play_status_rsp,
+/***************************************************************************
+**
+** Function rc_timeout_callback
+**
+** Description RC timeout callback.
+** This is called from BTU context and switches to BTIF
+** context to handle the timeout events
+** Returns None
+**
+***************************************************************************/
+static void rc_timeout_callback (timer_entry_t *tle)
+{
+ char *p_data = (char*)tle->data;
+
+ tle->data = NULL;
+ btif_transfer_context(rc_timeout_handler, 0,
+ p_data, sizeof(btif_rc_timer_context_t), NULL);
+ osi_freebuf (p_data);
+}
+
+/***************************************************************************
+**
+** Function rc_start_play_status_timer
+**
+** Description Helper function to start the timer to fetch play status.
+** Returns None
+**
+***************************************************************************/
+void rc_start_play_status_timer ()
+{
+ btif_rc_timer_context_t *p_rc_timer_context;
+ /* Start the Play status timer only if it is not started */
+ if (btif_rc_cb.tle_rc_play_status.data == NULL)
+ {
+ p_rc_timer_context = (btif_rc_timer_context_t*) osi_getbuf(sizeof(btif_rc_timer_context_t));
+ if (p_rc_timer_context != NULL)
+ {
+ p_rc_timer_context->timer_id = RC_TIMER_PLAY_STATUS;
+ memset(&btif_rc_cb.tle_rc_play_status, 0, sizeof(timer_entry_t));
+ btif_rc_cb.tle_rc_play_status.param = rc_timeout_callback;
+ btif_rc_cb.tle_rc_play_status.data = p_rc_timer_context;
+ btu_start_timer(&btif_rc_cb.tle_rc_play_status, BTU_TTYPE_USER_FUNC,
+ BTIF_TIMEOUT_RC_INTERIM_RSP);
+ }
+ }
+}
+
+/***************************************************************************
+**
+** Function rc_stop_play_status_timer
+**
+** Description Helper function to stop the play status timer.
+** Returns None
+**
+***************************************************************************/
+void rc_stop_play_status_timer ()
+{
+ if (btif_rc_cb.tle_rc_play_status.data != NULL)
+ {
+ btu_stop_timer (&btif_rc_cb.tle_rc_play_status);
+ osi_freebuf(btif_rc_cb.tle_rc_play_status.data);
+ btif_rc_cb.tle_rc_play_status.data = NULL;
+ }
+}
+
+/***************************************************************************
+**
+** Function rc_timeout_handler
+**
+** Description RC timeout handler (Runs in BTIF context).
+** main handler for all the timers created from RC module
+** Returns None
+**
+***************************************************************************/
+static void rc_timeout_handler (UINT16 event, char* p_data)
+{
+ btif_rc_timer_context_t *p_rc_timer_context;
+ tAVRC_RESPONSE avrc_response = {0};
+ tBTA_AV_META_MSG meta_msg;
+
+ p_rc_timer_context = (btif_rc_timer_context_t *)p_data;
+ memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
+ meta_msg.rc_handle = btif_rc_cb.rc_handle;
+
+ switch (p_rc_timer_context->timer_id)
+ {
+ case RC_TIMER_STATUS_CMD:
+ switch (p_rc_timer_context->rc_status_cmd.pdu_id)
+ {
+ case AVRC_PDU_REGISTER_NOTIFICATION:
+ rc_notification_interim_timout(
+ p_rc_timer_context->rc_status_cmd.label);
+ break;
+
+ case AVRC_PDU_GET_CAPABILITIES:
+ avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
+ handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_ATTR:
+ avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
+ handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_VALUES:
+ avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
+ handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
+ break;
+
+ case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
+ avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
+ handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
+ avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
+ handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
+ avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
+ handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
+ break;
+
+ case AVRC_PDU_GET_ELEMENT_ATTR:
+ avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
+ handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
+ break;
+
+ case AVRC_PDU_GET_PLAY_STATUS:
+ avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
+ handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
+ break;
+ }
+ release_transaction (p_rc_timer_context->rc_status_cmd.label);
+ break;
+
+ case RC_TIMER_CONTROL_CMD:
+ switch (p_rc_timer_context->rc_control_cmd.pdu_id)
+ {
+ case AVRC_PDU_SET_PLAYER_APP_VALUE:
+ avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
+ handle_set_app_attr_val_response(&meta_msg, &avrc_response.set_app_val);
+ break;
+ }
+ release_transaction (p_rc_timer_context->rc_control_cmd.label);
+ break;
+
+ case RC_TIMER_PLAY_STATUS:
+ get_play_status_cmd();
+ rc_start_play_status_timer();
+ break;
+
+ default:
+ BTIF_TRACE_ERROR("%s Error unknown timer id %d",
+ __FUNCTION__, p_rc_timer_context->timer_id);
+ break;
+ }
+}
+
+/***************************************************************************
+**
+** Function register_for_event_notification
+**
+** Description Helper function registering notification events
+** sets an interim response timeout to handle if the remote
+** does not respond.
+** Returns None
+**
+***************************************************************************/
+static void register_for_event_notification (btif_rc_supported_event_t *p_event)
+{
+ bt_status_t status;
+ rc_transaction_t *p_transaction;
+
+ status = get_transaction(&p_transaction);
+ if (status == BT_STATUS_SUCCESS)
+ {
+ btif_rc_timer_context_t *p_rc_timer_context;
+
+ status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
+ if (status != BT_STATUS_SUCCESS)
+ {
+ BTIF_TRACE_ERROR("%s Error in Notification registration %d",
+ __FUNCTION__, status);
+ release_transaction (p_transaction->lbl);
+ return;
+ }
+ p_event->label = p_transaction->lbl;
+ p_event->status = eREGISTERED;
+ p_rc_timer_context = (btif_rc_timer_context_t*) osi_getbuf(sizeof(btif_rc_timer_context_t));
+ if (p_rc_timer_context != NULL)
+ {
+ p_rc_timer_context->timer_id = RC_TIMER_STATUS_CMD;
+ p_rc_timer_context->rc_status_cmd.label = p_transaction->lbl;
+ p_rc_timer_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
+ memset(&p_transaction->tle_txn, 0, sizeof(timer_entry_t));
+ p_transaction->tle_txn.param = rc_timeout_callback;
+ p_transaction->tle_txn.data = p_rc_timer_context;
+ btu_start_timer(&p_transaction->tle_txn, BTU_TTYPE_USER_FUNC,
+ BTIF_TIMEOUT_RC_INTERIM_RSP);
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
+ __FUNCTION__, status);
+ }
+}
+
+static void start_status_command_timer (UINT8 pdu_id, rc_transaction_t *p_txn)
+{
+ bt_status_t status;
+ btif_rc_timer_context_t *p_rc_timer_context;
+
+ p_rc_timer_context = (btif_rc_timer_context_t*) osi_getbuf(sizeof(btif_rc_timer_context_t));
+ if (p_rc_timer_context != NULL)
+ {
+ p_rc_timer_context->timer_id = RC_TIMER_STATUS_CMD;
+ p_rc_timer_context->rc_status_cmd.label = p_txn->lbl;
+ p_rc_timer_context->rc_status_cmd.pdu_id = pdu_id;
+
+ memset(&p_txn->tle_txn, 0, sizeof(timer_entry_t));
+ p_txn->tle_txn.param = rc_timeout_callback;
+ p_txn->tle_txn.data = p_rc_timer_context;
+ btu_start_timer(&p_txn->tle_txn, BTU_TTYPE_USER_FUNC,
+ BTIF_TIMEOUT_RC_STATUS_CMD);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s Getbuf failed while starting command timer",
+ __FUNCTION__);
+ }
+}
+
+static void start_control_command_timer (UINT8 pdu_id, rc_transaction_t *p_txn)
+{
+ bt_status_t status;
+ btif_rc_timer_context_t *p_rc_timer_context;
+
+ p_rc_timer_context = (btif_rc_timer_context_t*) osi_getbuf(sizeof(btif_rc_timer_context_t));
+ if (p_rc_timer_context != NULL)
+ {
+ p_rc_timer_context->timer_id = RC_TIMER_CONTROL_CMD;
+ p_rc_timer_context->rc_control_cmd.label = p_txn->lbl;
+ p_rc_timer_context->rc_control_cmd.pdu_id = pdu_id;
+
+ memset(&p_txn->tle_txn, 0, sizeof(timer_entry_t));
+ p_txn->tle_txn.param = rc_timeout_callback;
+ p_txn->tle_txn.data = p_rc_timer_context;
+ btu_start_timer(&p_txn->tle_txn, BTU_TTYPE_USER_FUNC,
+ BTIF_TIMEOUT_RC_CONTROL_CMD);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s Getbuf failed while starting command timer",
+ __FUNCTION__);
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_get_capability_response
+**
+** Description Handles the get_cap_response to populate company id info
+** and query the supported events.
+** Initiates Notification registration for events supported
+** Returns None
+**
+***************************************************************************/
+static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
+{
+ int xx = 0;
+
+ /* Todo: Do we need to retry on command timeout */
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
+ __FUNCTION__, p_rsp->status);
+ return;
+ }
+
+ if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
+ {
+ btif_rc_supported_event_t *p_event;
+
+ /* Todo: Check if list can be active when we hit here */
+ btif_rc_cb.rc_supported_event_list = list_new(rc_supported_event_free);
+ for (xx = 0; xx < p_rsp->count; xx++)
+ {
+ /* Skip registering for Play position change notification */
+ if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
+ (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
+ (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
+ {
+ p_event = (btif_rc_supported_event_t*) osi_getbuf(sizeof(btif_rc_supported_event_t));
+ p_event->event_id = p_rsp->param.event_id[xx];
+ p_event->status = eNOT_REGISTERED;
+ list_append(btif_rc_cb.rc_supported_event_list, p_event);
+ }
+ }
+ p_event = list_front(btif_rc_cb.rc_supported_event_list);
+ if (p_event != NULL)
+ {
+ register_for_event_notification(p_event);
+ }
+ }
+ else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
+ {
+ getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
+ BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
+ for (xx = 0; xx < p_rsp->count; xx++)
+ {
+ BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
+ }
+ }
+}
+
+bool rc_is_track_id_valid (tAVRC_UID uid)
+{
+ tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+ if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_notification_response
+**
+** Description Main handler for notification responses to registered events
+** 1. Register for unregistered event(in interim response path)
+** 2. After registering for all supported events, start
+** retrieving application settings and values
+** 3. Reregister for events on getting changed response
+** 4. Run play status timer for getting position when the
+** status changes to playing
+** 5. Get the Media details when the track change happens
+** or track change interim response is received with
+** valid track id
+** 6. HAL callback for play status change and application
+** setting change
+** Returns None
+**
+***************************************************************************/
+static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
+{
+ bt_bdaddr_t rc_addr;
+ UINT32 attr_list[] = {
+ AVRC_MEDIA_ATTR_ID_TITLE,
+ AVRC_MEDIA_ATTR_ID_ARTIST,
+ AVRC_MEDIA_ATTR_ID_ALBUM,
+ AVRC_MEDIA_ATTR_ID_TRACK_NUM,
+ AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
+ AVRC_MEDIA_ATTR_ID_GENRE,
+ AVRC_MEDIA_ATTR_ID_PLAYING_TIME
+ };
+
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ if (pmeta_msg->code == AVRC_RSP_INTERIM)
+ {
+ btif_rc_supported_event_t *p_event;
+ list_node_t *node;
+
+ BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
+ switch (p_rsp->event_id)
+ {
+ case AVRC_EVT_PLAY_STATUS_CHANGE:
+ /* Start timer to get play status periodically
+ * if the play state is playing.
+ */
+ if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
+ {
+ rc_start_play_status_timer();
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
+ &rc_addr, p_rsp->param.play_status);
+ break;
+
+ case AVRC_EVT_TRACK_CHANGE:
+ if (rc_is_track_id_valid (p_rsp->param.track) != true)
+ {
+ break;
+ }
+ else
+ {
+ UINT8 *p_data = p_rsp->param.track;
+ /* Update the UID for current track
+ * Attributes will be fetched after the AVRCP procedure
+ */
+ BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
+ }
+ break;
+
+ case AVRC_EVT_APP_SETTING_CHANGE:
+ break;
+
+ case AVRC_EVT_NOW_PLAYING_CHANGE:
+ break;
+
+ case AVRC_EVT_AVAL_PLAYERS_CHANGE:
+ break;
+
+ case AVRC_EVT_ADDR_PLAYER_CHANGE:
+ break;
+
+ case AVRC_EVT_UIDS_CHANGE:
+ break;
+
+ case AVRC_EVT_TRACK_REACHED_END:
+ case AVRC_EVT_TRACK_REACHED_START:
+ case AVRC_EVT_PLAY_POS_CHANGED:
+ case AVRC_EVT_BATTERY_STATUS_CHANGE:
+ case AVRC_EVT_SYSTEM_STATUS_CHANGE:
+ default:
+ BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
+ p_rsp->event_id);
+ return;
+ }
- list_foreach_ext(btif_rc_cb.rc_supported_event_list,
++ list_foreach(btif_rc_cb.rc_supported_event_list,
+ iterate_supported_event_list_for_interim_rsp,
- (void*)&p_rsp->event_id);
++ &p_rsp->event_id);
+
+ node = list_begin(btif_rc_cb.rc_supported_event_list);
+ while (node != NULL)
+ {
+ p_event = (btif_rc_supported_event_t *)list_node(node);
+ if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
+ {
+ register_for_event_notification(p_event);
+ break;
+ }
+ node = list_next (node);
+ p_event = NULL;
+ }
+ /* Registered for all events, we can request application settings */
+ if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
+ {
+ /* we need to do this only if remote TG supports
+ * player application settings
+ */
+ btif_rc_cb.rc_app_settings.query_started = TRUE;
+ if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
+ {
+ list_player_app_setting_attrib_cmd();
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
+ rc_ctrl_procedure_complete();
+ }
+ }
+ }
+ else if (pmeta_msg->code == AVRC_RSP_CHANGED)
+ {
+ btif_rc_supported_event_t *p_event;
+ list_node_t *node;
+
+ BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
+ p_rsp->event_id);
+
+ node = list_begin(btif_rc_cb.rc_supported_event_list);
+ while (node != NULL)
+ {
+ p_event = (btif_rc_supported_event_t *)list_node(node);
+ if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
+ {
+ p_event->status = eNOT_REGISTERED;
+ register_for_event_notification(p_event);
+ break;
+ }
+ node = list_next (node);
+ }
+
+ switch (p_rsp->event_id)
+ {
+ case AVRC_EVT_PLAY_STATUS_CHANGE:
+ /* Start timer to get play status periodically
+ * if the play state is playing.
+ */
+ if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
+ {
+ rc_start_play_status_timer();
+ }
+ else
+ {
+ rc_stop_play_status_timer();
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
+ &rc_addr, p_rsp->param.play_status);
+ break;
+
+ case AVRC_EVT_TRACK_CHANGE:
+ if (rc_is_track_id_valid (p_rsp->param.track) != true)
+ {
+ break;
+ }
+ get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
+ break;
+
+ case AVRC_EVT_APP_SETTING_CHANGE:
+ {
+ btrc_player_settings_t app_settings;
+ UINT16 xx;
+
+ app_settings.num_attr = p_rsp->param.player_setting.num_attr;
+ for (xx = 0; xx < app_settings.num_attr; xx++)
+ {
+ app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
+ app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
+ &rc_addr, &app_settings);
+ }
+ break;
+
+ case AVRC_EVT_NOW_PLAYING_CHANGE:
+ break;
+
+ case AVRC_EVT_AVAL_PLAYERS_CHANGE:
+ break;
+
+ case AVRC_EVT_ADDR_PLAYER_CHANGE:
+ break;
+
+ case AVRC_EVT_UIDS_CHANGE:
+ break;
+
+ case AVRC_EVT_TRACK_REACHED_END:
+ case AVRC_EVT_TRACK_REACHED_START:
+ case AVRC_EVT_PLAY_POS_CHANGED:
+ case AVRC_EVT_BATTERY_STATUS_CHANGE:
+ case AVRC_EVT_SYSTEM_STATUS_CHANGE:
+ default:
+ BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
+ __FUNCTION__, p_rsp->event_id);
+ return;
+ }
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_app_attr_response
+**
+** Description handles the the application attributes response and
+** initiates procedure to fetch the attribute values
+** Returns None
+**
+***************************************************************************/
+static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
+{
+ UINT8 xx;
+
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
+ __FUNCTION__, p_rsp->status);
+ rc_ctrl_procedure_complete();
+ return;
+ }
+
+ for (xx = 0; xx < p_rsp->num_attr; xx++)
+ {
+ UINT8 st_index;
+
+ if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
+ {
+ st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
+ btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
+ btif_rc_cb.rc_app_settings.num_ext_attrs++;
+ }
+ else
+ {
+ st_index = btif_rc_cb.rc_app_settings.num_attrs;
+ btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
+ btif_rc_cb.rc_app_settings.num_attrs++;
+ }
+ }
+ btif_rc_cb.rc_app_settings.attr_index = 0;
+ btif_rc_cb.rc_app_settings.ext_attr_index = 0;
+ btif_rc_cb.rc_app_settings.ext_val_index = 0;
+ if (p_rsp->num_attr)
+ {
+ list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s No Player application settings found",
+ __FUNCTION__);
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_app_val_response
+**
+** Description handles the the attributes value response and if extended
+** menu is available, it initiates query for the attribute
+** text. If not, it initiates procedure to get the current
+** attribute values and calls the HAL callback for provding
+** application settings information.
+** Returns None
+**
+***************************************************************************/
+static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
+{
+ UINT8 xx, attr_index;
+ int i,j;
+ UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
+ btif_rc_player_app_settings_t *p_app_settings;
+ bt_bdaddr_t rc_addr;
+
+ /* Todo: Do we need to retry on command timeout */
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
+ __FUNCTION__, p_rsp->status);
+ return;
+ }
+
+ p_app_settings = &btif_rc_cb.rc_app_settings;
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ if (p_app_settings->attr_index < p_app_settings->num_attrs)
+ {
+ attr_index = p_app_settings->attr_index;
+ p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
+ for (xx = 0; xx < p_rsp->num_val; xx++)
+ {
+ p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
+ }
+ attr_index++;
+ p_app_settings->attr_index++;
+ if (attr_index < p_app_settings->num_attrs)
+ {
+ list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
+ }
+ else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
+ {
+ attr_index = 0;
+ p_app_settings->ext_attr_index = 0;
+ list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
+ }
+ else
+ {
+ for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+ {
+ attrs[xx] = p_app_settings->attrs[xx].attr_id;
+ }
+ get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
+ HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
+ p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
+ }
+ }
+ else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
+ {
+ attr_index = p_app_settings->ext_attr_index;
+ p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
+ for (xx = 0; xx < p_rsp->num_val; xx++)
+ {
+ p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
+ }
+ attr_index++;
+ p_app_settings->ext_attr_index++;
+ if (attr_index < p_app_settings->num_ext_attrs)
+ {
+ list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
+ }
+ else
+ {
+ UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
+ UINT8 xx;
+
+ for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
+ {
+ attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
+ }
+ get_player_app_setting_attr_text_cmd(attr, xx);
+ }
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_app_cur_val_response
+**
+** Description handles the the get attributes value response.
+**
+** Returns None
+**
+***************************************************************************/
+static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
+{
+ btrc_player_settings_t app_settings;
+ bt_bdaddr_t rc_addr;
+ UINT16 xx;
+
+ /* Todo: Do we need to retry on command timeout */
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
+ __FUNCTION__, p_rsp->status);
+ return;
+ }
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ app_settings.num_attr = p_rsp->num_val;
+ for (xx = 0; xx < app_settings.num_attr; xx++)
+ {
+ app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
+ app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
+ &rc_addr, &app_settings);
+ /* Application settings are fetched only once for initial values
+ * initiate anything that follows after RC procedure.
+ * Defer it if browsing is supported till players query
+ */
+ rc_ctrl_procedure_complete ();
+ osi_freebuf(p_rsp->p_vals);
+}
+
+/***************************************************************************
+**
+** Function handle_app_attr_txt_response
+**
+** Description handles the the get attributes text response, if fails
+** calls HAL callback with just normal settings and initiates
+** query for current settings else initiates query for value text
+** Returns None
+**
+***************************************************************************/
+static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
+{
+ UINT8 xx, attr_index;
+ UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
+ btif_rc_player_app_settings_t *p_app_settings;
+ bt_bdaddr_t rc_addr;
+
+ p_app_settings = &btif_rc_cb.rc_app_settings;
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ /* Todo: Do we need to retry on command timeout */
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
+
+ BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
+ __FUNCTION__, p_rsp->status);
+ /* Not able to fetch Text for extended Menu, skip the process
+ * and cleanup used memory. Proceed to get the current settings
+ * for standard attributes.
+ */
+ p_app_settings->num_ext_attrs = 0;
+ for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
+ {
+ osi_freebuf (p_app_settings->ext_attrs[xx].p_str);
+ }
+ p_app_settings->ext_attr_index = 0;
+
+ for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+ {
+ attrs[xx] = p_app_settings->attrs[xx].attr_id;
+ }
+ HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
+ p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
+
+ get_player_app_setting_cmd (xx, attrs);
+ return;
+ }
+
+ for (xx = 0; xx < p_rsp->num_attr; xx++)
+ {
+ UINT8 x;
+ for (x = 0; x < p_app_settings->num_ext_attrs; x++)
+ {
+ if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
+ {
+ p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
+ p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
+ p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
+ break;
+ }
+ }
+ }
+
+ for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
+ {
+ vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
+ }
+ get_player_app_setting_value_text_cmd(vals, xx);
+}
+
+
+/***************************************************************************
+**
+** Function handle_app_attr_val_txt_response
+**
+** Description handles the the get attributes value text response, if fails
+** calls HAL callback with just normal settings and initiates
+** query for current settings
+** Returns None
+**
+***************************************************************************/
+static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
+{
+ UINT8 xx, attr_index;
+ UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
+ UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
+ btif_rc_player_app_settings_t *p_app_settings;
+ bt_bdaddr_t rc_addr;
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+ p_app_settings = &btif_rc_cb.rc_app_settings;
+
+ /* Todo: Do we need to retry on command timeout */
+ if (p_rsp->status != AVRC_STS_NO_ERROR)
+ {
+ UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
+
+ BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
+ __FUNCTION__, p_rsp->status);
+
+ /* Not able to fetch Text for extended Menu, skip the process
+ * and cleanup used memory. Proceed to get the current settings
+ * for standard attributes.
+ */
+ p_app_settings->num_ext_attrs = 0;
+ for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
+ {
+ int x;
+ btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
+
+ for (x = 0; x < p_ext_attr->num_val; x++)
+ {
+ osi_freebuf (p_ext_attr->ext_attr_val[x].p_str);
+ }
+ p_ext_attr->num_val = 0;
+ osi_freebuf (p_app_settings->ext_attrs[xx].p_str);
+ }
+ p_app_settings->ext_attr_index = 0;
+
+ for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+ {
+ attrs[xx] = p_app_settings->attrs[xx].attr_id;
+ }
+ HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
+ p_app_settings->num_attrs, &p_app_settings->attrs, 0, NULL);
+
+ get_player_app_setting_cmd (xx, attrs);
+ return;
+ }
+
+ for (xx = 0; xx < p_rsp->num_attr; xx++)
+ {
+ UINT8 x;
+ btrc_player_app_ext_attr_t *p_ext_attr;
+ p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
+ for (x = 0; x < p_rsp->num_attr; x++)
+ {
+ if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
+ {
+ p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
+ p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
+ p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
+ break;
+ }
+ }
+ }
+ p_app_settings->ext_val_index++;
+
+ if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
+ {
+ attr_index = p_app_settings->ext_val_index;
+ for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
+ {
+ vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
+ }
+ get_player_app_setting_value_text_cmd(vals, xx);
+ }
+ else
+ {
+ UINT8 x;
+
+ for (xx = 0; xx < p_app_settings->num_attrs; xx++)
+ {
+ attrs[xx] = p_app_settings->attrs[xx].attr_id;
+ }
+ for (x = 0; x < p_app_settings->num_ext_attrs; x++)
+ {
+ attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
+ }
+ HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
+ p_app_settings->num_attrs, &p_app_settings->attrs,
+ p_app_settings->num_ext_attrs, &p_app_settings->ext_attrs);
+ get_player_app_setting_cmd (xx + x, attrs);
+
+ /* Free the application settings information after sending to
+ * application.
+ */
+ for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
+ {
+ int x;
+ btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
+
+ for (x = 0; x < p_ext_attr->num_val; x++)
+ {
+ osi_freebuf (p_ext_attr->ext_attr_val[x].p_str);
+ }
+ p_ext_attr->num_val = 0;
+ osi_freebuf (p_app_settings->ext_attrs[xx].p_str);
+ }
+ p_app_settings->num_attrs = 0;
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_set_app_attr_val_response
+**
+** Description handles the the set attributes value response, if fails
+** calls HAL callback to indicate the failure
+** Returns None
+**
+***************************************************************************/
+static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
+{
+ uint8_t accepted = 0;
+ bt_bdaddr_t rc_addr;
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ /* For timeout pmeta_msg will be NULL, else we need to
+ * check if this is accepted by TG
+ */
+ if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
+ {
+ accepted = 1;
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
+}
+
+/***************************************************************************
+**
+** Function handle_get_elem_attr_response
+**
+** Description handles the the element attributes response, calls
+** HAL callback to update track change information.
+** Returns None
+**
+***************************************************************************/
+static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
+{
+ btrc_element_attr_val_t *p_attr;
+ bt_bdaddr_t rc_addr;
+ UINT16 xx;
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ if (p_rsp->status == AVRC_STS_NO_ERROR)
+ {
+ p_attr = (btrc_element_attr_val_t*)osi_getbuf (p_rsp->num_attr * sizeof(btrc_element_attr_val_t));
+ if (p_attr != NULL)
+ {
+ memset(p_attr, 0, osi_get_buf_size (p_attr));
+ for (xx = 0; xx < p_rsp->num_attr; xx++)
+ {
+ p_attr[xx].attr_id = p_rsp->p_attrs[xx].attr_id;
+ /* Todo. Legth limit check to include null */
+ if (p_rsp->p_attrs[xx].name.str_len && p_rsp->p_attrs[xx].name.p_str)
+ {
+ memcpy(p_attr[xx].text, p_rsp->p_attrs[xx].name.p_str,
+ p_rsp->p_attrs[xx].name.str_len);
+ osi_freebuf (p_rsp->p_attrs[xx].name.p_str);
+ }
+ }
+ HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
+ &rc_addr, p_rsp->num_attr, p_attr);
+ osi_freebuf (p_attr);
+ }
+ }
+ else if (p_rsp->status == BTIF_RC_STS_TIMEOUT)
+ {
+ /* Retry for timeout case, this covers error handling
+ * for continuation failure also.
+ */
+ UINT32 attr_list[] = {
+ AVRC_MEDIA_ATTR_ID_TITLE,
+ AVRC_MEDIA_ATTR_ID_ARTIST,
+ AVRC_MEDIA_ATTR_ID_ALBUM,
+ AVRC_MEDIA_ATTR_ID_TRACK_NUM,
+ AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
+ AVRC_MEDIA_ATTR_ID_GENRE,
+ AVRC_MEDIA_ATTR_ID_PLAYING_TIME
+ };
+ get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
+ __FUNCTION__, p_rsp->status);
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_get_playstatus_response
+**
+** Description handles the the play status response, calls
+** HAL callback to update play position.
+** Returns None
+**
+***************************************************************************/
+static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
+{
+ bt_bdaddr_t rc_addr;
+
+ bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+
+ if (p_rsp->status == AVRC_STS_NO_ERROR)
+ {
+ HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
+ &rc_addr, p_rsp->song_len, p_rsp->song_pos);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
+ __FUNCTION__, p_rsp->status);
+ }
+}
+
+/***************************************************************************
+**
+** Function clear_cmd_timeout
+**
+** Description helper function to stop the command timeout timer
+** Returns None
+**
+***************************************************************************/
+static void clear_cmd_timeout (UINT8 label)
+{
+ rc_transaction_t *p_txn;
+
+ p_txn = get_transaction_by_lbl (label);
+ if (p_txn == NULL)
+ {
+ BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
+ return;
+ }
+
+ btu_stop_timer (&p_txn->tle_txn);
+ if (p_txn->tle_txn.data != NULL)
+ {
+ osi_freebuf (p_txn->tle_txn.data);
+ p_txn->tle_txn.data = NULL;
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_avk_rc_metamsg_rsp
+**
+** Description Handle RC metamessage response
+**
+** Returns void
+**
+***************************************************************************/
+static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
+{
+ tAVRC_RESPONSE avrc_response = {0};
+ UINT8 scratch_buf[512] = {0};// this variable is unused
+ UINT16 buf_len;
+ tAVRC_STS status;
+
+ BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
+ pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
+
+ if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
+ (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
+ (pmeta_msg->code <= AVRC_RSP_INTERIM))
+ {
+ status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
+ BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
+ __FUNCTION__, status, avrc_response.pdu,
+ pmeta_msg->p_msg->vendor.hdr.ctype);
+
+ switch (avrc_response.pdu)
+ {
+ case AVRC_PDU_REGISTER_NOTIFICATION:
+ handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
+ if (pmeta_msg->code == AVRC_RSP_INTERIM)
+ {
+ /* Don't free the transaction Id */
+ clear_cmd_timeout (pmeta_msg->label);
+ return;
+ }
+ break;
+
+ case AVRC_PDU_GET_CAPABILITIES:
+ handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_ATTR:
+ handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
+ break;
+
+ case AVRC_PDU_LIST_PLAYER_APP_VALUES:
+ handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
+ break;
+
+ case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
+ handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
+ handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
+ break;
+
+ case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
+ handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
+ break;
+
+ case AVRC_PDU_SET_PLAYER_APP_VALUE:
+ handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
+ break;
+
+ case AVRC_PDU_GET_ELEMENT_ATTR:
+ handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
+ break;
+
+ case AVRC_PDU_GET_PLAY_STATUS:
+ handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
+ break;
+ }
+ release_transaction(pmeta_msg->label);
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
+ __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
+ return;
+ }
+}
+
+/***************************************************************************
+**
+** Function handle_avk_rc_metamsg_cmd
+**
+** Description Handle RC metamessage response
+**
+** Returns void
+**
+***************************************************************************/
+static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
+{
+ tAVRC_COMMAND avrc_cmd = {0};
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
+ pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
+ if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
+ (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
+ {
+ status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
+ BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
+ __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
+
+ if (status != AVRC_STS_NO_ERROR)
+ {
+ /* return error */
+ BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
+ __FUNCTION__, status);
+ send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
+ }
+ else
+ {
+ if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
+ {
+ UINT8 event_id = avrc_cmd.reg_notif.event_id;
+ BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
+ __FUNCTION__, dump_rc_notification_event_id(event_id));
+ }
+ else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
+ {
+ BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
+ }
+ btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
+ }
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
+ __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
+ return;
+ }
+}
+#endif
+
+/***************************************************************************
+**
+** Function cleanup
+**
+** Description Closes the AVRC interface
+**
+** Returns void
+**
+***************************************************************************/
+static void cleanup()
+{
+ BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
+ close_uinput();
+ if (bt_rc_callbacks)
+ {
+ bt_rc_callbacks = NULL;
+ }
+ memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
+ lbl_destroy();
+ BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
+}
+
+/***************************************************************************
+**
+** Function cleanup_ctrl
+**
+** Description Closes the AVRC Controller interface
+**
+** Returns void
+**
+***************************************************************************/
+static void cleanup_ctrl()
+{
+ BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
+
+ if (bt_rc_ctrl_callbacks)
+ {
+ bt_rc_ctrl_callbacks = NULL;
+ }
+ memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
+ lbl_destroy();
+ BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
+}
+
+/***************************************************************************
+**
+** Function getcapabilities_cmd
+**
+** Description GetCapabilties from Remote(Company_ID, Events_Supported)
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t getcapabilities_cmd (uint8_t cap_id)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
+ CHECK_RC_CONNECTED
+ bt_status_t tran_status=get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_caps.capability_id = cap_id;
+ avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
+ avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function list_player_app_setting_attrib_cmd
+**
+** Description Get supported List Player Attributes
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t list_player_app_setting_attrib_cmd(void)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
+ CHECK_RC_CONNECTED
+ bt_status_t tran_status=get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
+ avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
+ }
+ else
+ {
+
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (NULL!=p_msg)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function list_player_app_setting_value_cmd
+**
+** Description Get values of supported Player Attributes
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction=NULL;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
+ CHECK_RC_CONNECTED
+ bt_status_t tran_status=get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ avrc_cmd.list_app_values.attr_id = attrib_id;
+ avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
+ avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
+ }
+ if (NULL!=p_msg)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function get_player_app_setting_cmd
+**
+** Description Get current values of Player Attributes
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+ int count = 0;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
+ CHECK_RC_CONNECTED
+ bt_status_t tran_status=get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
+ avrc_cmd.get_cur_app_val.num_attr = num_attrib;
+ avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
+
+ for (count = 0; count < num_attrib; count++)
+ {
+ avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
+ }
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function change_player_app_setting
+**
+** Description Set current values of Player Attributes
+**
+** Returns void
+**
+***************************************************************************/
+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)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+ int count = 0;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
+ CHECK_RC_CONNECTED
+ bt_status_t tran_status=get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
+ avrc_cmd.set_app_val.num_val = num_attrib;
+ avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
+ avrc_cmd.set_app_val.p_vals =
+ (tAVRC_APP_SETTING*)osi_getbuf(sizeof(tAVRC_APP_SETTING)*num_attrib);
+ if (avrc_cmd.set_app_val.p_vals == NULL)
+ {
+ BTIF_TRACE_ERROR("%s: alloc failed", __FUNCTION__);
+ return BT_STATUS_FAIL;
+ }
+ for (count = 0; count < num_attrib; count++)
+ {
+ avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
+ avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
+ }
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+ osi_freebuf(avrc_cmd.set_app_val.p_vals);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function get_player_app_setting_attr_text_cmd
+**
+** Description Get text description for app attribute
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+ int count = 0;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ bt_status_t tran_status;
+ CHECK_RC_CONNECTED
+
+ BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
+
+ tran_status = get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
+ avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
+
+ for (count = 0; count < num_attrs; count++)
+ {
+ avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
+ }
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, p_transaction->lbl);
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+ AVRC_CMD_STATUS, data_start, p_msg->len);
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
+ }
+ if (NULL != p_msg)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function get_player_app_setting_val_text_cmd
+**
+** Description Get text description for app attribute values
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+ int count = 0;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ bt_status_t tran_status;
+ CHECK_RC_CONNECTED
+
+ BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
+
+ tran_status = get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
+ avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_app_val_txt.num_val = num_vals;
+
+ for (count = 0; count < num_vals; count++)
+ {
+ avrc_cmd.get_app_val_txt.vals[count] = vals[count];
+ }
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, p_transaction->lbl);
+ if (p_msg != NULL)
+ {
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+ AVRC_CMD_STATUS, data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (NULL != p_msg)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function register_notification_cmd
+**
+** Description Send Command to register for a Notification ID
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
+{
+
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ CHECK_RC_CONNECTED
+
+
+ BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
+
+ avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
+ avrc_cmd.reg_notif.event_id = event_id;
+ avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
+ avrc_cmd.reg_notif.param = event_value;
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, label);
+ if (p_msg != NULL)
+ {
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
+ data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function get_element_attribute_cmd
+**
+** Description Get Element Attribute for attributeIds
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction=NULL;
+ int count = 0;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ bt_status_t tran_status;
+ CHECK_RC_CONNECTED
+
+ BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
+ __FUNCTION__, num_attribute, p_attr_ids[0]);
+
+ tran_status = get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
+ avrc_cmd.get_elem_attrs.num_attr = num_attribute;
+ avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
+ for (count = 0; count < num_attribute; count++)
+ {
+ avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
+ }
+
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, p_transaction->lbl);
+ if (p_msg != NULL)
+ {
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+ AVRC_CMD_STATUS, data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
+ p_transaction);
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function get_play_status_cmd
+**
+** Description Get Element Attribute for attributeIds
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t get_play_status_cmd(void)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ rc_transaction_t *p_transaction = NULL;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_COMMAND avrc_cmd = {0};
+ BT_HDR *p_msg = NULL;
+ bt_status_t tran_status;
+ CHECK_RC_CONNECTED
+
+ BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
+ tran_status = get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS != tran_status)
+ return BT_STATUS_FAIL;
+
+ avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
+ avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
+ avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, p_transaction->lbl);
+ if (p_msg != NULL)
+ {
+ BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
+ AVRC_CMD_STATUS, data_start, p_msg->len);
+ status = BT_STATUS_SUCCESS;
+ start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+
+}
+
+/***************************************************************************
+**
+** Function set_volume_rsp
+**
+** Description Rsp for SetAbsoluteVolume Command
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ tAVRC_RESPONSE avrc_rsp;
+ BT_HDR *p_msg = NULL;
+ CHECK_RC_CONNECTED
+
+ BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
+
+ avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
+ avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
+ avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
+ avrc_rsp.volume.volume = abs_vol;
+ status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__, btif_rc_cb.rc_vol_label);
+ if (p_msg != NULL)
+ {
+ BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+ BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
+ status = BT_STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function send_register_abs_vol_rsp
+**
+** Description Rsp for Notification of Absolute Volume
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
+ uint8_t abs_vol, uint8_t label)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+ tAVRC_RESPONSE avrc_rsp;
+ BT_HDR *p_msg = NULL;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __FUNCTION__, rsp_type, abs_vol);
+ CHECK_RC_CONNECTED
+
+ avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
+ avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
+ avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
+ avrc_rsp.reg_notif.param.volume = abs_vol;
+ avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
+
+ status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+ if (status == AVRC_STS_NO_ERROR)
+ {
+ BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
+ __FUNCTION__,label);
+ UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
+ BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+ (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
+ data_start, p_msg->len, 0);
+ if (p_msg != NULL)
+ osi_freebuf(p_msg);
+ status = BT_STATUS_SUCCESS;
+ }
+ else
+ {
+ if (NULL!=p_msg)
+ osi_freebuf(p_msg);
+ BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
+ __FUNCTION__, status);
+ }
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function send_groupnavigation_cmd
+**
+** Description Send Pass-Through command
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
+ uint8_t key_state)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ rc_transaction_t *p_transaction=NULL;
+ BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
+ key_code, key_state);
+ CHECK_RC_CONNECTED
+ if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+ {
+ bt_status_t tran_status = get_transaction(&p_transaction);
+ if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction))
+ {
+ UINT8* p_buf = (UINT8*)osi_getbuf(AVRC_PASS_THRU_GROUP_LEN);
+ if (p_buf != NULL)
+ {
+ UINT8* start = p_buf;
+ UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
+ *(start)++ = 0;
+ UINT8_TO_BE_STREAM(start, key_code);
+ BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+ (tBTA_AV_STATE)key_state, p_buf, AVRC_PASS_THRU_GROUP_LEN);
+ status = BT_STATUS_SUCCESS;
+ BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
+ __FUNCTION__);
+ }
+ }
+ else
+ {
+ status = BT_STATUS_FAIL;
+ BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
+ }
+ }
+ else
+ {
+ status = BT_STATUS_FAIL;
+ BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
+ }
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+/***************************************************************************
+**
+** Function send_passthrough_cmd
+**
+** Description Send Pass-Through command
+**
+** Returns void
+**
+***************************************************************************/
+static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
+{
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+#if (AVRC_CTLR_INCLUDED == TRUE)
+ CHECK_RC_CONNECTED
+ rc_transaction_t *p_transaction=NULL;
+ BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
+ key_code, key_state);
+ if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+ {
+ bt_status_t tran_status = get_transaction(&p_transaction);
+ if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
+ {
+ BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+ (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
+ status = BT_STATUS_SUCCESS;
+ BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
+ }
+ else
+ {
+ status = BT_STATUS_FAIL;
+ BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
+ }
+ }
+ else
+ {
+ status = BT_STATUS_FAIL;
+ BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
+ }
+#else
+ BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
+#endif
+ return status;
+}
+
+static const btrc_interface_t bt_rc_interface = {
+ sizeof(bt_rc_interface),
+ init,
+ get_play_status_rsp,
NULL, /* list_player_app_attr_rsp */
NULL, /* list_player_app_value_rsp */
NULL, /* get_player_app_value_rsp */