[Adapt: Frwk] Implement AVRCP Controller role in bt-service 32/116932/2
authorNilesh Trimbake <t.shripati@samsung.com>
Wed, 8 Feb 2017 12:49:16 +0000 (18:19 +0530)
committerNilesh Trimbake <t.shripati@samsung.com>
Thu, 2 Mar 2017 09:41:44 +0000 (15:11 +0530)
    This patch handles following:-
        a/ AVRCP Target Connect
        b/ AVRCP Target Disconnect
        c/ AVRCP Target Connection handler states
        d/ Send command, get track info, set property

Change-Id: Ib8d3a138b1d1a2458597ccd4a0034b0462b9ea57
Signed-off-by: Nilesh Trimbake <t.shripati@samsung.com>
bt-service-adaptation/CMakeLists.txt
bt-service-adaptation/services/adapter/bt-service-core-adapter.c
bt-service-adaptation/services/audio/avrcp_ctrl/bt-service-avrcp-ctrl.c [new file with mode: 0644]
bt-service-adaptation/services/audio/bt-service-audio.c
bt-service-adaptation/services/bt-request-handler.c
bt-service-adaptation/services/bt-service-event-receiver.c
bt-service-adaptation/services/bt-service-event-sender.c
bt-service-adaptation/services/include/bt-service-avrcp-ctrl.h [new file with mode: 0644]
bt-service-adaptation/services/include/bt-service-event-receiver.h

index 482df7a..cbfbb8e 100644 (file)
@@ -22,6 +22,7 @@ marshal.c
 ./services/audio/a2dp_src/bt-service-a2dp-src.c
 ./services/audio/a2dp_sink/bt-service-a2dp-sink.c
 ./services/health/bt-service-hdp.c
+./services/audio/avrcp_ctrl/bt-service-avrcp-ctrl.c
 )
 
 IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
index 321f536..a0db55e 100644 (file)
@@ -722,7 +722,12 @@ static int __bt_init_profiles()
                BT_ERR("_bt_audio_initialize(BT_AG_MODULE) Failed");
                return ret;
        }
