[BluezHAL] Implement BlueZ HAL for AVRCP TARGET 77/117177/1
authorAtul Rai <a.rai@samsung.com>
Fri, 10 Feb 2017 13:16:17 +0000 (18:46 +0530)
committerAtul Rai <a.rai@samsung.com>
Fri, 3 Mar 2017 03:38:57 +0000 (09:08 +0530)
This patch adds BlueZ HAL interface implementation for
AVRCP target role.

Change-Id: I695265e98b8702c04aeba7ab2291b9595c50510e
Signed-off-by: Atul Rai <a.rai@samsung.com>
15 files changed:
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/hardware/bt_rc.h
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/src/bt-hal-adapter-dbus-handler.c
bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-avrcp-tg.h [moved from bt-oal/bluez_hal/hardware/src with 76% similarity]
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.c
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.h
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-event-receiver.h
bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.c
bt-oal/bluez_hal/src/bt-hal-internal.h

index e5acfa7..7d19a95 100644 (file)
@@ -15,6 +15,8 @@ SET(SRCS
 ./src/bt-hal-av-dbus-handler.c
 ./src/bt-hal-a2dp-sink.c
 ./src/bt-hal-a2dp-sink-dbus-handler.c
+./src/bt-hal-avrcp-tg.c
+./src/bt-hal-avrcp-tg-dbus-handler.c
 ./src/bt-hal-avrcp-ctrl.c
 ./src/bt-hal-avrcp-ctrl-dbus-handler.c
 ./src/bt-hal-hf.c
index 8bdce1c..dc65cba 100644 (file)
@@ -286,6 +286,11 @@ typedef struct {
     uint8_t   p_str[BTRC_MAX_ATTR_STR_LEN];
 } btrc_br_folder_name_t;
 
+#ifdef TIZEN_BT_HAL
+/** Callback for the target connection state */
+typedef void (* btrc_tg_connection_state_callback) (bt_bdaddr_t *bd_addr, btrc_connection_state_t state);
+#endif
+
 /** Callback for the controller's supported feautres */
 typedef void (* btrc_remote_features_callback)(bt_bdaddr_t *bd_addr,
                                                       btrc_remote_features_t features);
@@ -380,84 +385,13 @@ typedef void (* btrc_search_callback) (uint16_t charset_id,
 typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope,
                 uint8_t* uid, uint16_t  uid_counter, bt_bdaddr_t *bd_addr);
 
-/** Callback for set addressed player response on TG **/
-typedef void (* btrc_set_addressed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr);
-
-/** Callback for set browsed player response on TG **/
-typedef void (* btrc_set_browsed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr);
-
-/** Callback for get folder items on TG
-**  num_attr: specifies the number of attributes requested in p_attr_ids
-*/
-typedef void (* btrc_get_folder_items_callback) (uint8_t scope, uint32_t start_item,
-              uint32_t end_item, uint8_t num_attr, uint32_t *p_attr_ids, bt_bdaddr_t *bd_addr);
-
-/** Callback for changing browsed path on TG **/
-typedef void (* btrc_change_path_callback) (uint8_t direction,
-                uint8_t* folder_uid, bt_bdaddr_t *bd_addr);
-
-/** Callback to fetch the get item attributes of the media item
-**  num_attr: specifies the number of attributes requested in p_attrs
-*/
-typedef void (* btrc_get_item_attr_callback) (uint8_t scope, uint8_t* uid, uint16_t uid_counter,
-                uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr);
-
-/** Callback for play request for the media item indicated by an identifier */
-typedef void (* btrc_play_item_callback) (uint8_t scope,
-                uint16_t uid_counter, uint8_t* uid, bt_bdaddr_t *bd_addr);
-
-/** Callback to fetch total number of items from a folder **/
-typedef void (* btrc_get_total_num_of_items_callback) (uint8_t scope, bt_bdaddr_t *bd_addr);
-
-/** Callback for conducting recursive search on a current browsed path for a specified string */
-typedef void (* btrc_search_callback) (uint16_t charset_id,
-                uint16_t str_len, uint8_t* p_str, bt_bdaddr_t *bd_addr);
-
-/** Callback to add a specified media item indicated by an identifier to now playing queue. */
-typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope,
-                uint8_t* uid, uint16_t  uid_counter, bt_bdaddr_t *bd_addr);
-
-/** Callback for set addressed player response on TG **/
-typedef void (* btrc_set_addressed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr);
-
-/** Callback for set browsed player response on TG **/
-typedef void (* btrc_set_browsed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr);
-
-/** Callback for get folder items on TG
-**  num_attr: specifies the number of attributes requested in p_attr_ids
-*/
-typedef void (* btrc_get_folder_items_callback) (uint8_t scope, uint32_t start_item,
-              uint32_t end_item, uint8_t num_attr, uint32_t *p_attr_ids, bt_bdaddr_t *bd_addr);
-
-/** Callback for changing browsed path on TG **/
-typedef void (* btrc_change_path_callback) (uint8_t direction,
-                uint8_t* folder_uid, bt_bdaddr_t *bd_addr);
-
-/** Callback to fetch the get item attributes of the media item
-**  num_attr: specifies the number of attributes requested in p_attrs
-*/
-typedef void (* btrc_get_item_attr_callback) (uint8_t scope, uint8_t* uid, uint16_t uid_counter,
-                uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr);
-
-/** Callback for play request for the media item indicated by an identifier */
-typedef void (* btrc_play_item_callback) (uint8_t scope,
-                uint16_t uid_counter, uint8_t* uid, bt_bdaddr_t *bd_addr);
-
-/** Callback to fetch total number of items from a folder **/
-typedef void (* btrc_get_total_num_of_items_callback) (uint8_t scope, bt_bdaddr_t *bd_addr);
-
-/** Callback for conducting recursive search on a current browsed path for a specified string */
-typedef void (* btrc_search_callback) (uint16_t charset_id,
-                uint16_t str_len, uint8_t* p_str, bt_bdaddr_t *bd_addr);
-
-/** Callback to add a specified media item indicated by an identifier to now playing queue. */
-typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope,
-                uint8_t* uid, uint16_t  uid_counter, bt_bdaddr_t *bd_addr);
-
 /** BT-RC Target callback structure. */
 typedef struct {
     /** set to sizeof(BtRcCallbacks) */
     size_t      size;
+#ifdef TIZEN_BT_HAL
+    btrc_tg_connection_state_callback          connection_state_cb;
+#endif
     btrc_remote_features_callback               remote_features_cb;
     btrc_get_play_status_callback               get_play_status_cb;
     btrc_list_player_app_attr_callback          list_player_app_attr_cb;
@@ -491,6 +425,14 @@ typedef struct {
      */
     bt_status_t (*init)( btrc_callbacks_t* callbacks );
 
+#ifdef TIZEN_BT_HAL
+    /** connect to AVRCP controller device */
+    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
+
+    /** dis-connect from AVRCP controller device */
+    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
+#endif
+
     /** Respose to GetPlayStatus request. Contains the current
     **  1. Play status
     **  2. Song duration/length
index 3516d9b..526c433 100644 (file)
@@ -415,4 +415,27 @@ struct hal_ev_play_status_changed {
        uint8_t status;
 } __attribute__((packed));
 
+/* AVRCP TG events */
+#ifdef TIZEN_BT_HAL
+#define HAL_EV_AVRCP_TG_CONN_STATE             0xA2
+
+#define HAL_AVRCP_TG_STATE_DISCONNECTED        0x00
+#define HAL_AVRCP_TG_STATE_CONNECTED   0x01
+struct hal_ev_avrcp_tg_conn_state {
+       uint8_t bdaddr[6];
+       uint8_t state;
+} __attribute__((packed));
+#endif /* TIZEN_BT_HAL */
+
+#define HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY              0xA3
+
+#define HAL_AVRCP_TG_PLAYER_PROP_EQUALIZER     0x00
+#define HAL_AVRCP_TG_PLAYER_PROP_REPEAT                0x01
+#define HAL_AVRCP_TG_PLAYER_PROP_SHUFFLE       0x02
+#define HAL_AVRCP_TG_PLAYER_PROP_SCAN          0x03
+struct hal_ev_avrcp_tg_player_property {
+       uint8_t prop_type;
+       uint8_t value;
+} __attribute__((packed));
+
 #endif //_BT_HAL_MSG_H_
index 27539a4..7a19d20 100644 (file)
@@ -1276,7 +1276,7 @@ int _bt_hal_dbus_get_bonded_devices(void)
 
        DBG("+");
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL)
                return  BT_STATUS_FAIL;
 
diff --git a/bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.c
new file mode 100644 (file)
index 0000000..555106b
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@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 <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-internal.h"
+#include "bt-hal-avrcp-tg-dbus-handler.h"
+
+#define HAL_ERROR_INTERNAL "InternalError"
+#define HAL_ERROR_INVALID_PARAM "InvalidParameters"
+#define HAL_ERROR_INVALID_INTERFACE "InvalidInterface"
+
+#define BT_HAL_MEDIA_OBJECT_PATH "/Musicplayer"
+#define BT_HAL_MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
+
+typedef enum {
+       HAL_AVRCP_ERROR_NONE,
+       HAL_AVRCP_ERROR_INTERNAL,
+       HAL_AVRCP_ERROR_INVALID_PARAM,
+       HAL_AVRCP_ERROR_NOT_SUPPORTED,
+       HAL_AVRCP_ERROR_INVALID_INTERFACE
+} hal_avrcp_error_t;
+
+static handle_stack_msg event_cb = NULL;
+
+static guint avrcp_reg_id = 0;
+
+/* Introspection data exposed from bt-service */
+static const gchar hal_avrcp_tg_introspection_xml[] =
+"<node name='/'>"
+" <interface name='org.freedesktop.DBus.Properties'>"
+"     <method name='Set'>"
+"          <arg type='s' name='interface' direction='in'/>"
+"          <arg type='s' name='property' direction='in'/>"
+"          <arg type='v' name='value' direction='in'/>"
+"     </method>"
+" </interface>"
+"</node>";
+
+static const char *__repeat_val_to_str(btrc_player_repeat_val_t repeat_val)
+{
+       switch (repeat_val) {
+       case BTRC_PLAYER_VAL_OFF_REPEAT:
+               return "None";
+       case BTRC_PLAYER_VAL_SINGLE_REPEAT:
+               return "Track";
+       case BTRC_PLAYER_VAL_ALL_REPEAT:
+               return "Playlist";
+       case BTRC_PLAYER_VAL_GROUP_REPEAT:
+               return "Playlist";
+       default:
+               ERR("Invalid repeat value: %d", repeat_val);
+               return "";
+       }
+}
+
+#if 0
+static const char *__shuffle_val_to_str(btrc_player_shuffle_val_t shuffle_val)
+{
+       switch (shuffle_val) {
+       case BTRC_PLAYER_VAL_OFF_SHUFFLE:
+               return "off";
+       case BTRC_PLAYER_VAL_ALL_SHUFFLE:
+               return "alltracks";
+       case BTRC_PLAYER_VAL_GROUP_SHUFFLE:
+               return "group";
+       default:
+               ERR("Invalid shuffle value: %d", shuffle_val);
+               return "";
+       }
+}
+#endif
+
+static const char *__play_status_to_str(btrc_play_status_t play_status)
+{
+       switch (play_status) {
+       case BTRC_PLAYSTATE_STOPPED:
+               return "stopped";
+       case BTRC_PLAYSTATE_PLAYING:
+               return "playing";
+       case BTRC_PLAYSTATE_PAUSED:
+               return "paused";
+       case BTRC_PLAYSTATE_FWD_SEEK:
+               return "forward-seek";
+       case BTRC_PLAYSTATE_REV_SEEK:
+               return "reverse-seek";
+       case BTRC_PLAYSTATE_ERROR:
+               return "error";
+       default:
+               ERR("Invalid play status: %d", play_status);
+               return "";
+       }
+}
+
+static GQuark __hal_avrcp_error_quark(void)
+{
+       static GQuark quark = 0;
+
+       if (!quark)
+               quark = g_quark_from_static_string("bt-avrcp");
+
+       return quark;
+}
+
+static GError *__hal_avrcp_set_error(hal_avrcp_error_t error)
+{
+       ERR("error[%d]\n", error);
+
+       switch (error) {
+       case HAL_AVRCP_ERROR_INVALID_PARAM:
+               return g_error_new(__hal_avrcp_error_quark(),
+                               error, HAL_ERROR_INVALID_PARAM);
+       case HAL_AVRCP_ERROR_INVALID_INTERFACE:
+               return g_error_new(__hal_avrcp_error_quark(),
+                               error, HAL_ERROR_INVALID_INTERFACE);
+       case HAL_AVRCP_ERROR_INTERNAL:
+       default:
+               return g_error_new(__hal_avrcp_error_quark(),
+                               error, HAL_ERROR_INTERNAL);
+       }
+}
+
+static void __hal_avrcp_agent_method(GDBusConnection *connection,
+               const gchar *sender,
+               const gchar *object_path,
+               const gchar *interface_name,
+               const gchar *method_name,
+               GVariant *parameters,
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
+{
+       int ret = HAL_AVRCP_ERROR_NONE;
+       GError *err = NULL;
+       gboolean shuffle_status;
+       gchar *interface = NULL;
+       gchar *property = NULL;
+       gchar *loop_status = NULL;
+       GVariant *value = NULL;
+
+       DBG("+");
+       INFO("method %s", method_name);
+       INFO("object_path %s", object_path);
+
+       if (g_strcmp0(method_name, "Set") == 0) {
+               g_variant_get(parameters, "(&s&sv)",
+                               &interface, &property, &value);
+
+               if (g_strcmp0(interface, BT_HAL_MEDIA_PLAYER_INTERFACE) != 0) {
+                       ret = HAL_AVRCP_ERROR_INVALID_INTERFACE;
+                       goto fail;
+               }
+       }
+
+       if (value == NULL) {
+               ERR("value is NULL");
+               ret = HAL_AVRCP_ERROR_INVALID_PARAM;
+               goto fail;
+       }
+
+       DBG("Property: %s\n", property);
+       if (g_strcmp0(property, "Shuffle") == 0) {
+               struct hal_ev_avrcp_tg_player_property ev;
+
+               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) {
+                       ERR("Error");
+                       ret = HAL_AVRCP_ERROR_INVALID_PARAM;
+                       goto fail;
+               }
+
+               /* Prepare to send AVRCP player property event */
+               memset(&ev, 0, sizeof(ev));
+               shuffle_status = g_variant_get_boolean(value);
+               DBG("Value: %s\n", shuffle_status ? "TRUE" : "FALSE");
+
+               ev.prop_type = HAL_AVRCP_TG_PLAYER_PROP_SHUFFLE;
+               if (shuffle_status)
+                       ev.value = BTRC_PLAYER_VAL_ALL_SHUFFLE;
+               else
+                       ev.value = BTRC_PLAYER_VAL_OFF_SHUFFLE;
+
+               if (!event_cb)
+                       ERR("AVRCP target DBUS handler callback not registered");
+               else
+                       event_cb(HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY, (void *)&ev, sizeof(ev));
+       } else if (g_strcmp0(property, "LoopStatus") == 0) {
+               struct hal_ev_avrcp_tg_player_property ev;
+
+               if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
+                       ERR("Error");
+                       ret = HAL_AVRCP_ERROR_INVALID_PARAM;
+                       goto fail;
+               }
+
+               loop_status = (gchar *)g_variant_get_string(value, NULL);
+               DBG("Value: %s\n", loop_status);
+
+               /* Prepare to send AVRCP player property event */
+               memset(&ev, 0, sizeof(ev));
+               ev.prop_type = HAL_AVRCP_TG_PLAYER_PROP_REPEAT;
+               if (g_strcmp0(loop_status, "Track") == 0)
+                       ev.value = BTRC_PLAYER_VAL_SINGLE_REPEAT;
+               else if (g_strcmp0(loop_status, "Playlist") == 0)
+                       ev.value = BTRC_PLAYER_VAL_ALL_REPEAT;
+               else
+                       ev.value = BTRC_PLAYER_VAL_OFF_REPEAT;
+
+               if (!event_cb)
+                       ERR("AVRCP target DBUS handler callback not registered");
+               else
+                       event_cb(HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY, (void *)&ev, sizeof(ev));
+
+       }
+
+       DBG("-");
+       return;
+
+fail:
+       if (value)
+               g_variant_unref(value);
+       err = __hal_avrcp_set_error(ret);
+       g_dbus_method_invocation_return_gerror(invocation, err);
+       g_clear_error(&err);
+}
+
+static const GDBusInterfaceVTable method_table = {
+       __hal_avrcp_agent_method,
+       NULL,
+       NULL,
+};
+
+static GDBusNodeInfo *__hal_avrcp_create_method_node_info
+                               (const gchar *introspection_data)
+{
+       GError *err = NULL;
+       GDBusNodeInfo *node_info = NULL;
+
+       if (introspection_data == NULL)
+               return NULL;
+
+       node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
+
+       if (err) {
+               ERR("Unable to create node: %s", err->message);
+               g_clear_error(&err);
+       }
+
+       return node_info;
+}
+
+static void __bt_hal_avrcp_unregister_object_path(void)
+{
+       GDBusConnection *conn;
+
+       conn = _bt_get_system_gconn();
+       if (conn == NULL) {
+               ERR("conn == NULL, return");
+               return;
+       }
+
+       if (avrcp_reg_id > 0) {
+               g_dbus_connection_unregister_object(conn, avrcp_reg_id);
+               avrcp_reg_id = 0;
+       }
+}
+
+bt_status_t _bt_hal_dbus_handler_register_media_player(void)
+{
+       GDBusConnection *conn;
+       gchar *adapter_path;
+       gchar *path;
+       GDBusNodeInfo *node_info;
+       GDBusProxy *proxy;
+       GVariantBuilder *builder;
+       GVariant *ret;
+       GError *error = NULL;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       node_info = __hal_avrcp_create_method_node_info(
+                       hal_avrcp_tg_introspection_xml);
+       if (node_info == NULL) {
+               ERR("__hal_avrcp_create_method_node_info failed");
+               return BT_STATUS_FAIL;
+       }
+
+       avrcp_reg_id = g_dbus_connection_register_object(conn,
+                       BT_HAL_MEDIA_OBJECT_PATH,
+                       node_info->interfaces[0],
+                       &method_table,
+                       NULL, NULL, &error);
+       g_dbus_node_info_unref(node_info);
+
+       if (avrcp_reg_id == 0) {
+               ERR("Failed to register: %s", error->message);
+               g_clear_error(&error);
+               return BT_STATUS_FAIL;
+       }
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (!adapter_path) {
+               ERR("Could not get adapter path");
+               return BT_STATUS_FAIL;
+       }
+
+       proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_MEDIA_INTERFACE, NULL, &error);
+       g_free(adapter_path);
+       if (proxy == NULL) {
+               ERR("Unable to create proxy");
+               if (error) {
+                       ERR("Error: %s", error->message);
+                       g_clear_error(&error);
+               }
+
+               return BT_STATUS_FAIL;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       g_variant_builder_add(builder, "{sv}", "LoopStatus",
+                       g_variant_new("s", __repeat_val_to_str(BTRC_PLAYER_VAL_OFF_REPEAT)));
+       g_variant_builder_add(builder, "{sv}", "Shuffle", g_variant_new("b", FALSE));
+       g_variant_builder_add(builder, "{sv}", "PlaybackStatus",
+                       g_variant_new("s", __play_status_to_str(BTRC_PLAYSTATE_STOPPED)));
+       g_variant_builder_add(builder, "{sv}", "Position", g_variant_new("u", 0));
+
+       path = g_strdup(BT_HAL_MEDIA_OBJECT_PATH);
+       ret = g_dbus_proxy_call_sync(proxy, "RegisterPlayer",
+                       g_variant_new("(oa{sv})", path, builder),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       g_variant_builder_unref(builder);
+       g_object_unref(proxy);
+       g_free(path);
+       if (ret == NULL) {
+               ERR("Call RegisterPlayer Failed");
+               if (error) {
+                       ERR("errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_unref(ret);
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_unregister_media_player(void)
+{
+       GDBusConnection *conn;
+       GDBusProxy *proxy;
+       gchar *adapter_path;
+       GVariant *ret;
+       GError *error = NULL;
+       gchar *path;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (adapter_path == NULL) {
+               result = BT_STATUS_FAIL;
+               goto FAIL;
+       }
+
+       conn = _bt_get_system_gconn();
+       if (conn == NULL) {
+               ERR("conn is NULL");
+               g_free(adapter_path);
+               result = BT_STATUS_FAIL;
+               goto FAIL;
+       }
+
+       proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_MEDIA_INTERFACE, NULL, &error);
+       g_free(adapter_path);
+       if (proxy == NULL) {
+               ERR("Unable to create proxy");
+               if (error) {
+                       ERR("Error: %s", error->message);
+                       g_clear_error(&error);
+               }
+               result = BT_STATUS_FAIL;
+               goto FAIL;
+       }
+
+       path = g_strdup(BT_HAL_MEDIA_OBJECT_PATH);
+       DBG("path is [%s]", path);
+       ret = g_dbus_proxy_call_sync(proxy, "UnregisterPlayer",
+                       g_variant_new("(o)", path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       g_free(path);
+       g_object_unref(proxy);
+       if (ret == NULL) {
+               ERR("UnregisterPlayer failed");
+               if (error) {
+                       ERR("D-Bus API failure: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(ret);
+
+FAIL:
+       __bt_hal_avrcp_unregister_object_path();
+
+       DBG("-");
+       return result;
+}
+
+#ifdef TIZEN_BT_HAL
+static void __bt_hal_avrcp_tg_connect_cb(
+               GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+       struct hal_ev_avrcp_tg_conn_state ev;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+       GVariant *reply = NULL;
+       GError *g_error = NULL;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("AVRCP Target Connect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       DBG("Address: %s", address);
+
+       /*
+        * If result is success, Remote device connected event will be triggered
+        * automatically from stack, so return from here.
+        */
+       if (result == BT_STATUS_SUCCESS)
+               goto done;
+
+       /* Prepare to send AVRCP Target connection state event */
+       memset(&ev, 0, sizeof(ev));
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+       ev.state = HAL_AVRCP_TG_STATE_DISCONNECTED;
+       if (!event_cb)
+               ERR("AVRCP target DBUS handler callback not registered");
+       else
+               event_cb(HAL_EV_AVRCP_TG_CONN_STATE, (void *)&ev, sizeof(ev));
+done:
+       g_free(address);
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_connect(bt_bdaddr_t *bd_addr)
+{
+       GDBusConnection *conn;
+       char *address;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_connect_profile(address, AVRCP_CTRL_UUID,
+                       __bt_hal_avrcp_tg_connect_cb, address);
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile(AVRCP Controller) Error");
+               return BT_STATUS_FAIL;
+       }
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_avrcp_tg_disconnect_cb(
+               GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+       struct hal_ev_avrcp_tg_conn_state ev;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+       GError *g_error = NULL;
+       GVariant *reply = NULL;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("AVRCP Target Disconnect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       /*
+        * If result is success, Remote device disconnected event will be triggered
+        * automatically from stack, so return from here.
+        */
+       if (BT_STATUS_FAIL != result) {
+               DBG("AVRCP TG Disconnected for Device: %s", address);
+               g_free(address);
+               return;
+       }
+
+       DBG("AVRCP TG Disconnect failed for Device: %s", address);
+       /* Prepare to send AVRCP Target disconnection state event */
+       memset(&ev, 0, sizeof(ev));
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+       ev.state = HAL_AVRCP_TG_STATE_CONNECTED;
+       if (!event_cb)
+               ERR("AVRCP Target DBUS handler callback not registered");
+       else
+               event_cb(HAL_EV_AVRCP_TG_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       g_free(address);
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_disconnect(bt_bdaddr_t *bd_addr)
+{
+       GDBusConnection *conn;
+       char *address;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_disconnect_profile(address, AVRCP_TARGET_UUID,
+                       __bt_avrcp_tg_disconnect_cb, address);
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile(AVRCP Target) Error");
+               return BT_STATUS_FAIL;
+       }
+
+       return BT_STATUS_SUCCESS;
+}
+#endif
+
+static gboolean __hal_media_emit_property_changed(GDBusConnection *connection,
+               const char *path, const char *interface, const char *name,
+               const GVariant *variant)
+{
+       GVariantBuilder *builder = NULL;
+       GVariantBuilder *invalid_builder = NULL;
+       GError *error = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       g_variant_builder_add(builder, "{sv}", name, variant);
+
+       invalid_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       g_dbus_connection_emit_signal(connection, NULL, path,
+                               DBUS_INTERFACE_PROPERTIES,
+                               "PropertiesChanged",
+                               g_variant_new("(sa{sv}as)",
+                               interface, builder, invalid_builder),
+                               &error);
+       g_variant_builder_unref(builder);
+       g_variant_builder_unref(invalid_builder);
+       if (error) {
+               ERR("Could not Emit PropertiesChanged Signal: errCode[%x], message[%s]",
+                       error->code, error->message);
+               g_clear_error(&error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_play_status_changed(btrc_play_status_t play_status)
+{
+       GDBusConnection *conn;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       if (!__hal_media_emit_property_changed(conn, BT_HAL_MEDIA_OBJECT_PATH,
+                       BT_HAL_MEDIA_PLAYER_INTERFACE, "PlaybackStatus",
+                       g_variant_new_string(__play_status_to_str(play_status)))) {
+               ERR("Error sending the PropertyChanged signal");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_play_pos_changed(uint32_t song_pos)
+{
+       GDBusConnection *conn;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       if (!__hal_media_emit_property_changed(conn, BT_HAL_MEDIA_OBJECT_PATH,
+                       BT_HAL_MEDIA_PLAYER_INTERFACE, "Position",
+                       g_variant_new_uint32(song_pos))) {
+               ERR("Error sending the PropertyChanged signal");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_app_setting_changed(btrc_player_settings_t *player_setting)
+{
+       GDBusConnection *conn;
+       char *property_name = NULL;
+       GVariant *variant;
+       int i;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       for (i = 0; i < player_setting->num_attr; i++) {
+               property_name = NULL;
+               variant = NULL;
+
+               switch (player_setting->attr_ids[i]) {
+               case BTRC_PLAYER_ATTR_REPEAT:
+                       property_name = "LoopStatus";
+                       variant = g_variant_new_string(
+                                       __repeat_val_to_str(player_setting->attr_values[i]));
+                       break;
+               case BTRC_PLAYER_ATTR_SHUFFLE:
+                       property_name = "Shuffle";
+                       if (BTRC_PLAYER_VAL_OFF_SHUFFLE == player_setting->attr_values[i])
+                               variant = g_variant_new_boolean(FALSE);
+                       else
+                               variant = g_variant_new_boolean(TRUE);
+                       break;
+               case BTRC_PLAYER_ATTR_SCAN:
+               case BTRC_PLAYER_ATTR_EQUALIZER:
+               default:
+                       ERR("Unsupported attr type: %d", player_setting->attr_ids[i]);
+               }
+
+               if (!property_name)
+                       continue;
+
+               if (!__hal_media_emit_property_changed(conn, BT_HAL_MEDIA_OBJECT_PATH,
+                                       BT_HAL_MEDIA_PLAYER_INTERFACE, property_name, variant)) {
+                       ERR("Error sending the PropertyChanged signal");
+                       return BT_STATUS_FAIL;
+               }
+       }
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_set_track_info(
+               uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+{
+       GDBusConnection *conn;
+       GError *error = NULL;
+       GVariantBuilder *invalid_builder = NULL;
+       GVariantBuilder *builder = NULL;
+       GVariantBuilder *inner_builder = NULL;
+       char *interface = BT_HAL_MEDIA_PLAYER_INTERFACE;
+       gboolean ret;
+       int i;
+
+       DBG("+");
+
+       if (!p_attrs) {
+               ERR("p_attrs is NULL");
+               return BT_STATUS_FAIL;
+       }
+
+       conn = _bt_get_system_gconn();;
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       invalid_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       for (i = 0; i < num_attr; i++) {
+               switch (p_attrs[i].attr_id) {
+               case BTRC_MEDIA_ATTR_ID_TITLE:
+                       INFO("Title: %s", p_attrs[i].text);
+                       g_variant_builder_add(inner_builder, "{sv}",
+                                       "xesam:title", g_variant_new_string((const char *)p_attrs[i].text));
+                       break;
+               case BTRC_MEDIA_ATTR_ID_ARTIST: {
+                       GVariant *children[1];
+
+                       INFO("Artist: %s", p_attrs[i].text);
+                       children[0] = g_variant_new_string((const char *)p_attrs[i].text);
+                       g_variant_builder_add(inner_builder, "{sv}", "xesam:artist",
+                                       g_variant_new_array(G_VARIANT_TYPE_STRING, children, 1));
+                       break;
+               }
+               case BTRC_MEDIA_ATTR_ID_ALBUM:
+                       INFO("Album: %s", p_attrs[i].text);
+                       g_variant_builder_add(inner_builder, "{sv}",
+                                       "xesam:album", g_variant_new_string((const char *)p_attrs[i].text));
+                       break;
+               case BTRC_MEDIA_ATTR_ID_TRACK_NUM: {
+                       uint32_t cur_track = 0;
+
+                       sscanf((char *)p_attrs[i].text, "%u", &cur_track);
+                       INFO("Current track: %u", cur_track);
+                       g_variant_builder_add(inner_builder, "{sv}",
+                                       "xesam:trackNumber", g_variant_new_int32(cur_track));
+                       break;
+               }
+               case BTRC_MEDIA_ATTR_ID_NUM_TRACKS: {
+                       uint32_t num_tracks = 0;
+
+                       sscanf((char *)p_attrs[i].text, "%u", &num_tracks);
+                       INFO("Total tracks: %u", num_tracks);
+                       g_variant_builder_add(inner_builder, "{sv}",
+                                       "xesam:totalTracks", g_variant_new_int32(num_tracks));
+                       break;
+               }
+               case BTRC_MEDIA_ATTR_ID_GENRE: {
+                       GVariant *children[1];
+
+                       INFO("Genre: %s", p_attrs[i].text);
+                       children[0] = g_variant_new_string((const char *)p_attrs[i].text);
+                       g_variant_builder_add(inner_builder, "{sv}", "xesam:genre",
+                                       g_variant_new_array(G_VARIANT_TYPE_STRING, children, 1));
+                       break;
+               }
+               case BTRC_MEDIA_ATTR_ID_PLAYING_TIME: {
+                       uint32_t duration = 0;
+
+                       sscanf((char *)p_attrs[i].text, "%u", &duration);
+                       INFO("Song duration: %u", duration);
+                       g_variant_builder_add(inner_builder, "{sv}",
+                                       "mpris:length", g_variant_new_int64(duration));
+                       break;
+               }
+               default:
+                       INFO("Unknown attribute Id: %d", p_attrs[i].attr_id);
+               }
+       }
+
+       g_variant_builder_add(builder, "{sv}",
+                       "Metadata", g_variant_new("a{sv}", inner_builder));
+       ret = g_dbus_connection_emit_signal(conn, NULL, BT_HAL_MEDIA_OBJECT_PATH,
+                       DBUS_INTERFACE_PROPERTIES,
+                       "PropertiesChanged",
+                       g_variant_new("(sa{sv}as)",
+                               interface, builder, invalid_builder),
+                       &error);
+       g_variant_builder_unref(inner_builder);
+       g_variant_builder_unref(builder);
+       g_variant_builder_unref(invalid_builder);
+       if (!ret) {
+               if (error != NULL) {
+                       ERR("D-Bus API failure: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
+
+/* To send stack event to hal-avrcp-tg handler */
+void _bt_hal_register_avrcp_tg_dbus_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+/* To send stack event to hal-avrcp-tg handler */
+void _bt_hal_unregister_avrcp_tg_dbus_handler_cb()
+{
+       event_cb = NULL;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-avrcp-tg-dbus-handler.h
new file mode 100644 (file)
index 0000000..8f19153
--- /dev/null
@@ -0,0 +1,55 @@
+/* Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@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_HAL_AVRCP_TG_DBUS_HANDLER_H_
+#define _BT_HAL_AVRCP_TG_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_avrcp_tg_dbus_handler_cb(handle_stack_msg cb);
+void _bt_hal_unregister_avrcp_tg_dbus_handler_cb();
+
+#ifdef TIZEN_BT_HAL
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_connect(bt_bdaddr_t *bd_addr);
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_disconnect(bt_bdaddr_t *bd_addr);
+#endif
+bt_status_t _bt_hal_dbus_handler_register_media_player(void);
+bt_status_t _bt_hal_dbus_handler_unregister_media_player(void);
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_play_status_changed(btrc_play_status_t play_status);
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_play_pos_changed(uint32_t song_pos);
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_app_setting_changed(btrc_player_settings_t *player_setting);
+bt_status_t _bt_hal_dbus_handler_avrcp_tg_set_track_info(uint8_t num_attr, btrc_element_attr_val_t *p_attrs);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_AVRCP_TG_DBUS_HANDLER_H_ */
diff --git a/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c b/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c
new file mode 100644 (file)
index 0000000..225205d
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Atul Kumar Rai <a.rai@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 <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include "bt-hal-event-receiver.h"
+#include "bt-hal-avrcp-tg-dbus-handler.h"
+
+static const btrc_callbacks_t *bt_hal_avrcp_tg_cbacks;
+
+static bool interface_ready(void)
+{
+       return bt_hal_avrcp_tg_cbacks != NULL;
+}
+
+bt_status_t get_play_status_rsp(bt_bdaddr_t *bd_addr, btrc_play_status_t play_status,
+                       uint32_t song_len, uint32_t song_pos)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t list_player_app_attr_rsp(bt_bdaddr_t *bd_addr, int num_attr,
+                       btrc_player_attr_t *p_attrs)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t list_player_app_value_rsp(bt_bdaddr_t *bd_addr, int num_val, uint8_t *p_vals)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_player_app_value_rsp(bt_bdaddr_t *bd_addr, btrc_player_settings_t *p_vals)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_player_app_attr_text_rsp(bt_bdaddr_t *bd_addr, int num_attr,
+               btrc_player_setting_text_t *p_attrs)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_player_app_value_text_rsp(bt_bdaddr_t *bd_addr, int num_val,
+               btrc_player_setting_text_t *p_vals)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_element_attr_rsp(bt_bdaddr_t *bd_addr, uint8_t num_attr,
+               btrc_element_attr_val_t *p_attrs)
+{
+       if (num_attr > 0 && !p_attrs)
+               return BT_STATUS_PARM_INVALID;
+
+       return _bt_hal_dbus_handler_avrcp_tg_set_track_info(num_attr, p_attrs);
+}
+
+bt_status_t set_player_app_value_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+gboolean __fetch_track_info(gpointer data)
+{
+       if (bt_hal_avrcp_tg_cbacks->get_element_attr_cb) {
+               uint8_t num_attr;
+               btrc_media_attr_t attrs[] = {
+                       BTRC_MEDIA_ATTR_TITLE, BTRC_MEDIA_ATTR_ARTIST,
+                       BTRC_MEDIA_ATTR_ALBUM, BTRC_MEDIA_ATTR_TRACK_NUM,
+                       BTRC_MEDIA_ATTR_NUM_TRACKS, BTRC_MEDIA_ATTR_GENRE,
+                       BTRC_MEDIA_ATTR_PLAYING_TIME};
+
+               num_attr = sizeof(attrs) / sizeof(btrc_media_attr_t);
+
+               bt_hal_avrcp_tg_cbacks->get_element_attr_cb(num_attr, attrs, NULL);
+       }
+
+       return FALSE;
+}
+
+bt_status_t register_notification_rsp(btrc_event_id_t event_id,
+               btrc_notification_type_t type,
+               btrc_register_notification_t *p_param)
+{
+       if (BTRC_NOTIFICATION_TYPE_INTERIM == type)
+               return BT_STATUS_SUCCESS;
+
+       switch (event_id) {
+       case BTRC_EVT_PLAY_STATUS_CHANGED:
+               _bt_hal_dbus_handler_avrcp_tg_play_status_changed(p_param->play_status);
+               break;
+       case BTRC_EVT_TRACK_CHANGE:
+               g_idle_add(__fetch_track_info, NULL);
+               break;
+       case BTRC_EVT_PLAY_POS_CHANGED:
+               _bt_hal_dbus_handler_avrcp_tg_play_pos_changed(p_param->song_pos);
+               break;
+       case BTRC_EVT_APP_SETTINGS_CHANGED:
+               _bt_hal_dbus_handler_avrcp_tg_app_setting_changed(&(p_param->player_setting));
+               break;
+       default:
+               ERR("Unknown event Id: %d", event_id);
+       }
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t set_volume(uint8_t volume)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t set_addressed_player_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t set_browsed_player_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
+               uint32_t num_items, uint16_t charset_id, uint8_t folder_depth,
+               btrc_br_folder_name_t *p_folders)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_folder_items_list_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
+               uint16_t uid_counter, uint8_t num_items, btrc_folder_items_t *p_items)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t change_path_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
+               uint32_t num_items)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_item_attr_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
+               uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t play_item_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t get_total_num_of_items_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
+               uint32_t uid_counter, uint32_t num_items)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t search_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, uint32_t uid_counter,
+               uint32_t num_items)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+bt_status_t add_to_now_playing_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
+{
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static gboolean __bt_avrcp_register_notifications(gpointer user_data)
+{
+       bt_bdaddr_t *bdaddr = user_data;
+
+       if (!bt_hal_avrcp_tg_cbacks->register_notification_cb)
+               return FALSE;
+
+       bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_PLAY_STATUS_CHANGED, 0, bdaddr);
+       bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_TRACK_CHANGE, 0, bdaddr);
+       bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_PLAY_POS_CHANGED, 1, bdaddr);
+       bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_APP_SETTINGS_CHANGED, 0, bdaddr);
+
+       return FALSE;
+}
+
+static void __handle_player_property(void *buf, uint16_t len)
+{
+       btrc_player_settings_t player_setting;
+       struct hal_ev_avrcp_tg_player_property *ev = buf;
+
+       if (!bt_hal_avrcp_tg_cbacks->set_player_app_value_cb)
+               return;
+
+       memset(&player_setting, 0, sizeof(btrc_player_settings_t));
+       player_setting.num_attr = 1;
+
+       switch (ev->prop_type) {
+       case HAL_AVRCP_TG_PLAYER_PROP_REPEAT:
+               player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_REPEAT;
+               player_setting.attr_values[0] = ev->value;
+               break;
+       case HAL_AVRCP_TG_PLAYER_PROP_SHUFFLE:
+               player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SHUFFLE;
+               player_setting.attr_values[0] = ev->value;
+               break;
+       case HAL_AVRCP_TG_PLAYER_PROP_SCAN:
+               player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SCAN;
+               player_setting.attr_values[0] = ev->value;
+               break;
+       case HAL_AVRCP_TG_PLAYER_PROP_EQUALIZER:
+               player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_EQUALIZER;
+               player_setting.attr_values[0] = ev->value;
+               break;
+       default:
+               INFO("Player property not handled: %d", ev->prop_type);
+               return;
+       }
+
+       bt_hal_avrcp_tg_cbacks->set_player_app_value_cb(&player_setting, NULL);
+}
+
+static void __bt_hal_handle_avrcp_tg_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+
+       switch (message) {
+#ifdef TIZEN_BT_HAL
+       case HAL_EV_AVRCP_TG_CONN_STATE: {
+               struct hal_ev_avrcp_tg_conn_state *ev = buf;
+
+               if (!bt_hal_avrcp_tg_cbacks->connection_state_cb)
+                       break;
+
+               bt_hal_avrcp_tg_cbacks->connection_state_cb(
+                               (bt_bdaddr_t *)ev->bdaddr, ev->state);
+               /*
+                * To retrieve various player properties, callbacks are invoked from bluedroid to
+                * upper layers (in our case OAL). But in case of BlueZ, these properties are
+                * cached in stack and replied from within. For this, BlueZ relies on property
+                * changed signals from upper layer, to keep its cache updated. To handle the above
+                * case in BlueZ HAL, we register notifications (internal to HAL) and send property
+                * changed signals to bluez on receiving notifications from upper layer (OAL).
+                */
+               if (HAL_AVRCP_TG_STATE_CONNECTED == ev->state)
+                       g_idle_add(__bt_avrcp_register_notifications, ev->bdaddr);
+               break;
+       }
+#endif
+       case HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY:
+               __handle_player_property(buf, len);
+               break;
+       default:
+               ERR("Unknown event: 0x%.2X", message);
+       }
+
+       DBG("-");
+}
+
+#ifdef TIZEN_BT_HAL
+bt_status_t hal_avrcp_tg_connect(bt_bdaddr_t *rem_addr)
+{
+       return _bt_hal_dbus_handler_avrcp_tg_connect(rem_addr);
+}
+
+bt_status_t hal_avrcp_tg_disconnect(bt_bdaddr_t *rem_addr)
+{
+       return _bt_hal_dbus_handler_avrcp_tg_disconnect(rem_addr);
+}
+#endif
+
+void _bt_hal_avrcp_tg_register_media_player(void)
+{
+       int ret;
+
+       DBG("+");
+
+       if (!interface_ready()) {
+               INFO("AVRCP target not enabled");
+               return;
+       }
+
+       /* Register AVRCP Media player */
+       ret = _bt_hal_dbus_handler_register_media_player();
+       if (BT_STATUS_SUCCESS != ret)
+               ERR("_bt_hal_dbus_handler_register_media_player failed");
+
+       DBG("-");
+}
+
+static bt_status_t init(btrc_callbacks_t *callbacks)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_DONE;
+
+       if (!callbacks)
+               return BT_STATUS_PARM_INVALID;
+
+       /* Register AVRCP event callback */
+       _bt_hal_register_avrcp_tg_dbus_handler_cb(
+                       __bt_hal_handle_avrcp_tg_events);
+       _bt_hal_register_avrcp_tg_event_handler_cb(
+                       __bt_hal_handle_avrcp_tg_events);
+
+       bt_hal_avrcp_tg_cbacks = callbacks;
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       /* Un-register AVRCP Media player */
+       _bt_hal_dbus_handler_unregister_media_player();
+
+       /* Un-register AVRCP event callback */
+       _bt_hal_unregister_avrcp_tg_dbus_handler_cb();
+       _bt_hal_unregister_avrcp_tg_event_handler_cb();
+
+       bt_hal_avrcp_tg_cbacks = NULL;
+}
+
+static btrc_interface_t avrcp_tg_if = {
+       .size = sizeof(avrcp_tg_if),
+       .init = init,
+#ifdef TIZEN_BT_HAL
+       .connect = hal_avrcp_tg_connect,
+       .disconnect = hal_avrcp_tg_disconnect,
+#endif
+       .get_play_status_rsp = get_play_status_rsp,
+       .list_player_app_attr_rsp = list_player_app_attr_rsp,
+       .list_player_app_value_rsp = list_player_app_value_rsp,
+       .get_player_app_attr_text_rsp = get_player_app_attr_text_rsp,
+       .get_player_app_value_text_rsp = get_player_app_value_text_rsp,
+       .get_element_attr_rsp = get_element_attr_rsp,
+       .set_player_app_value_rsp = set_player_app_value_rsp,
+       .register_notification_rsp = register_notification_rsp,
+       .set_volume = set_volume,
+       .set_addressed_player_rsp = set_addressed_player_rsp,
+       .set_browsed_player_rsp = set_browsed_player_rsp,
+       .get_folder_items_list_rsp = get_folder_items_list_rsp,
+       .change_path_rsp = change_path_rsp,
+       .get_item_attr_rsp = get_item_attr_rsp,
+       .play_item_rsp = play_item_rsp,
+       .get_total_num_of_items_rsp = get_total_num_of_items_rsp,
+       .search_rsp = search_rsp,
+       .add_to_now_playing_rsp = add_to_now_playing_rsp,
+       .cleanup = cleanup
+};
+
+btrc_interface_t *bt_get_avrcp_tg_interface(void)
+{
+       return &avrcp_tg_if;
+}
similarity index 76%
rename from bt-oal/bluez_hal/hardware/src
rename to bt-oal/bluez_hal/src/bt-hal-avrcp-tg.h
index fd1103b..1a34ae3 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact:  Anupam Roy <anupam.r@samsung.com>
+ * Contact:  Atul Kumar Rai <a.rai@samsung.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef __BT_HAL_HF_SRC_H__
-#define __BT_HAL_HF_SRC_H__
+#ifndef __BT_HAL_AVRCP_TG_H__
+#define __BT_HAL_AVRCP_TG_H__
 
 #include <stdint.h>
 #include <glib.h>
@@ -28,6 +28,7 @@
 #include <dlog.h>
 #include <stdio.h>
 
-bthf_interface_t *bt_get_hf_interface(void);
+void _bt_hal_avrcp_tg_register_media_player(void);
+btrc_interface_t *bt_get_avrcp_tg_interface(void);
 
-#endif //__BT_HAL_HF_SRC_H__
+#endif //__BT_HAL_AVRCP_TG_H__
index b5f014c..bd94537 100644 (file)
@@ -38,6 +38,7 @@
 #include <bt-hal-hf.h>
 #include <bt-hal-hdp.h>
 #include <bt-hal-a2dp-sink.h>
+#include <bt-hal-avrcp-tg.h>
 #include <bt-hal-avrcp-ctrl.h>
 
 #define enum_prop_to_hal(prop, hal_prop, type) do { \
@@ -227,7 +228,7 @@ static const void *get_profile_interface(const char *profile_id)
                return bt_get_av_interface();
 
        if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
-               return NULL;
+               return bt_get_avrcp_tg_interface();
 
        if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_ID))
                return bt_get_hf_interface();
@@ -406,6 +407,9 @@ static void __bt_hal_handle_adapter_state_changed(void *buf, uint16_t len)
 
        if (bt_hal_cbacks->adapter_state_changed_cb)
                bt_hal_cbacks->adapter_state_changed_cb(ev->state);
+
+       if (HAL_POWER_ON == ev->state)
+               _bt_hal_avrcp_tg_register_media_player();
 }
 
 static void __bt_adapter_props_to_hal(bt_property_t *send_props, struct hal_property *prop,
index 3b86e1e..f92bcaf 100644 (file)
@@ -58,9 +58,9 @@ static char *avrcp_control_path = NULL;
 
 static GDBusConnection *system_conn;
 static GDBusConnection *session_conn;
-static GDBusProxy *manager_proxy;
-static GDBusProxy *adapter_proxy;
-static GDBusProxy *profile_gproxy;
+static GDBusProxy *manager_gproxy = NULL;
+static GDBusProxy *adapter_gproxy = NULL;
+static GDBusProxy *profile_gproxy = NULL;
 
 static GDBusProxy *adapter_properties_proxy;
 static GDBusProxy *avrcp_ctrl_proxy;
@@ -127,6 +127,8 @@ static GDBusProxy *__bt_init_manager_proxy(void)
 {
        GDBusProxy *proxy;
 
+       DBG("+");
+
        if (system_conn == NULL) {
                system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
                if (system_conn == NULL)
@@ -140,8 +142,9 @@ static GDBusProxy *__bt_init_manager_proxy(void)
        if (proxy == NULL)
                return NULL;
 
-       manager_proxy = proxy;
+       manager_gproxy = proxy;
 
+       DBG("-");
        return proxy;
 }
 
@@ -157,11 +160,11 @@ static GDBusProxy *__bt_init_adapter_proxy(void)
                        return  NULL;
        }
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL)
                return  NULL;
 
-       adapter_path = _bt_get_adapter_path();
+       adapter_path = _bt_hal_get_adapter_path();
        if (adapter_path == NULL)
                return  NULL;
 
@@ -174,7 +177,7 @@ static GDBusProxy *__bt_init_adapter_proxy(void)
        if (proxy == NULL)
                return NULL;
 
-       adapter_proxy = proxy;
+       adapter_gproxy = proxy;
 
        return proxy;
 }
@@ -191,11 +194,11 @@ static GDBusProxy *__bt_init_adapter_properties_proxy(void)
                        return  NULL;
        }
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL)
                return  NULL;
 
-       adapter_path = _bt_get_adapter_path();
+       adapter_path = _bt_hal_get_adapter_path();
        if (adapter_path == NULL)
                return   NULL;
 
@@ -285,7 +288,7 @@ static GDBusProxy *__bt_init_avrcp_ctrl_proxy(bt_bdaddr_t *bd_addr)
                }
        }
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL) {
                return  NULL;
        }
@@ -325,29 +328,31 @@ GDBusConnection *_bt_get_system_gconn(void)
        return (system_conn) ? system_conn : __bt_init_system_gconn();
 }
 
-GDBusProxy *_bt_get_manager_proxy(void)
+GDBusProxy *_bt_hal_get_manager_proxy(void)
 {
-       if (manager_proxy) {
-               const gchar *path =  g_dbus_proxy_get_object_path(manager_proxy);
+       DBG("+");
+       if (manager_gproxy) {
+               const gchar *path =  g_dbus_proxy_get_object_path(manager_gproxy);
                if (path == NULL) {
                        ERR("Already proxy released hence creating new proxy");
                        return  __bt_init_manager_proxy();
                }
-               return manager_proxy;
+               return manager_gproxy;
        }
+       DBG("-");
        return  __bt_init_manager_proxy();
 }
 
 GDBusProxy *_bt_get_adapter_proxy(void)
 {
-       if (adapter_proxy) {
-               const char *path =  g_dbus_proxy_get_object_path(adapter_proxy);
+       if (adapter_gproxy) {
+               const char *path =  g_dbus_proxy_get_object_path(adapter_gproxy);
                if (path == NULL) {
                        ERR("Already proxy released hence creating new proxy");
                        return  __bt_init_adapter_proxy();
                }
 
-               return adapter_proxy;
+               return adapter_gproxy;
        }
        return  __bt_init_adapter_proxy();
 
@@ -473,7 +478,7 @@ static char *__bt_extract_adapter_path(GVariantIter *iter)
        return NULL;
 }
 
-char *_bt_get_adapter_path(void)
+char *_bt_hal_get_adapter_path(void)
 {
        GDBusConnection *conn;
        GDBusProxy *manager_proxy;
@@ -481,11 +486,12 @@ char *_bt_get_adapter_path(void)
        GVariantIter *iter = NULL;
        char *adapter_path = NULL;
 
+       DBG("+");
        conn = _bt_get_system_gconn();
        if (conn == NULL)
                return  NULL;
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL)
                return NULL;
 
@@ -506,19 +512,20 @@ char *_bt_get_adapter_path(void)
        adapter_path = __bt_extract_adapter_path(iter);
        g_variant_iter_free(iter);
        g_variant_unref(result);
+       DBG("-");
        return adapter_path;
 }
 
 void _bt_deinit_bluez_proxy(void)
 {
-       if (manager_proxy) {
-               g_object_unref(manager_proxy);
-               manager_proxy = NULL;
+       if (manager_gproxy) {
+               g_object_unref(manager_gproxy);
+               manager_gproxy = NULL;
        }
 
-       if (adapter_proxy) {
-               g_object_unref(adapter_proxy);
-               adapter_proxy = NULL;
+       if (adapter_gproxy) {
+               g_object_unref(adapter_gproxy);
+               adapter_gproxy = NULL;
        }
        if (adapter_properties_proxy) {
                g_object_unref(adapter_properties_proxy);
@@ -783,7 +790,7 @@ char *_bt_get_device_object_path(char *address)
        if (conn == NULL)
                return NULL;
 
-       manager_proxy = _bt_get_manager_proxy();
+       manager_proxy = _bt_hal_get_manager_proxy();
        if (manager_proxy == NULL)
                return  NULL;
 
index 757bb1d..347421a 100644 (file)
@@ -403,11 +403,11 @@ typedef int (*bt_hal_new_connection_cb) (const char *path, int fd, bt_bdaddr_t *
 GDBusProxy *_bt_get_adapter_proxy(void);
 GDBusProxy *_bt_get_adapter_properties_proxy(void);
 GDBusConnection *_bt_get_system_gconn(void);
-GDBusProxy *_bt_get_manager_proxy(void);
+GDBusProxy *_bt_hal_get_manager_proxy(void);
 GDBusProxy *_bt_get_profile_proxy(void);
 GDBusProxy *_bt_get_avrcp_ctrl_proxy(bt_bdaddr_t *bd_addr);
 GDBusProxy *_bt_get_avrcp_ctrl_properties_proxy(bt_bdaddr_t *bd_addr);
-char *_bt_get_adapter_path(void);
+char *_bt_hal_get_adapter_path(void);
 
 char *_bt_get_device_object_path(char *address);
 void _bt_convert_device_path_to_address(const char *device_path, char *device_address);
index 3bfea7d..40ace13 100644 (file)
@@ -54,6 +54,7 @@ static handle_stack_msg av_event_cb = NULL;
 static handle_stack_msg a2dp_sink_event_cb = NULL;
 static handle_stack_msg hf_event_cb = NULL;
 static handle_stack_msg avrcp_ctrl_event_cb = NULL;
+static handle_stack_msg avrcp_tg_event_cb = NULL;
 static guint event_id;
 
 /* Forward declarations */
@@ -524,6 +525,54 @@ static gboolean __bt_hal_parse_device_properties(GVariant *item)
        return TRUE;
 }
 
+static void __bt_hal_handle_avrcp_tg_events(GVariant *msg, const char *path)
+{
+       int state;
+       GVariantIter value_iter;
+       char *property = NULL;
+       char *address;
+       GVariant *val = NULL;
+       GVariant *child = NULL;
+
+       g_variant_iter_init(&value_iter, msg);
+       while ((child = g_variant_iter_next_value(&value_iter))) {
+               g_variant_get(child, "{sv}", &property, &val);
+               INFO("Property %s", property);
+               if (strcasecmp(property, "Connected") == 0) {
+                       struct hal_ev_avrcp_tg_conn_state ev;
+
+                       gboolean connected = FALSE;
+
+                       g_variant_get(val, "b", &connected);
+
+                       state = connected ? HAL_AVRCP_TG_STATE_CONNECTED :
+                               HAL_AVRCP_TG_STATE_DISCONNECTED;
+
+                       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+                       _bt_convert_device_path_to_address(path, address);
+
+                       DBG("connected: %d", connected);
+                       DBG("address: %s", address);
+
+                       /* Prepare to send AVRCP Target connection state event */
+                       memset(&ev, 0, sizeof(ev));
+                       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+                       ev.state = state;
+                       if (!avrcp_tg_event_cb)
+                               ERR("AVRCP target DBUS handler callback not registered");
+                       else
+                               avrcp_tg_event_cb(HAL_EV_AVRCP_TG_CONN_STATE, (void *)&ev, sizeof(ev));
+                       g_free(address);
+               }
+               g_free(property);
+               g_variant_unref(child);
+               g_variant_unref(val);
+       }
+
+       DBG("-");
+}
+
 static void __bt_hal_handle_property_changed_event(GVariant *msg, const char *object_path)
 {
        char *interface_name = NULL;
@@ -542,7 +591,8 @@ static void __bt_hal_handle_property_changed_event(GVariant *msg, const char *ob
                /* TODO: Handle event */
        } else if (strcasecmp(interface_name, BT_HAL_MEDIA_CONTROL_INTERFACE) == 0) {
                DBG("Event: Property Changed: Interface: BT_HAL_MEDIA_CONTROL_INTERFACE");
-               /* TODO: Handle event */
+               /* Handle AVRCP target event */
+               __bt_hal_handle_avrcp_tg_events(val, object_path);
        } else if (strcasecmp(interface_name, BT_HAL_PLAYER_CONTROL_INTERFACE) == 0) {
                DBG("Event: Property Changed: Interface: BT_HAL_PLAYER_CONTROL_INTERFACE");
                __bt_hal_handle_avrcp_ctrl_events(val, NULL, object_path);
@@ -1930,3 +1980,14 @@ static void __bt_hal_send_hf_audio_connection_state_event(gboolean connected,
        else
                hf_event_cb(HAL_EV_HANDSFREE_AUDIO_STATE, &ev, sizeof(ev));
 }
+
+/* AVRCP target Role(Remote:AVRCP Controller) Events */
+void _bt_hal_register_avrcp_tg_event_handler_cb(handle_stack_msg cb)
+{
+       avrcp_tg_event_cb = cb;
+}
+
+void _bt_hal_unregister_avrcp_tg_event_handler_cb()
+{
+       avrcp_tg_event_cb = NULL;
+}
\ No newline at end of file
index b81ca39..203ef8f 100644 (file)
@@ -68,6 +68,10 @@ handle_stack_msg _bt_hal_get_stack_message_handler(void);
 
 int __bt_insert_hal_properties(void *buf, uint8_t type, uint16_t len, const void *val);
 
+/* AVRCP Target Role Events */
+void _bt_hal_register_avrcp_tg_event_handler_cb(handle_stack_msg cb);
+void _bt_hal_unregister_avrcp_tg_event_handler_cb(void);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 15a8ca9..abf97af 100644 (file)
@@ -657,7 +657,7 @@ static GDBusProxy *__get_health_device_proxy(char *address)
 
        DBG("+");
 
-       adapter_path = _bt_get_adapter_path();
+       adapter_path = _bt_hal_get_adapter_path();
        if (!adapter_path) {
                ERR("Could not get adapter path");
                return NULL;
index a2e8048..757d5b3 100644 (file)
@@ -66,6 +66,7 @@ typedef enum {
 #define HID_UUID                "00001124-0000-1000-8000-00805f9b34fb"
 #define A2DP_SINK_UUID          "0000110b-0000-1000-8000-00805f9b34fb"
 #define A2DP_SOURCE_UUID        "0000110a-0000-1000-8000-00805f9b34fb"
+#define AVRCP_CTRL_UUID       "0000110e-0000-1000-8000-00805f9b34fb"
 #define AVRCP_TARGET_UUID       "0000110c-0000-1000-8000-00805f9b34fb"
 #define HFP_HF_UUID             "0000111e-0000-1000-8000-00805f9b34fb"