--- /dev/null
+/*
+ * Open Adaptation Layer (OAL)
+ *
+ * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Nilesh Trimbake <t.shripati@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef _OAL_AVRCP_CT_H_
+#define _OAL_AVRCP_CT_H_
+
+
+#include <glib.h>
+#include <sys/types.h>
+#include <oal-manager.h>
+#include "oal-event.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ OAL_RC_PASS_CMD_PLAY = 0x01,
+ OAL_RC_PASS_CMD_PAUSE,
+ OAL_RC_PASS_CMD_STOP,
+ OAL_RC_PASS_CMD_NEXT,
+ OAL_RC_PASS_CMD_PREVIOUS,
+ OAL_RC_PASS_CMD_PRESS_FAST_FORWARD,
+ OAL_RC_PASS_CMD_RELEASE_FAST_FORWARD,
+ OAL_RC_PASS_CMD_PRESS_REWIND,
+ OAL_RC_PASS_CMD_RELEASE_REWIND
+} avrcp_ct_pass_cmd_key_code_t;
+
+/**
+ * @brief Current State of remote key(pressed/released)
+ *
+ * @see avrcp_ct_fforward
+ * @see avrcp_ct_rewind
+ */
+typedef enum {
+ PRESS_STATE = 0x00,
+ RELEASE_STATE = 0x01
+} avrcp_ct_pass_state_t;
+
+typedef struct {
+ avrcp_ct_pass_cmd_key_code_t key_code;
+ avrcp_ct_pass_state_t key_state;
+} avrcp_ct_pass_cmd_t;
+
+typedef struct {
+ uint8_t accepted;
+} avrcp_ct_playersetting_t;
+
+typedef enum {
+ OAL_EQUALIZER = 0x01,
+ OAL_REPEAT,
+ OAL_SHUFFLE,
+ OAL_SCAN,
+ OAL_PLAY_STATUS,
+ OAL_PLAY_POSITION,
+} avrcp_ct_player_property_type_t;
+
+typedef enum {
+ OAL_PLAYSTATE_STOPPED = 0x00, /* Stopped */
+ OAL_PLAYSTATE_PLAYING = 0x01, /* Playing */
+ OAL_PLAYSTATE_PAUSED = 0x02, /* Paused */
+ OAL_PLAYSTATE_FWD_SEEK = 0x03, /* Fwd Seek*/
+ OAL_PLAYSTATE_REV_SEEK = 0x04, /* Rev Seek*/
+ OAL_PLAYSTATE_ERROR = 0xFF, /* Error */
+} avrcp_ct_play_status_t;
+
+typedef struct {
+ const char *title;
+ const char *artist;
+ const char *album;
+ const char *genre;
+ unsigned int total_tracks;
+ unsigned int number;
+ unsigned int duration;
+} avrcp_ct_media_metadata_attr_t;
+
+typedef struct {
+ unsigned int value;
+} avrcp_ct_property_value_t;
+
+typedef struct {
+ uint32_t song_len;
+ uint32_t song_pos;
+} avrcp_ct_play_position_t;
+
+typedef struct {
+ avrcp_ct_play_status_t play_status;
+} avrcp_ct_play_status_val_t;
+
+/**
+ * @brief Enable AVRCP Ctroller Feature
+ *
+ * @remarks BT Profile AVRCP Controller will be able to connect.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre OAL API must be initialized with oal_bt_init().
+ *
+ * @see avrcp_ct_disable()
+ */
+oal_status_t avrcp_ct_enable(void);
+
+/**
+ * @brief Disable AVRCP Controller Feature
+ *
+ * @remarks BT Profile AVRCP Controller will be able to connect.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre Audio host should be enabled with avrcp_ct_enable().
+ *
+ * @see avrcp_ct_enable()
+ */
+oal_status_t avrcp_ct_disable(void);
+
+
+/**
+ * @brief Initiate a connection with a BT Sound device
+ *
+ * @details Result will be notified through an OAL event
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre BT Audio should be enabled with avrcp_ct_enable().
+ *
+ * @see OAL_EVENT_AVRCP_CT_CONNECTED
+ */
+
+oal_status_t avrcp_ct_connect(bt_address_t *device_address);
+
+
+/**
+ * @brief Remove a connection with a BT Sound device
+ *
+ * @details Result will be notified through an OAL event
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre BT Audio should be connected with a BT Sound device.
+ *
+ * @see OAL_EVENT_AVRCP_CT_DISCONNECTED
+ */
+
+oal_status_t avrcp_ct_disconnect(bt_address_t *device_address);
+
+/**
+ * @brief Play audio on the connected remote device.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_play(bt_address_t *device_address);
+
+/**
+ * @brief Stop audio on the connected remote device.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_stop(bt_address_t *device_address);
+
+/**
+ * @brief Pause audio on the connected remote device.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_pause(bt_address_t *device_address);
+
+/**
+ * @brief Fast Forward audio on the connected remote device.
+ *
+ * @remarks PRESS_STATE - Start Fast Forward
+ * RELEASE_STATE - Stop Fast Forward
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_fforward(bt_address_t *device_address, avrcp_ct_pass_state_t press_state);
+
+/**
+ * @brief Rewind audio on the connected remote device.
+ *
+ * @remarks PRESS_STATE - Start Rewind
+ * RELEASE_STATE - Stop Rewind
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_rewind(bt_address_t *device_address, avrcp_ct_pass_state_t press_state);
+
+/**
+ * @brief Play next track on the connected remote device.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_next_track(bt_address_t *device_address);
+
+
+/**
+ * @brief Play prev track on the connected remote device.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre A2DP Sink should be connected with a device.
+ * @pre AVRCP connection should exist with the device.
+ **/
+oal_status_t avrcp_ct_prev_track(bt_address_t *device_address);
+
+/**
+ * @brief Set media player properties to target device
+ *
+ * @remarks Target device will receive media player properties.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre OAL API must be initialize with avrcp_ct_enable().
+ *
+ */
+oal_status_t avrcp_ct_set_property(bt_address_t *device_address, avrcp_ct_player_property_type_t type, uint32_t value);
+
+/**
+ * @brief Get media player properties to target device
+ *
+ * @remarks Target device will send media player properties.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre OAL API must be initialize with avrcp_ct_enable().
+ *
+ */
+oal_status_t avrcp_ct_get_property(bt_address_t *device_address, avrcp_ct_player_property_type_t type, uint32_t *value);
+
+/**
+ * @brief Set media player properties to target device
+ *
+ * @remarks Target device will receive media player properties.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre OAL API must be initialize with avrcp_ct_enable().
+ *
+ */
+oal_status_t avrcp_ct_get_media_attribute(bt_address_t *device_address);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /*_OAL_AVRCP_CT_H_*/
--- /dev/null
+/*
+ * Open Adaptation Layer (OAL)
+ *
+ * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Nilesh Trimbake <t.shripati@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlog.h>
+#include <glib.h>
+
+#include <bluetooth.h>
+#include <bt_rc.h>
+
+#include "oal-internal.h"
+#include "oal-avrcp-ct.h"
+#include "oal-utils.h"
+#include "oal-common.h"
+
+#define CHECK_OAL_AVRCP_CTRL_ENABLED() \
+ do { \
+ if (avrcp_ct_interface == NULL) { \
+ BT_ERR("OAL, Audio Not Enabled"); \
+ return OAL_STATUS_NOT_READY; \
+ } \
+ } while (0)
+
+#define NO_OF_ATTRIBUTE 1
+
+typedef struct {
+ long int song_pos;
+ long int playing_time;
+ uint8_t title[BTRC_MAX_ATTR_STR_LEN];
+ uint8_t artist[BTRC_MAX_ATTR_STR_LEN];
+ uint8_t album[BTRC_MAX_ATTR_STR_LEN];
+ uint8_t genre[BTRC_MAX_ATTR_STR_LEN];
+ long int num_tracks;
+ uint32_t cur_track;
+} avrcp_ct_track_info_t;
+
+typedef struct {
+ int equalizer;
+ btrc_player_repeat_val_t repeat;
+ btrc_player_shuffle_val_t shuffle;
+ int scan;
+ btrc_play_status_t status;
+ unsigned int volume;
+} avrcp_ct_player_settings_t;
+
+const btrc_ctrl_interface_t * _bt_get_stack_interface(void);
+static const btrc_ctrl_interface_t *avrcp_ct_interface = NULL;
+
+static void cb_avrcp_ct_connection_state(bool rc_connect, bool bt_connect, bt_bdaddr_t* bd_addr);
+static void cb_avrcp_ct_btrc_playerapplicationsetting_changed (bt_bdaddr_t *bd_addr, btrc_player_settings_t *p_vals);
+static void cb_avrcp_ct_btrc_play_position_changed (bt_bdaddr_t *bd_addr, uint32_t song_len, uint32_t song_pos);
+static void cb_avrcp_ct_btrc_play_status_changed (bt_bdaddr_t *bd_addr, btrc_play_status_t play_status);
+static void cb_avrcp_ct_trak_info_chnaged (bt_bdaddr_t *bd_address, uint8_t num_attr, btrc_element_attr_val_t *p_attrs);
+static void cb_avrcp_ct_btrc_passthrough_rsp (bt_bdaddr_t *bd_addr, int id, int key_state);
+static void cb_avrcp_ct_btrc_setplayerapplicationsetting_rsp (bt_bdaddr_t *bd_addr, uint8_t accepted);
+
+static avrcp_ct_track_info_t track_info;
+static avrcp_ct_player_settings_t player_setting;
+
+/** AVRCP Controller callback structure. */
+static btrc_ctrl_callbacks_t avrcp_ct_cb = {
+ /** set to sizeof(BtRcCallbacks) */
+ sizeof(avrcp_ct_cb),
+ cb_avrcp_ct_btrc_passthrough_rsp,
+ NULL, //cb_avrcp_ct_btrc_groupnavigation_rsp,
+ cb_avrcp_ct_connection_state,
+ NULL,/*btrc_ct_getrcfeatures_callback*/
+ cb_avrcp_ct_btrc_setplayerapplicationsetting_rsp,
+ NULL, /*btrc_ct_playerapplicationsetting_callback*/
+ cb_avrcp_ct_btrc_playerapplicationsetting_changed,
+ NULL, /*btrc_ct_setabsvol_cmd_callback*/
+ NULL, /*btrc_ct_registernotification_abs_vol_callback*/
+ cb_avrcp_ct_trak_info_chnaged,
+ cb_avrcp_ct_btrc_play_position_changed,
+ cb_avrcp_ct_btrc_play_status_changed,
+ NULL, /*btrc_ct_get_folder_items_callback*/
+ NULL, /*btrc_ct_change_path_callback*/
+ NULL, /*btrc_ct_set_browsed_player_callback*/
+ NULL /*btrc_ct_set_addressed_player_callback*/
+};
+
+
+oal_status_t avrcp_ct_enable(void)
+{
+ const bt_interface_t* blued_inf;
+ int ret;
+
+ API_TRACE("AVRCP Controller Enable");
+
+ if ( (blued_inf = adapter_get_stack_interface()) == NULL) {
+ BT_ERR("Bluetooth module is not loaded");
+ return OAL_STATUS_NOT_READY;
+ }
+
+ if (avrcp_ct_interface != NULL) {
+ BT_WARN("AVRCP Controller Interface is already initialized...");
+ return OAL_STATUS_ALREADY_DONE;
+ }
+
+ if ( (avrcp_ct_interface = (const btrc_ctrl_interface_t *)blued_inf->get_profile_interface(BT_PROFILE_AV_RC_CTRL_ID)) == NULL) {
+ BT_ERR("OAL, Failed to get Bluetooth AVRCP Controller Interface");
+ return OAL_STATUS_INTERNAL_ERROR;
+ }
+
+ BT_DBG("Got profile interface");
+ if ( (ret = avrcp_ct_interface->init(&avrcp_ct_cb)) != BT_STATUS_SUCCESS) {
+ BT_ERR("Failed to initialize Bluetooth AVRCP Controller, status: %s", status2string(ret));
+ avrcp_ct_interface = NULL;
+ return convert_to_oal_status(ret);
+ }
+ BT_DBG("OAL, Bluetooth avrcp controller interface initialised");
+
+ return OAL_STATUS_SUCCESS;
+}
+
+/* Audio deinit: Resets all the audio information
+ * Note: Adapter should be disabled before calling deinit
+ * */
+oal_status_t avrcp_ct_disable(void)
+{
+ API_TRACE("AVRCP Controller Disable");
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+
+ avrcp_ct_interface->cleanup();
+ avrcp_ct_interface = NULL;
+
+ return OAL_STATUS_SUCCESS;
+}
+
+void avrcp_ct_cleanup(void)
+{
+ BT_DBG();
+ avrcp_ct_interface = NULL;
+}
+
+
+oal_status_t avrcp_ct_connect(bt_address_t *device_address)
+{
+ int result = OAL_STATUS_SUCCESS;
+ bt_status_t status;
+ bdstr_t bdstr;
+
+ API_TRACE();
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+ OAL_CHECK_PARAMETER(device_address, return);
+
+ BT_INFO("BT Audio Address: %s", bdt_bd2str(device_address, &bdstr));
+
+ status = avrcp_ct_interface->connect((bt_bdaddr_t *)device_address);
+ if((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
+ BT_ERR("Connection could not be established, err: %s", status2string(status));;
+ result = convert_to_oal_status(status);
+ }
+ return result;
+}
+
+oal_status_t avrcp_ct_disconnect( bt_address_t *device_address )
+{
+ int result = OAL_STATUS_SUCCESS;
+ bdstr_t bdstr;
+ bt_status_t status;
+
+ API_TRACE();
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+ OAL_CHECK_PARAMETER(device_address, return);
+
+ BT_INFO("BT Audio Address: %s", bdt_bd2str(device_address, &bdstr));
+
+ status = avrcp_ct_interface->disconnect((bt_bdaddr_t *)device_address);
+ if((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
+ BT_ERR("OAL, Disconnection failed err: %s", status2string(status));
+ result = convert_to_oal_status(status);
+ }
+ return result;
+}
+
+static void cb_avrcp_ct_connection_state(bool rc_connect, bool bt_connect, bt_bdaddr_t* bd_addr)
+{
+ bt_address_t * event_data = NULL;
+ bdstr_t bdstr;
+ oal_event_t event;
+
+ ret_if(bd_addr == NULL);
+ BT_INFO("rc_connect = %d, bt_connect = %d, BT Address = %s",
+ rc_connect, bt_connect, bdt_bd2str((bt_address_t*)bd_addr, &bdstr));
+
+ event_data = g_new0(bt_address_t, 1);
+ memcpy(event_data->addr, bd_addr->address, BT_ADDRESS_BYTES_NUM);
+
+ switch(rc_connect) {
+ case BTRC_CONNECTION_STATE_CONNECTED:
+ event = OAL_EVENT_AVRCP_CTRL_CONNECTED;
+ break;
+ case BTRC_CONNECTION_STATE_DISCONNECTED:
+ event = OAL_EVENT_AVRCP_CTRL_DISCONNECTED;
+ break;
+ default:
+ BT_INFO("Invalid state");
+ g_free(event_data);
+ event_data = NULL;
+ return;
+ }
+ send_event_bda_trace(event, event_data, sizeof(bt_address_t), (bt_address_t*)bd_addr);
+}
+
+avrcp_ct_play_status_t __hal_to_oal_play_status(btrc_play_status_t play_status)
+{
+ avrcp_ct_play_status_t status = OAL_PLAYSTATE_ERROR;
+ switch(play_status) {
+ case BTRC_PLAYSTATE_STOPPED:
+ status = OAL_PLAYSTATE_STOPPED;
+ break;
+ case BTRC_PLAYSTATE_PLAYING:
+ status = OAL_PLAYSTATE_PLAYING;
+ break;
+ case BTRC_PLAYSTATE_PAUSED:
+ status = OAL_PLAYSTATE_PAUSED;
+ break;
+ case BTRC_PLAYSTATE_FWD_SEEK:
+ status = OAL_PLAYSTATE_FWD_SEEK;
+ break;
+ case BTRC_PLAYSTATE_REV_SEEK:
+ status = OAL_PLAYSTATE_REV_SEEK;
+ break;
+ default :
+ BT_INFO("Incorrect Play status");
+ break;
+ }
+ return status;
+}
+
+static void cb_avrcp_ct_btrc_playerapplicationsetting_changed(
+ bt_bdaddr_t *bd_addr, btrc_player_settings_t *p_vals)
+{
+ avrcp_ct_property_value_t *event_data = NULL;
+ oal_event_t event;
+ int i;
+
+ for (i = 0; i < p_vals->num_attr; i++) {
+ event_data = g_new0(avrcp_ct_property_value_t, 1);
+
+ switch(p_vals->attr_ids[i]) {
+ case BTRC_PLAYER_ATTR_EQUALIZER:
+ event = OAL_EVENT_AVRCP_CTRL_EQUALIZER_STATUS;
+ event_data->value = p_vals->attr_values[i];
+ player_setting.equalizer = p_vals->attr_values[i];
+ break;
+ case BTRC_PLAYER_ATTR_REPEAT:
+ event = OAL_EVENT_AVRCP_CTRL_REPEAT_STATUS;
+ event_data->value = p_vals->attr_values[i];
+ player_setting.repeat = p_vals->attr_values[i];
+ break;
+ case BTRC_PLAYER_ATTR_SHUFFLE:
+ event = OAL_EVENT_AVRCP_CTRL_SHUFFLE_STATUS;
+ event_data->value = p_vals->attr_values[i];
+ player_setting.shuffle = p_vals->attr_values[i];
+ break;
+ case BTRC_PLAYER_ATTR_SCAN:
+ event = OAL_EVENT_AVRCP_CTRL_SCAN_STATUS;
+ event_data->value = p_vals->attr_values[i];
+ player_setting.scan = p_vals->attr_values[i];
+ break;
+ default :
+ event = OAL_EVENT_END;
+ break;
+ }
+
+ if (OAL_EVENT_END != event)
+ send_event(event, event_data, sizeof(avrcp_ct_property_value_t *));
+ }
+}
+
+static void cb_avrcp_ct_btrc_play_position_changed (bt_bdaddr_t *bd_addr, uint32_t song_len, uint32_t song_pos)
+{
+ avrcp_ct_play_position_t *event_data = NULL;
+
+ event_data = g_new0(avrcp_ct_play_position_t, 1);
+ event_data->song_len = track_info.playing_time;
+ event_data->song_pos = song_pos;
+ track_info.song_pos = song_pos;
+ send_event(OAL_EVENT_AVRCP_CTRL_PLAY_POSITION_STATUS, event_data, sizeof(avrcp_ct_play_position_t *));
+}
+
+static void cb_avrcp_ct_btrc_play_status_changed (bt_bdaddr_t *bd_addr, btrc_play_status_t play_status)
+{
+ avrcp_ct_play_status_val_t *event_data = NULL;
+
+ event_data = g_new0(avrcp_ct_play_status_val_t, 1);
+ event_data->play_status = __hal_to_oal_play_status(play_status);
+ player_setting.status = play_status;
+ send_event(OAL_EVENT_AVRCP_CTRL_PLAY_STATUS_CHANGED, event_data, sizeof(avrcp_ct_play_status_val_t *));
+}
+
+static void cb_avrcp_ct_btrc_passthrough_rsp (bt_bdaddr_t *bd_addr, int id, int state)
+{
+ avrcp_ct_pass_cmd_key_code_t key_code;
+ avrcp_ct_pass_state_t key_state;
+ avrcp_ct_pass_cmd_t *event_data;
+
+ event_data = g_new0(avrcp_ct_pass_cmd_t, 1);
+
+ key_code = id;
+ key_state = state;
+ if(key_code) {
+ event_data->key_code = key_code;
+ event_data->key_state = key_state;
+ send_event(OAL_EVENT_AVRCP_CTRL_PASS_CMD_RES, event_data, sizeof(avrcp_ct_pass_cmd_t *));
+ } else {
+ BT_ERR("Invalid pass through command key code");
+ }
+}
+
+static void cb_avrcp_ct_btrc_setplayerapplicationsetting_rsp (bt_bdaddr_t *bd_addr, uint8_t accepted)
+{
+ avrcp_ct_playersetting_t *event_data;
+
+ event_data = g_new0(avrcp_ct_playersetting_t, 1);
+
+ event_data->accepted = accepted;
+ send_event(OAL_EVENT_AVRCP_CTRL_PLAYER_SETTING_RES, event_data, sizeof(avrcp_ct_playersetting_t *));
+}
+
+static void cb_avrcp_ct_trak_info_chnaged(bt_bdaddr_t *device_address, uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+{
+ int idx =0;
+ avrcp_ct_media_metadata_attr_t *event_data = NULL;
+ event_data = g_new0(avrcp_ct_media_metadata_attr_t, 1);
+
+ for(idx=0; idx < num_attr; idx++) {
+ BT_INFO("idx [%d]", p_attrs[idx].attr_id);
+
+ switch(p_attrs[idx].attr_id) {
+ case BTRC_MEDIA_ATTR_ID_TITLE:
+ event_data->title = g_strdup((const char*)&p_attrs[idx].text);
+ g_strlcpy((gchar *)track_info.title, event_data->title, BTRC_MAX_ATTR_STR_LEN);
+ break;
+ case BTRC_MEDIA_ATTR_ID_ARTIST:
+ event_data->artist = g_strdup((const char*)&p_attrs[idx].text);
+ g_strlcpy((gchar *)track_info.artist, event_data->artist, BTRC_MAX_ATTR_STR_LEN);
+ break;
+ case BTRC_MEDIA_ATTR_ID_ALBUM:
+ event_data->album = g_strdup((const char*)&p_attrs[idx].text);
+ g_strlcpy((gchar *)track_info.album, event_data->album, BTRC_MAX_ATTR_STR_LEN);
+ break;
+ case BTRC_MEDIA_ATTR_ID_GENRE:
+ event_data->genre = g_strdup((const char*)&p_attrs[idx].text);
+ g_strlcpy((gchar *)track_info.genre, event_data->genre, BTRC_MAX_ATTR_STR_LEN);
+ break;
+ case BTRC_MEDIA_ATTR_ID_NUM_TRACKS:
+ if(p_attrs[idx].text != NULL) {
+ event_data->total_tracks = g_ascii_strtoll((const gchar *)p_attrs[idx].text, NULL, 10);
+ track_info.num_tracks = event_data->total_tracks;
+ } else {
+ BT_WARN("string is null!!!!!!!");
+ }
+ break;
+ case BTRC_MEDIA_ATTR_ID_TRACK_NUM:
+ if(p_attrs[idx].text != NULL) {
+ event_data->number = g_ascii_strtoll((const gchar *)p_attrs[idx].text, NULL, 10);
+ track_info.cur_track = event_data->number;
+ } else {
+ BT_WARN("string is null!!!!!!!");
+ }
+ break;
+ case BTRC_MEDIA_ATTR_ID_PLAYING_TIME:
+ if(p_attrs[idx].text != NULL) {
+ event_data->duration = g_ascii_strtoll((const gchar *)p_attrs[idx].text, NULL, 10);
+ track_info.playing_time = event_data->duration;
+ } else {
+ BT_WARN("string is null!!!!!!!");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ send_event(OAL_EVENT_AVRCP_CTRL_TRACK_INFO_CHANGED, event_data, sizeof(avrcp_ct_media_metadata_attr_t *));
+ return;
+}
+
+oal_status_t __avrcp_ct_send_pass_through_cmd(bt_address_t *device_address,
+ avrcp_ct_pass_cmd_key_code_t key_code, avrcp_ct_pass_state_t key_state)
+{
+ int result = OAL_STATUS_SUCCESS;
+ bt_status_t status;
+ bdstr_t bdstr;
+
+ API_TRACE();
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+
+ BT_INFO("BT Audio Address: %s", bdt_bd2str(device_address, &bdstr));
+
+ status = avrcp_ct_interface->send_pass_through_cmd((bt_bdaddr_t *)device_address,
+ key_code, key_state);
+ if((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
+ BT_ERR("OAL, send pass through cmd failed err: %s", status2string(status));
+ result = convert_to_oal_status(status);
+ }
+ return result;
+}
+
+oal_status_t avrcp_ct_play(bt_address_t *device_address)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_PLAY, PRESS_STATE);
+
+ return result;
+}
+
+oal_status_t avrcp_ct_pause(bt_address_t *device_address)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_PAUSE, PRESS_STATE);
+
+ return result;
+}
+
+oal_status_t avrcp_ct_stop(bt_address_t *device_address)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_STOP, PRESS_STATE);
+
+ return result;
+}
+
+oal_status_t avrcp_ct_next_track(bt_address_t *device_address)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_NEXT, PRESS_STATE);
+
+ return result;
+}
+
+oal_status_t avrcp_ct_prev_track(bt_address_t *device_address)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_PREVIOUS, PRESS_STATE);
+
+ return result;
+}
+
+oal_status_t avrcp_ct_fforward(bt_address_t *device_address, avrcp_ct_pass_state_t press_state)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+ switch (press_state) {
+ case PRESS_STATE:
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_PRESS_FAST_FORWARD, press_state);
+ break;
+ case RELEASE_STATE:
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_RELEASE_FAST_FORWARD, press_state);
+ break;
+ default :
+ result = OAL_STATUS_INVALID_PARAM;
+ break;
+ }
+
+ return result;
+}
+
+oal_status_t avrcp_ct_rewind(bt_address_t *device_address, avrcp_ct_pass_state_t press_state)
+{
+ oal_status_t result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+ switch (press_state) {
+ case PRESS_STATE:
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_PRESS_REWIND, press_state);
+ break;
+ case RELEASE_STATE:
+ result = __avrcp_ct_send_pass_through_cmd(device_address,
+ OAL_RC_PASS_CMD_RELEASE_REWIND, press_state);
+ break;
+ default :
+ result = OAL_STATUS_INVALID_PARAM;
+ break;
+ }
+
+ return result;
+}
+
+uint8_t __oal_to_hal_property_type(avrcp_ct_player_property_type_t type)
+{
+ uint8_t property_type = 0;
+
+ switch (type) {
+ case OAL_EQUALIZER:
+ property_type = BTRC_PLAYER_ATTR_EQUALIZER;
+ break;
+ case OAL_REPEAT:
+ property_type = BTRC_PLAYER_ATTR_REPEAT;
+ break;
+ case OAL_SHUFFLE:
+ property_type = BTRC_PLAYER_ATTR_SHUFFLE;
+ break;
+ case OAL_SCAN:
+ property_type = BTRC_PLAYER_ATTR_SCAN;
+ break;
+ default:
+ BT_ERR(" Invalid Property type[%d]", type);
+ break;
+ }
+
+ return property_type;
+}
+
+oal_status_t avrcp_ct_set_property( bt_address_t *device_address, avrcp_ct_player_property_type_t type, uint32_t value)
+{
+ int result = OAL_STATUS_SUCCESS;
+ uint8_t property_type;
+ bt_status_t status;
+ bdstr_t bdstr;
+
+ API_TRACE();
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+ BT_INFO("BT Audio Address: %s", bdt_bd2str(device_address, &bdstr));
+
+ property_type = __oal_to_hal_property_type(type);
+ if (property_type) {
+ status = avrcp_ct_interface->set_player_app_setting_cmd((bt_bdaddr_t *)device_address, NO_OF_ATTRIBUTE,
+ (uint8_t* )&property_type, (uint8_t* )&value);
+ if((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
+ BT_ERR("OAL, Set property failed err: %s", status2string(status));
+ result = convert_to_oal_status(status);
+ }
+ } else {
+ result = OAL_STATUS_INTERNAL_ERROR;
+ }
+ return result;
+}
+
+oal_status_t avrcp_ct_get_property( bt_address_t *device_address, avrcp_ct_player_property_type_t type, uint32_t *value)
+{
+ int result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+
+ switch (type) {
+ case OAL_EQUALIZER:
+ *value = player_setting.equalizer;
+ break;
+ case OAL_REPEAT:
+ *value = player_setting.repeat;
+ break;
+ case OAL_SHUFFLE:
+ *value = player_setting.shuffle;
+ break;
+ case OAL_SCAN:
+ *value = player_setting.scan;
+ break;
+ case OAL_PLAY_STATUS:
+ *value = player_setting.status;
+ break;
+ case OAL_PLAY_POSITION:
+ *value = track_info.song_pos;
+ break;
+ default:
+ BT_ERR("Invalid Type [%d]", type);
+ result = OAL_STATUS_INVALID_PARAM;
+ }
+
+ return result;
+}
+
+gboolean __send_media_attribute_event()
+{
+ avrcp_ct_media_metadata_attr_t *event_data = NULL;
+
+ event_data = g_new0(avrcp_ct_media_metadata_attr_t, 1);
+
+ event_data->title = g_strdup((gchar *)track_info.title);
+ event_data->artist = g_strdup((gchar *)track_info.artist);
+ event_data->album = g_strdup((gchar *)track_info.album);
+ event_data->genre = g_strdup((gchar *)track_info.genre);
+ event_data->total_tracks = track_info.num_tracks;
+ event_data->number = track_info.cur_track;
+ event_data->duration = track_info.playing_time;
+
+ send_event(OAL_EVENT_AVRCP_CTRL_TRACK_INFO, event_data, sizeof(avrcp_ct_media_metadata_attr_t *));
+
+ return FALSE;
+}
+
+oal_status_t avrcp_ct_get_media_attribute(bt_address_t *device_address)
+{
+ int result = OAL_STATUS_SUCCESS;
+
+ API_TRACE();
+
+ CHECK_OAL_AVRCP_CTRL_ENABLED();
+
+ OAL_CHECK_PARAMETER(device_address, return);
+
+ g_idle_add(__send_media_attribute_event,NULL);
+ return result;
+}