-
+       /* Initialize AVRCP Controller */
+       ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("_bt_audio_initialize(BT_AVRCP_CTRL_MODULE) Failed");
+               return ret;
+       }
        /* Registering callback for receiving audio services searched */
        ret = _bt_audio_initialize(BT_AUDIO_ALL_MODULE);
        if (ret != BLUETOOTH_ERROR_NONE) {
diff --git a/bt-service-adaptation/services/audio/avrcp_ctrl/bt-service-avrcp-ctrl.c b/bt-service-adaptation/services/audio/avrcp_ctrl/bt-service-avrcp-ctrl.c
new file mode 100644 (file)
index 0000000..6663118
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <vconf.h>
+
+#include "oal-hardware.h"
+#include "oal-device-mgr.h"
+#include <oal-manager.h>
+#include <oal-avrcp-ct.h>
+
+#include <bt-service-avrcp-ctrl.h>
+#include <bluetooth-media-control.h>
+#include <bt-service-event.h>
+
+int _bt_avrcp_connect_remote_target(bluetooth_device_address_t *device_address)
+{
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+
+       status = avrcp_ct_connect((bt_address_t*)device_address);
+       if (status != OAL_STATUS_SUCCESS) {
+               BT_ERR("Connection could not be established, err: [%d]", status);
+               result = BLUETOOTH_ERROR_INTERNAL;
+       }
+       return result;
+}
+
+int _bt_avrcp_disconnect_remote_target(bluetooth_device_address_t *device_address)
+{
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+
+       status = avrcp_ct_disconnect((bt_address_t*)device_address);
+       if (status != OAL_STATUS_SUCCESS) {
+               BT_ERR("DisConnection err: [%d]", status);
+               result = BLUETOOTH_ERROR_INTERNAL;
+       }
+       return result;
+}
+
+int _bt_avrcp_control_cmd(int type)
+{
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+       gboolean connected;
+       bluetooth_device_address_t device_address;
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+
+       connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
+
+       if (connected) {
+               _bt_convert_addr_string_to_type(device_address.addr,
+                               connected_address);
+               switch(type) {
+               case RC_PASS_CMD_PLAY:
+                       status = avrcp_ct_play((bt_address_t*)&device_address);
+                       break;
+               case RC_PASS_CMD_PAUSE:
+                       status = avrcp_ct_pause((bt_address_t*)&device_address);
+                       break;
+               case RC_PASS_CMD_STOP:
+                       status = avrcp_ct_stop((bt_address_t*)&device_address);
+                       break;
+               case RC_PASS_CMD_NEXT:
+                       status = avrcp_ct_next_track((bt_address_t*)&device_address);
+                       break;
+               case RC_PASS_CMD_PREVIOUS:
+                       status = avrcp_ct_prev_track((bt_address_t*)&device_address);
+                       break;
+               case RC_PASS_CMD_PRESS_FAST_FORWARD:
+                       status = avrcp_ct_fforward((bt_address_t*)&device_address, PRESS_STATE);
+                       break;
+               case RC_PASS_CMD_RELEASE_FAST_FORWARD:
+                       status = avrcp_ct_fforward((bt_address_t*)&device_address, RELEASE_STATE);
+                       break;
+               case RC_PASS_CMD_PRESS_REWIND:
+                       status = avrcp_ct_rewind((bt_address_t*)&device_address, PRESS_STATE);
+                       break;
+               case RC_PASS_CMD_RELEASE_REWIND:
+                       status = avrcp_ct_rewind((bt_address_t*)&device_address, RELEASE_STATE);
+                       break;
+               default:
+                       break;
+               }
+
+               if (status != OAL_STATUS_SUCCESS) {
+                       BT_ERR("Send pass through command err: [%d]", status);
+                       result = BLUETOOTH_ERROR_INTERNAL;
+               }
+       } else {
+               BT_ERR("Device is not connected:");
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+
+       return result;
+}
+
+int _bt_avrcp_control_set_property(int type, unsigned int value)
+{
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+       gboolean connected;
+       bluetooth_device_address_t device_address;
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+       connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
+
+       if (connected) {
+               _bt_convert_addr_string_to_type(device_address.addr,
+                               connected_address);
+               status = avrcp_ct_set_property((bt_address_t*)&device_address,
+                               type, value);
+               if (status != OAL_STATUS_SUCCESS) {
+                       BT_ERR("Set peoperty err: [%d]", status);
+                       result = BLUETOOTH_ERROR_INTERNAL;
+               }
+       } else {
+               BT_ERR("Device is not connected:");
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+       return result;
+}
+
+int _bt_avrcp_control_get_property(int type, unsigned int *value)
+{
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+       gboolean connected;
+       bluetooth_device_address_t device_address;
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+       connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
+
+       if (connected) {
+               avrcp_ct_player_property_type_t oal_type;
+
+               _bt_convert_addr_string_to_type(
+                               device_address.addr,
+                               connected_address);
+
+               switch (type) {
+               case EQUALIZER:
+                       oal_type = OAL_EQUALIZER;
+                       break;
+               case SHUFFLE:
+                       oal_type = OAL_SHUFFLE;
+                       break;
+               case REPEAT:
+                       oal_type = OAL_REPEAT;
+                       break;
+               case SCAN:
+                       oal_type = OAL_SCAN;
+                       break;
+               case POSITION:
+                       oal_type = OAL_PLAY_POSITION;
+                       break;
+               case STATUS:
+                       oal_type = OAL_PLAY_STATUS;
+                       break;
+               default:
+                       return BLUETOOTH_ERROR_INTERNAL;
+               }
+
+               status = avrcp_ct_get_property((bt_address_t*)&device_address,
+                               oal_type, value);
+               if (status != OAL_STATUS_SUCCESS) {
+                       BT_ERR("Get peoperty err: [%d]", status);
+                       result = BLUETOOTH_ERROR_INTERNAL;
+               }
+       } else {
+               BT_ERR("Device is not connected:");
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+       return result;
+}
+
+int _bt_avrcp_control_get_track_info(void)
+{
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+       gboolean connected;
+       bluetooth_device_address_t device_address;
+       oal_status_t status = OAL_STATUS_SUCCESS;
+       int result = BLUETOOTH_ERROR_NONE;
+       BT_INFO("+");
+       connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
+
+       if (connected) {
+               _bt_convert_addr_string_to_type(
+                               device_address.addr,
+                               connected_address);
+
+               status = avrcp_ct_get_media_attribute((bt_address_t*)&device_address);
+               if (status != OAL_STATUS_SUCCESS) {
+                       BT_ERR("Get track info err: [%d]", status);
+                       result = BLUETOOTH_ERROR_INTERNAL;
+               }
+       } else {
+               BT_ERR("Device is not connected:");
+               return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
+       return result;
+}
+
+static void __bt_reply_avrcp_ct_connection_pending_request(bluetooth_device_address_t *address)
+{
+       BT_DBG("+");
+       char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+       int result = BLUETOOTH_ERROR_NONE;
+       bluetooth_device_address_t device_address;
+       GArray *out_param;
+       invocation_info_t *req_info;
+       memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH);
+       _bt_convert_addr_type_to_string(addr, address->addr);
+
+       req_info = _bt_get_request_info_data(BT_AVRCP_CONTROL_CONNECT, addr);
+       if (NULL == req_info) {
+               BT_INFO("AVRCP CT Connect request not found or possibly already replied");
+               return;
+       } else {
+               BT_INFO("AVRCP CT Connect request found for [%s]", addr);
+       }
+
+       out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+       g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
+       _bt_service_method_return(req_info->context,
+                       out_param, result);
+       g_array_free(out_param, TRUE);
+       g_free(req_info->user_data);
+       _bt_free_info_from_invocation_list(req_info);
+}
+
+static void __bt_handle_avrcp_target_connected_state(bluetooth_device_address_t *address)
+{
+       char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+       GVariant *param;
+       int result = BLUETOOTH_ERROR_NONE;
+       ret_if(NULL == address);
+       BT_INFO("+");
+
+       _bt_convert_addr_type_to_string(addr, address->addr);
+       BT_INFO("Address of connected device [%s]", addr);
+
+       /* Add data from the connected list */
+       _bt_add_headset_to_list(BT_AVRCP, BT_STATE_CONNECTED, addr);
+
+       /* Replay to avrcp cotroller connect */
+       __bt_reply_avrcp_ct_connection_pending_request(address);
+
+       /* Send AVRCP(TARGET Role) connected event to Application */
+       param = g_variant_new("(is)", result, addr);
+       _bt_send_event(BT_AVRCP_CONTROL_EVENT, BLUETOOTH_EVENT_AVRCP_CONNECTED, param);
+
+       BT_INFO("-");
+}
+
+static void __bt_reply_avrcp_ct_disconnection_pending_request(bluetooth_device_address_t *address)
+{
+       char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+       int result = BLUETOOTH_ERROR_NONE;
+       GArray *out_param;
+       invocation_info_t *req_info;
+
+       BT_DBG("+");
+       _bt_convert_addr_type_to_string(addr, address->addr);
+
+       req_info = _bt_get_request_info_data(BT_AVRCP_CONTROL_DISCONNECT, addr);
+       if (NULL == req_info) {
+               BT_INFO("AVRCP CT Disconnect request not found or possibly already replied");
+               return;
+       } else {
+               BT_INFO("AVRCP CT Disconnect request found for [%s]", addr);
+       }
+
+       out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+       g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
+       _bt_service_method_return(req_info->context,
+                       out_param, result);
+       g_array_free(out_param, TRUE);
+       g_free(req_info->user_data);
+       _bt_free_info_from_invocation_list(req_info);
+}
+
+static void __bt_handle_avrcp_target_disconnected_state(bluetooth_device_address_t *address)
+{
+       char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+       GVariant *param;
+       int result = BLUETOOTH_ERROR_NONE;
+       ret_if(NULL == address);
+       BT_INFO("+");
+
+       _bt_convert_addr_type_to_string(addr, address->addr);
+       BT_INFO("Address of disconnected device [%s]", addr);
+
+       /* Remove data from the connected list */
+       _bt_remove_headset_from_list(BT_AVRCP, addr);
+
+       /* Replay to avrcp cotroller connect */
+       __bt_reply_avrcp_ct_disconnection_pending_request(address);
+
+       /* Send AVRCP(TARGET Role) disconnected event to Application */
+       param = g_variant_new("(is)", result, addr);
+       _bt_send_event(BT_AVRCP_CONTROL_EVENT, BLUETOOTH_EVENT_AVRCP_DISCONNECTED, param);
+
+       BT_INFO("-");
+}
+
+static int __bt_oal_to_bt_event(int oal_event)
+{
+       int ret =0;
+
+       switch(oal_event) {
+               case OAL_EVENT_AVRCP_CTRL_EQUALIZER_STATUS:
+                       ret = BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_REPEAT_STATUS:
+                       ret = BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_SHUFFLE_STATUS:
+                       ret = BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_SCAN_STATUS:
+                       ret = BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_PLAY_POSITION_STATUS:
+                       ret = BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_PLAY_STATUS_CHANGED:
+                       ret = BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
+                       break;
+               case OAL_EVENT_AVRCP_CTRL_TRACK_INFO_CHANGED:
+                       ret = BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
+                       break;
+               default:
+                       break;
+       }
+       return ret;
+}
+
+static void __bt_handle_avrcp_target_player_property(unsigned int property_value, int oal_event)
+{
+       GVariant *param;
+       BT_INFO("+");
+       /* Send AVRCP Target player property event to Application */
+       param = g_variant_new("(u)", property_value);
+       _bt_send_event(BT_AVRCP_CONTROL_EVENT,
+                       __bt_oal_to_bt_event(oal_event), param);
+}
+
+static void __bt_handle_avrcp_track_info_changed(avrcp_ct_media_metadata_attr_t* metadata)
+{
+       GVariant *param;
+
+       BT_INFO("+");
+       /* Send AVRCP Target player track info changed event to application*/
+       param = g_variant_new("(ssssuuu)",
+                       metadata->title,
+                       metadata->artist,
+                       metadata->album,
+                       metadata->genre,
+                       metadata->total_tracks,
+                       metadata->number,
+                       metadata->duration);
+       _bt_send_event(BT_AVRCP_CONTROL_EVENT,
+                       BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
+}
+
+static invocation_info_t* __bt_get_request_info(int service_function)
+{
+       GSList *l;
+       invocation_info_t *req_info = NULL;
+
+       BT_DBG("+");
+       /* Get method invocation context */
+       for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
+               req_info = l->data;
+               if (req_info == NULL || req_info->service_function != service_function)
+                       continue;
+               return req_info;
+       }
+       return NULL;
+}
+
+static void __bt_handle_avrcp_track_info(avrcp_ct_media_metadata_attr_t* metadata)
+{
+       media_metadata_t meta_data;
+       invocation_info_t *req_info = NULL;
+       GArray *out_param = NULL;
+       int result = BLUETOOTH_ERROR_NONE;
+
+       memset(&meta_data, 0x00, sizeof(media_metadata_t));
+
+       if (_bt_copy_utf8_string(meta_data.title, metadata->title,
+                               BT_META_DATA_MAX_LEN))
+               BT_ERR("Error in copying Title\n");
+       if (_bt_copy_utf8_string(meta_data.artist, metadata->artist,
+                               BT_META_DATA_MAX_LEN))
+               BT_ERR("Error in copying Artist\n");
+       if (_bt_copy_utf8_string(meta_data.album, metadata->album,
+                               BT_META_DATA_MAX_LEN))
+               BT_ERR("Error in copying Album\n");
+       if (_bt_copy_utf8_string(meta_data.genre, metadata->genre,
+                               BT_META_DATA_MAX_LEN))
+               BT_ERR("Error in copying Genre\n");
+
+       if (_bt_utf8_validate(meta_data.title) == FALSE)
+               meta_data.title[0] = '\0';
+
+       if (_bt_utf8_validate(meta_data.artist) == FALSE)
+               meta_data.artist[0] = '\0';
+
+       if (_bt_utf8_validate(meta_data.album) == FALSE)
+               meta_data.album[0] = '\0';
+
+       if (_bt_utf8_validate(meta_data.genre) == FALSE)
+               meta_data.genre[0] = '\0';
+       meta_data.total_tracks = metadata->total_tracks;
+       meta_data.number = metadata->number;
+       meta_data.duration = metadata->duration;
+
+       g_free((gpointer)metadata->title);
+       g_free((gpointer)metadata->artist);
+       g_free((gpointer)metadata->album);
+       g_free((gpointer)metadata->genre);
+
+       req_info = __bt_get_request_info(BT_AVRCP_GET_TRACK_INFO);
+
+       out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+       g_array_append_vals(out_param, &meta_data,
+                       sizeof(media_metadata_t));
+
+       _bt_service_method_return(req_info->context, out_param, result);
+       g_array_free(out_param, TRUE);
+       _bt_free_info_from_invocation_list(req_info);
+}
+
+static void __bt_handle_avrcp_pass_cmd_res(avrcp_ct_pass_cmd_t *pass_cmd)
+{
+       BT_INFO(" Send Command Response [%d]", pass_cmd->key_code);
+}
+
+static void __bt_handle_avrcp_player_setting_res(avrcp_ct_playersetting_t *player_setting_res)
+{
+       BT_INFO("Set Property Response [%d]", player_setting_res->accepted);
+}
+
+void _bt_avrcp_ctrl_event_handler(int oal_event, gpointer event_data)
+{
+       BT_INFO("+");
+       bluetooth_device_address_t* bd_addr;
+
+       switch(oal_event) {
+       case OAL_EVENT_AVRCP_CTRL_CONNECTING:
+       case OAL_EVENT_AVRCP_CTRL_CONNECTED: {
+               BT_INFO("AVRCP Controller Profile connected..");
+               bd_addr= (bluetooth_device_address_t*)event_data;
+               __bt_handle_avrcp_target_connected_state(bd_addr);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_DISCONNECTING:
+       case OAL_EVENT_AVRCP_CTRL_DISCONNECTED: {
+               BT_INFO("AVRCP Controller Profile dissconnected..");
+               bd_addr= (bluetooth_device_address_t*)event_data;
+               __bt_handle_avrcp_target_disconnected_state(bd_addr);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_EQUALIZER_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_REPEAT_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_SHUFFLE_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_SCAN_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_PLAY_STATUS_CHANGED: {
+               avrcp_ct_property_value_t* property_val;
+               property_val = (avrcp_ct_property_value_t*)event_data;
+               __bt_handle_avrcp_target_player_property(property_val->value, oal_event);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_PLAY_POSITION_STATUS: {
+               avrcp_ct_play_position_t* play_position;
+               play_position = (avrcp_ct_play_position_t*)event_data;
+               __bt_handle_avrcp_target_player_property(play_position->song_pos, oal_event);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_TRACK_INFO_CHANGED: {
+               BT_INFO("AVRCP Controller Track Info Changed event..");
+               avrcp_ct_media_metadata_attr_t* metadata;
+
+               metadata = (avrcp_ct_media_metadata_attr_t* )event_data;
+               __bt_handle_avrcp_track_info_changed(metadata);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_TRACK_INFO: {
+               BT_INFO("AVRCP Controller Track Info event..");
+               avrcp_ct_media_metadata_attr_t* metadata;
+
+               metadata = (avrcp_ct_media_metadata_attr_t* )event_data;
+               __bt_handle_avrcp_track_info(metadata);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_PASS_CMD_RES: {
+               BT_INFO("AVRCP Controller Pass Command Res");
+               avrcp_ct_pass_cmd_t *pass_cmd;
+
+               pass_cmd = (avrcp_ct_pass_cmd_t *)event_data;
+               __bt_handle_avrcp_pass_cmd_res(pass_cmd);
+               break;
+       }
+       case OAL_EVENT_AVRCP_CTRL_PLAYER_SETTING_RES: {
+               BT_INFO("AVRCP Player setting response");
+               avrcp_ct_playersetting_t *player_setting_res;
+
+               player_setting_res = (avrcp_ct_playersetting_t *)event_data;
+               __bt_handle_avrcp_player_setting_res(player_setting_res);
+               break;
+       }
+       default:
+               BT_INFO("Invalid Event = %d", oal_event);
+               break;
+       }
+
+       BT_INFO("-");
+}
index 29b49bb..3858117 100644 (file)
@@ -37,6 +37,7 @@
 #include "bt-service-core-device.h"
 #include "bt-service-a2dp-src.h"
 #include "bt-service-a2dp-sink.h"
+#include "bt-service-avrcp-ctrl.h"
 #include "bt-service-hf.h"
 
 #ifdef TIZEN_SUPPORT_DUAL_HF
@@ -396,6 +397,8 @@ static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_de
                result = _bt_a2dp_connect_remote_sink(address);
                 break;
         case BT_AVRCP:
+               result = _bt_avrcp_connect_remote_target(address);
+               break;
         case BT_AUDIO_A2DP_SOURCE:
                return _bt_a2dp_connect_remote_source(address);
                break;
@@ -433,6 +436,8 @@ static int __bt_process_audio_profile_disconnect(bt_audio_type_t type, bluetooth
                result = _bt_a2dp_disconnect_remote_sink(address);
                 break;
         case BT_AVRCP:
+               result = _bt_avrcp_disconnect_remote_target(address);
+               break;
         case BT_AUDIO_A2DP_SOURCE:
                return _bt_a2dp_disconnect_remote_source(address);
                break;
@@ -517,6 +522,17 @@ int _bt_audio_initialize(bt_service_module_t module)
                        _bt_service_register_event_handler_callback(module, __bt_audio_event_handler);
                        break;
                }
+               case BT_AVRCP_CTRL_MODULE:
+               {
+                       status = avrcp_ct_enable();
+                       if (status != OAL_STATUS_SUCCESS) {
+                               BT_ERR( "Failed to initialize Bluetooth AVRCP Controller Profile, status: %d", status);
+                                       return BLUETOOTH_ERROR_INTERNAL;
+                       }
+                       /* Register Avrcp Controller event handler */
+                       _bt_service_register_event_handler_callback(module, _bt_avrcp_ctrl_event_handler);
+                       break;
+               }
                default:
                        BT_ERR("Not Supported: Module [%d]", module);
                        return BLUETOOTH_ERROR_NOT_SUPPORT;
index 7158d2c..7190527 100644 (file)
@@ -32,6 +32,7 @@
 #include "bt-service-core-adapter.h"
 #include "bt-service-core-device.h"
 #include "bt-service-audio-common.h"
+#include "bt-service-avrcp-ctrl.h"
 
 #ifdef TIZEN_DPM_ENABLE
 #include "bt-service-dpm.h"
@@ -168,7 +169,8 @@ static gboolean __bt_is_sync_function(int service_function)
                        || service_function == BT_RFCOMM_LISTEN
                        || service_function == BT_HDP_CREATE_APPLICATION
                        || service_function == BT_HDP_DESTROY_APPLICATION
-                       || service_function == BT_HDP_GET_FD)
+                       || service_function == BT_HDP_GET_FD
+                       || service_function == BT_AVRCP_GET_TRACK_INFO)
                return TRUE;
        else
                return FALSE;
@@ -1288,6 +1290,45 @@ int __bt_bluez_request(int function_name,
                 }
                 break;
         }
+       case BT_AVRCP_HANDLE_CONTROL: {
+               int key_code;
+               __bt_service_get_parameters(in_param1, &key_code, sizeof(int));
+               result = _bt_avrcp_control_cmd(key_code);
+               break;
+       }
+        case BT_AVRCP_CONTROL_SET_PROPERTY: {
+                int type;
+                unsigned int value;
+
+                __bt_service_get_parameters(in_param1,
+                              &type, sizeof(int));
+                __bt_service_get_parameters(in_param2,
+                              &value, sizeof(unsigned int));
+
+                result = _bt_avrcp_control_set_property(type, value);
+                break;
+        }
+        case BT_AVRCP_CONTROL_GET_PROPERTY: {
+                int type;
+                unsigned int value;
+
+                __bt_service_get_parameters(in_param1, &type, sizeof(int));
+
+                result = _bt_avrcp_control_get_property(type, &value);
+                g_array_append_vals(*out_param1, &value, sizeof(int));
+
+                break;
+        }
+       case BT_AVRCP_GET_TRACK_INFO: {
+               result = _bt_avrcp_control_get_track_info();
+                /* Save invocation */
+               if (result == BLUETOOTH_ERROR_NONE) {
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       _bt_save_invocation_context(context, result, sender,
+                                       function_name, NULL);
+               }
+               break;
+       }
        case BT_HDP_CREATE_APPLICATION: {
                unsigned short data_type;
                bt_hdp_role_type_t role;
index 0fb447a..08fc5b7 100644 (file)
@@ -42,6 +42,7 @@ _bt_service_event_handler_callback a2dp_source_cb;
 _bt_service_event_handler_callback a2dp_sink_cb;
 _bt_service_event_handler_callback ag_cb;
 _bt_service_event_handler_callback hdp_cb;
+_bt_service_event_handler_callback avrcp_ctrl_cb;
 
 void _bt_service_register_event_handler_callback(
                bt_service_module_t module, _bt_service_event_handler_callback cb)
@@ -83,6 +84,10 @@ void _bt_service_register_event_handler_callback(
                BT_INFO("Register BT_HEALTH_MODULE callback");
                hdp_cb = cb;
                break;
+       case BT_AVRCP_CTRL_MODULE:
+               BT_INFO("Register BT_AVRCP_CTRL_MODULE callback");
+               avrcp_ctrl_cb = cb;
+               break;
        default:
                BT_INFO("Unknown module");
        }
@@ -115,6 +120,10 @@ void _bt_service_unregister_event_handler_callback(bt_service_module_t module)
                BT_INFO("Un-Register BT_HEALTH_MODULE callback");
                hdp_cb = NULL;
                break;
+       case BT_AVRCP_CTRL_MODULE:
+               BT_INFO("Un-Register BT_AVRCP_CTRL_MODULE callback");
+               avrcp_ctrl_cb = NULL;
+               break;
        default:
                BT_INFO("Unknown module");
        }
@@ -221,6 +230,23 @@ void _bt_service_oal_event_receiver(int event_type, gpointer event_data, gsize l
                if (hdp_cb)
                        hdp_cb(event_type, event_data);
                break;
+       case OAL_EVENT_AVRCP_CTRL_CONNECTING:
+       case OAL_EVENT_AVRCP_CTRL_CONNECTED:
+       case OAL_EVENT_AVRCP_CTRL_DISCONNECTING:
+       case OAL_EVENT_AVRCP_CTRL_DISCONNECTED:
+       case OAL_EVENT_AVRCP_CTRL_EQUALIZER_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_REPEAT_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_SHUFFLE_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_SCAN_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_PLAY_POSITION_STATUS:
+       case OAL_EVENT_AVRCP_CTRL_PLAY_STATUS_CHANGED:
+       case OAL_EVENT_AVRCP_CTRL_TRACK_INFO_CHANGED:
+       case OAL_EVENT_AVRCP_CTRL_TRACK_INFO:
+       case OAL_EVENT_AVRCP_CTRL_PASS_CMD_RES:
+       case OAL_EVENT_AVRCP_CTRL_PLAYER_SETTING_RES:
+               if(avrcp_ctrl_cb)
+                       avrcp_ctrl_cb(event_type, event_data);
+               break;
        default:
                BT_ERR("Unhandled Event: %d", event_type);
                break;
index 1e32cb7..34b073a 100644 (file)
@@ -417,7 +417,6 @@ int _bt_send_event(int event_type, int event, GVariant *param)
        if (!g_dbus_connection_send_message(event_conn, msg1, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
                BT_ERR("Error while sending");
        }
-
        g_object_unref(msg1);
 
 #ifdef HPS_FEATURE
diff --git a/bt-service-adaptation/services/include/bt-service-avrcp-ctrl.h b/bt-service-adaptation/services/include/bt-service-avrcp-ctrl.h
new file mode 100644 (file)
index 0000000..edb1487
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 __BT_SERVICE_AVRCP_CONTROLLER_H__
+#define __BT_SERVICE_AVRCP_CONTROLLER_H__
+
+#include "bt-service-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <oal-manager.h>
+
+#include <bt-service-audio-common.h>
+#include <oal-avrcp-ct.h>
+
+typedef struct {
+       const char *title;
+       const char *artist;
+       const char *album;
+       const char *genre;
+       unsigned int total_tracks;
+       unsigned int number;
+       int64_t duration;
+} _bt_avrcp_ct_media_metadata_attr_t;
+
+typedef struct {
+               unsigned int value;
+} _bt_avrcp_ct_property_value_t;
+
+typedef enum {
+       RC_PASS_CMD_PLAY = 0x01,
+       RC_PASS_CMD_PAUSE,
+       RC_PASS_CMD_STOP,
+       RC_PASS_CMD_NEXT,
+       RC_PASS_CMD_PREVIOUS,
+       RC_PASS_CMD_PRESS_FAST_FORWARD,
+       RC_PASS_CMD_RELEASE_FAST_FORWARD,
+       RC_PASS_CMD_PRESS_REWIND,
+       RC_PASS_CMD_RELEASE_REWIND
+} _bt_avrcp_ct_pass_cmd_key_code_t;
+
+int _bt_avrcp_connect_remote_target(bluetooth_device_address_t *address);
+
+int _bt_avrcp_disconnect_remote_target(bluetooth_device_address_t *address);
+
+int _bt_avrcp_control_cmd(int type);
+
+int _bt_avrcp_control_set_property(int type, unsigned int value);
+
+int _bt_avrcp_control_get_property(int type, unsigned int *value);
+
+int _bt_avrcp_control_get_track_info(void);
+
+void _bt_set_control_device_path(const char *path);
+
+void _bt_remove_control_device_path(const char *path);
+
+void _bt_avrcp_ctrl_event_handler(int oal_event, gpointer event_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __BT_SERVICE_AVRCP_CONTROLLER_H__ */
index 7b3b7d2..9e487c0 100644 (file)
@@ -39,8 +39,9 @@ typedef enum {
        BT_A2DP_SINK_MODULE,
        BT_HFP_MODULE,
        BT_AG_MODULE,
-       BT_AUDIO_ALL_MODULE,
        BT_HEALTH_MODULE,
+       BT_AUDIO_ALL_MODULE,
+       BT_AVRCP_CTRL_MODULE
 } bt_service_module_t;
 
 void _bt_service_oal_event_receiver(int event_type, gpointer event_data, gsize len);